1763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// 2763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// Copyright (C) 2015 The Android Open Source Project 3763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// 4763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// you may not use this file except in compliance with the License. 6763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// You may obtain a copy of the License at 7763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// 8763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// 10763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// Unless required by applicable law or agreed to in writing, software 11763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// See the License for the specific language governing permissions and 14763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// limitations under the License. 15763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// 16763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 171b03f9f983a22fabb8d53e036abf1b192e7d5811Alex Deymo#include "update_engine/boot_control_chromeos.h" 18763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 19763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <string> 20763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 21aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo#include <base/bind.h> 22763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <base/files/file_path.h> 23763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <base/files/file_util.h> 24763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <base/strings/string_util.h> 253f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/make_unique_ptr.h> 26763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <rootdev/rootdev.h> 27763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 28763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoextern "C" { 29763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo#include <vboot/vboot_host.h> 30763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 31763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 3239910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/boot_control.h" 3339910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/subprocess.h" 3439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 35763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 36763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymousing std::string; 37763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 38763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymonamespace { 39763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 40763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoconst char* kChromeOSPartitionNameKernel = "kernel"; 41763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoconst char* kChromeOSPartitionNameRoot = "root"; 42763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoconst char* kAndroidPartitionNameKernel = "boot"; 43763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoconst char* kAndroidPartitionNameRoot = "system"; 44763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 45763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// Returns the currently booted rootfs partition. "/dev/sda3", for example. 46763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymostring GetBootDevice() { 47763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo char boot_path[PATH_MAX]; 48763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // Resolve the boot device path fully, including dereferencing through 49763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // dm-verity. 50763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int ret = rootdev(boot_path, sizeof(boot_path), true, false); 51763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (ret < 0) { 52763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "rootdev failed to find the root device"; 53763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return ""; 54763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 55763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG_IF(WARNING, ret > 0) << "rootdev found a device name with no device node"; 56763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 57763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // This local variable is used to construct the return string and is not 58763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // passed around after use. 59763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return boot_path; 60763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 61763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 62aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo// ExecCallback called when the execution of setgoodkernel finishes. Notifies 63aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo// the caller of MarkBootSuccessfullAsync() by calling |callback| with the 64aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo// result. 65aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymovoid OnMarkBootSuccessfulDone(base::Callback<void(bool)> callback, 66aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo int return_code, 67aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo const string& output) { 68aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo callback.Run(return_code == 0); 69aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo} 70aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo 71763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} // namespace 72763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 73763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymonamespace chromeos_update_engine { 74763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 75b17327ce55e7132da1f64039040df93a8c260fefAlex Deymonamespace boot_control { 76b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 77b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Factory defined in boot_control.h. 78b17327ce55e7132da1f64039040df93a8c260fefAlex Deymostd::unique_ptr<BootControlInterface> CreateBootControl() { 79b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo std::unique_ptr<BootControlChromeOS> boot_control_chromeos( 80b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo new BootControlChromeOS()); 81b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo if (!boot_control_chromeos->Init()) { 82b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo LOG(ERROR) << "Ignoring BootControlChromeOS failure. We won't run updates."; 83b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo } 84ce8c8ee8f9df9bea3b5aedf930dfeba5da46031cAlex Vakulenko return std::move(boot_control_chromeos); 85b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 86b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 87b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} // namespace boot_control 88b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 89763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymobool BootControlChromeOS::Init() { 90763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo string boot_device = GetBootDevice(); 91763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (boot_device.empty()) 92763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 93763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 94763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int partition_num; 95763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (!utils::SplitPartitionName(boot_device, &boot_disk_name_, &partition_num)) 96763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 97763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 98763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // All installed Chrome OS devices have two slots. We don't update removable 99763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // devices, so we will pretend we have only one slot in that case. 100763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (IsRemovableDevice(boot_disk_name_)) { 101763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(INFO) 102763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo << "Booted from a removable device, pretending we have only one slot."; 103763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo num_slots_ = 1; 104763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } else { 105763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // TODO(deymo): Look at the actual number of slots reported in the GPT. 106763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo num_slots_ = 2; 107763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 108763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 109763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // Search through the slots to see which slot has the partition_num we booted 110763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // from. This should map to one of the existing slots, otherwise something is 111763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // very wrong. 112763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo current_slot_ = 0; 113763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo while (current_slot_ < num_slots_ && 114763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo partition_num != 115763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo GetPartitionNumber(kChromeOSPartitionNameRoot, current_slot_)) { 116763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo current_slot_++; 117763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 118763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (current_slot_ >= num_slots_) { 119763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "Couldn't find the slot number corresponding to the " 120763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo "partition " << boot_device 121763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo << ", number of slots: " << num_slots_ 122763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo << ". This device is not updateable."; 123763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo num_slots_ = 1; 124763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo current_slot_ = BootControlInterface::kInvalidSlot; 125763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 126763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 127763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 128763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(INFO) << "Booted from slot " << current_slot_ << " (slot " 12931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << SlotName(current_slot_) << ") of " << num_slots_ 13031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << " slots present on disk " << boot_disk_name_; 131763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return true; 132763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 133763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 134763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymounsigned int BootControlChromeOS::GetNumSlots() const { 135763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return num_slots_; 136763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 137763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 138763e7dbaac735da0ae802933a1015b6b7874bce2Alex DeymoBootControlInterface::Slot BootControlChromeOS::GetCurrentSlot() const { 139763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return current_slot_; 140763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 141763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 142763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymobool BootControlChromeOS::GetPartitionDevice(const string& partition_name, 143763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo unsigned int slot, 144763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo string* device) const { 145763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int partition_num = GetPartitionNumber(partition_name, slot); 146763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (partition_num < 0) 147763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 148763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 149763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo string part_device = utils::MakePartitionName(boot_disk_name_, partition_num); 150763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (part_device.empty()) 151763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 152763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 153763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo *device = part_device; 154763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return true; 155763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 156763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 157763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymobool BootControlChromeOS::IsSlotBootable(Slot slot) const { 158763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int partition_num = GetPartitionNumber(kChromeOSPartitionNameKernel, slot); 159763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (partition_num < 0) 160763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 161763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 162763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo CgptAddParams params; 163763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo memset(¶ms, '\0', sizeof(params)); 164763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.drive_name = const_cast<char*>(boot_disk_name_.c_str()); 165763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.partition = partition_num; 166763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 167763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int retval = CgptGetPartitionDetails(¶ms); 168763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (retval != CGPT_OK) 169763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 170763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 171763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return params.successful || params.tries > 0; 172763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 173763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 174763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymobool BootControlChromeOS::MarkSlotUnbootable(Slot slot) { 17531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(INFO) << "Marking slot " << SlotName(slot) << " unbootable"; 176763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 177763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (slot == current_slot_) { 178763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "Refusing to mark current slot as unbootable."; 179763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 180763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 181763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 182763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int partition_num = GetPartitionNumber(kChromeOSPartitionNameKernel, slot); 183763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (partition_num < 0) 184763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 185763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 186763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo CgptAddParams params; 187763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo memset(¶ms, 0, sizeof(params)); 188763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 189763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.drive_name = const_cast<char*>(boot_disk_name_.c_str()); 190763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.partition = partition_num; 191763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 192763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.successful = false; 193763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.set_successful = true; 194763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 195763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.tries = 0; 196763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo params.set_tries = true; 197763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 198763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int retval = CgptSetAttributes(¶ms); 199763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (retval != CGPT_OK) { 200763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "Marking kernel unbootable failed."; 201763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 202763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 203763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 204763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return true; 205763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 206763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 20731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymobool BootControlChromeOS::SetActiveBootSlot(Slot slot) { 20831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(INFO) << "Marking slot " << SlotName(slot) << " active."; 20931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 21031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo int partition_num = GetPartitionNumber(kChromeOSPartitionNameKernel, slot); 21131d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo if (partition_num < 0) 21231d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo return false; 21331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 21431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo CgptPrioritizeParams prio_params; 21531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo memset(&prio_params, 0, sizeof(prio_params)); 21631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 21731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo prio_params.drive_name = const_cast<char*>(boot_disk_name_.c_str()); 21831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo prio_params.set_partition = partition_num; 21931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 22031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo prio_params.max_priority = 0; 22131d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 22231d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo int retval = CgptPrioritize(&prio_params); 22331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo if (retval != CGPT_OK) { 22431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to set highest priority for slot " << SlotName(slot) 22531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << " (partition " << partition_num << ")."; 22631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo return false; 22731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo } 22831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 22931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo CgptAddParams add_params; 23031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo memset(&add_params, 0, sizeof(add_params)); 23131d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 23231d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo add_params.drive_name = const_cast<char*>(boot_disk_name_.c_str()); 23331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo add_params.partition = partition_num; 23431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 23531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo add_params.tries = 6; 23631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo add_params.set_tries = true; 23731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 23831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo retval = CgptSetAttributes(&add_params); 23931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo if (retval != CGPT_OK) { 24031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to set NumTriesLeft to " << add_params.tries 24131d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << " for slot " << SlotName(slot) << " (partition " 24231d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << partition_num << ")."; 24331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo return false; 24431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo } 24531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 24631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo return true; 24731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo} 24831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 249aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymobool BootControlChromeOS::MarkBootSuccessfulAsync( 250aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo base::Callback<void(bool)> callback) { 251aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo return Subprocess::Get().Exec( 252aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo {"/usr/sbin/chromeos-setgoodkernel"}, 253aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo base::Bind(&OnMarkBootSuccessfulDone, callback)) != 0; 254aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo} 255aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo 256763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// static 257763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymostring BootControlChromeOS::SysfsBlockDevice(const string& device) { 258763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo base::FilePath device_path(device); 259763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (device_path.DirName().value() != "/dev") { 260763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return ""; 261763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 262763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return base::FilePath("/sys/block").Append(device_path.BaseName()).value(); 263763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 264763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 265763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo// static 266763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymobool BootControlChromeOS::IsRemovableDevice(const string& device) { 267763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo string sysfs_block = SysfsBlockDevice(device); 268763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo string removable; 269763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (sysfs_block.empty() || 270763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo !base::ReadFileToString(base::FilePath(sysfs_block).Append("removable"), 271763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo &removable)) { 272763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return false; 273763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 274763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo base::TrimWhitespaceASCII(removable, base::TRIM_ALL, &removable); 275763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return removable == "1"; 276763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 277763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 278763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymoint BootControlChromeOS::GetPartitionNumber( 279763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo const string partition_name, 280763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo BootControlInterface::Slot slot) const { 281763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (slot >= num_slots_) { 282763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "Invalid slot number: " << slot << ", we only have " 283763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo << num_slots_ << " slot(s)"; 284763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return -1; 285763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo } 286763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 287763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // In Chrome OS, the partition numbers are hard-coded: 288763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // KERNEL-A=2, ROOT-A=3, KERNEL-B=4, ROOT-B=4, ... 289763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // To help compatibility between different we accept both lowercase and 290763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // uppercase names in the ChromeOS or Brillo standard names. 291763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo // See http://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format 2920103c36caa2e38e034e0d22185736b9ccfb35c58Alex Vakulenko string partition_lower = base::ToLowerASCII(partition_name); 293763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo int base_part_num = 2 + 2 * slot; 294763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (partition_lower == kChromeOSPartitionNameKernel || 295763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo partition_lower == kAndroidPartitionNameKernel) 296763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return base_part_num + 0; 297763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo if (partition_lower == kChromeOSPartitionNameRoot || 298763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo partition_lower == kAndroidPartitionNameRoot) 299763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return base_part_num + 1; 300763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo LOG(ERROR) << "Unknown Chrome OS partition name \"" << partition_name << "\""; 301763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo return -1; 302763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} 303763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo 304763e7dbaac735da0ae802933a1015b6b7874bce2Alex Deymo} // namespace chromeos_update_engine 305