1b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// 2b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Copyright (C) 2015 The Android Open Source Project 3b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// 4b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// you may not use this file except in compliance with the License. 6b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// You may obtain a copy of the License at 7b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// 8b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// 10b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Unless required by applicable law or agreed to in writing, software 11b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// See the License for the specific language governing permissions and 14b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// limitations under the License. 15b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// 16b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 171b03f9f983a22fabb8d53e036abf1b192e7d5811Alex Deymo#include "update_engine/boot_control_android.h" 18b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 19aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo#include <base/bind.h> 20753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen#include <base/files/file_util.h> 21aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo#include <base/logging.h> 22753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen#include <base/strings/string_util.h> 233f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/make_unique_ptr.h> 243f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop.h> 25b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 2639910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 27fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo#include "update_engine/utils_android.h" 28b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 29b17327ce55e7132da1f64039040df93a8c260fefAlex Deymousing std::string; 30b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 31cee6ad93d1772be82477fe30407c768160406539Connor O'Brienusing android::hardware::Return; 32cee6ad93d1772be82477fe30407c768160406539Connor O'Brienusing android::hardware::boot::V1_0::BoolResult; 33cee6ad93d1772be82477fe30407c768160406539Connor O'Brienusing android::hardware::boot::V1_0::CommandResult; 34cee6ad93d1772be82477fe30407c768160406539Connor O'Brienusing android::hardware::boot::V1_0::IBootControl; 35cee6ad93d1772be82477fe30407c768160406539Connor O'Brienusing android::hardware::hidl_string; 36cee6ad93d1772be82477fe30407c768160406539Connor O'Brien 37cee6ad93d1772be82477fe30407c768160406539Connor O'Briennamespace { 38cee6ad93d1772be82477fe30407c768160406539Connor O'Brienauto StoreResultCallback(CommandResult* dest) { 39cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return [dest](const CommandResult& result) { *dest = result; }; 40cee6ad93d1772be82477fe30407c768160406539Connor O'Brien} 41cee6ad93d1772be82477fe30407c768160406539Connor O'Brien} // namespace 4244348e01c0c66e6baf1376f0b712ecae26fc5595Alex Deymo 43b17327ce55e7132da1f64039040df93a8c260fefAlex Deymonamespace chromeos_update_engine { 44b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 45b17327ce55e7132da1f64039040df93a8c260fefAlex Deymonamespace boot_control { 46b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 47b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Factory defined in boot_control.h. 48b17327ce55e7132da1f64039040df93a8c260fefAlex Deymostd::unique_ptr<BootControlInterface> CreateBootControl() { 49753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen std::unique_ptr<BootControlAndroid> boot_control(new BootControlAndroid()); 50753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (!boot_control->Init()) { 51753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return nullptr; 52753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 53ce8c8ee8f9df9bea3b5aedf930dfeba5da46031cAlex Vakulenko return std::move(boot_control); 54b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 55b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 56b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} // namespace boot_control 57b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 58753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthenbool BootControlAndroid::Init() { 598da5d2221b422da3d0b971132401e28d8145e9b3Chris Phoenix module_ = IBootControl::getService(); 60cee6ad93d1772be82477fe30407c768160406539Connor O'Brien if (module_ == nullptr) { 61927e00d1e9fd046e81c84ef61d05c347eee408dcSteven Moreland LOG(ERROR) << "Error getting bootctrl HIDL module."; 62753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 63753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 64753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 65927e00d1e9fd046e81c84ef61d05c347eee408dcSteven Moreland LOG(INFO) << "Loaded boot control hidl hal."; 66753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 67753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return true; 68753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen} 69b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 70b17327ce55e7132da1f64039040df93a8c260fefAlex Deymounsigned int BootControlAndroid::GetNumSlots() const { 71cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return module_->getNumberSlots(); 72b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 73b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 74b17327ce55e7132da1f64039040df93a8c260fefAlex DeymoBootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const { 75cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return module_->getCurrentSlot(); 76b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 77b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 78b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::GetPartitionDevice(const string& partition_name, 79753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen Slot slot, 80b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo string* device) const { 81753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // We can't use fs_mgr to look up |partition_name| because fstab 82753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // doesn't list every slot partition (it uses the slotselect option 83753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // to mask the suffix). 84753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 85753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // We can however assume that there's an entry for the /misc mount 86753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // point and use that to get the device file for the misc 87753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // partition. This helps us locate the disk that |partition_name| 88753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // resides on. From there we'll assume that a by-name scheme is used 89753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // so we can just replace the trailing "misc" by the given 90753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // |partition_name| and suffix corresponding to |slot|, e.g. 91753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 92753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> 93753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a 94753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 95753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // If needed, it's possible to relax the by-name assumption in the 96753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // future by trawling /sys/block looking for the appropriate sibling 97753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // of misc and then finding an entry in /dev matching the sysfs 98753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // entry. 99753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 100fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo base::FilePath misc_device; 101fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo if (!utils::DeviceForMountPoint("/misc", &misc_device)) 102753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 103753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 10412542ace0f43c5afaf1e7112556b71aea8454c79Alex Deymo if (!utils::IsSymlink(misc_device.value().c_str())) { 105753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(ERROR) << "Device file " << misc_device.value() << " for /misc " 10612542ace0f43c5afaf1e7112556b71aea8454c79Alex Deymo << "is not a symlink."; 107753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 108753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 109753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 110cee6ad93d1772be82477fe30407c768160406539Connor O'Brien string suffix; 111cee6ad93d1772be82477fe30407c768160406539Connor O'Brien auto store_suffix_cb = [&suffix](hidl_string cb_suffix) { 112cee6ad93d1772be82477fe30407c768160406539Connor O'Brien suffix = cb_suffix.c_str(); 113cee6ad93d1772be82477fe30407c768160406539Connor O'Brien }; 114cee6ad93d1772be82477fe30407c768160406539Connor O'Brien Return<void> ret = module_->getSuffix(slot, store_suffix_cb); 115cee6ad93d1772be82477fe30407c768160406539Connor O'Brien 1167b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong if (!ret.isOk()) { 11731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "boot_control impl returned no suffix for slot " 11831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << SlotName(slot); 119753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 120753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 121753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 122753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen base::FilePath path = misc_device.DirName().Append(partition_name + suffix); 123753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (!base::PathExists(path)) { 124753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(ERROR) << "Device file " << path.value() << " does not exist."; 125753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 126753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 127753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 128753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen *device = path.value(); 129753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return true; 130b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 131b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 132b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::IsSlotBootable(Slot slot) const { 133cee6ad93d1772be82477fe30407c768160406539Connor O'Brien Return<BoolResult> ret = module_->isSlotBootable(slot); 1347b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong if (!ret.isOk()) { 13531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to determine if slot " << SlotName(slot) 136cee6ad93d1772be82477fe30407c768160406539Connor O'Brien << " is bootable: " 1377b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong << ret.description(); 138753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 139753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 140cee6ad93d1772be82477fe30407c768160406539Connor O'Brien if (ret == BoolResult::INVALID_SLOT) { 141cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Invalid slot: " << SlotName(slot); 142cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return false; 143cee6ad93d1772be82477fe30407c768160406539Connor O'Brien } 144cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return ret == BoolResult::TRUE; 145b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 146b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 147b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::MarkSlotUnbootable(Slot slot) { 148cee6ad93d1772be82477fe30407c768160406539Connor O'Brien CommandResult result; 149cee6ad93d1772be82477fe30407c768160406539Connor O'Brien auto ret = module_->setSlotAsUnbootable(slot, StoreResultCallback(&result)); 1507b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong if (!ret.isOk()) { 151cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot " 152cee6ad93d1772be82477fe30407c768160406539Connor O'Brien << SlotName(slot) << ": " 1537b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong << ret.description(); 1549ca8231d34dc134deaf16bcfb112a04cea8ff6d5Connor O'Brien return false; 15529dcbf32a88f1638bb911c86b8e0ea12f84d9364Alex Deymo } 156cee6ad93d1772be82477fe30407c768160406539Connor O'Brien if (!result.success) { 157cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Unable to mark slot " << SlotName(slot) 158cee6ad93d1772be82477fe30407c768160406539Connor O'Brien << " as unbootable: " << result.errMsg.c_str(); 159cee6ad93d1772be82477fe30407c768160406539Connor O'Brien } 160cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return result.success; 161b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 162b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 16331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymobool BootControlAndroid::SetActiveBootSlot(Slot slot) { 164cee6ad93d1772be82477fe30407c768160406539Connor O'Brien CommandResult result; 165cee6ad93d1772be82477fe30407c768160406539Connor O'Brien auto ret = module_->setActiveBootSlot(slot, StoreResultCallback(&result)); 1667b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong if (!ret.isOk()) { 167cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot) 1687b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong << ": " << ret.description(); 169cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return false; 170cee6ad93d1772be82477fe30407c768160406539Connor O'Brien } 171cee6ad93d1772be82477fe30407c768160406539Connor O'Brien if (!result.success) { 17231d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot) 173cee6ad93d1772be82477fe30407c768160406539Connor O'Brien << ": " << result.errMsg.c_str(); 17431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo } 175cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return result.success; 17631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo} 17731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 178aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymobool BootControlAndroid::MarkBootSuccessfulAsync( 179aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo base::Callback<void(bool)> callback) { 180cee6ad93d1772be82477fe30407c768160406539Connor O'Brien CommandResult result; 181cee6ad93d1772be82477fe30407c768160406539Connor O'Brien auto ret = module_->markBootSuccessful(StoreResultCallback(&result)); 1827b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong if (!ret.isOk()) { 183cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Unable to call MarkBootSuccessful: " 1847b514b4f91fb4dadd4b88b0a9213e37a100688b3Yifan Hong << ret.description(); 185cee6ad93d1772be82477fe30407c768160406539Connor O'Brien return false; 186cee6ad93d1772be82477fe30407c768160406539Connor O'Brien } 187cee6ad93d1772be82477fe30407c768160406539Connor O'Brien if (!result.success) { 188cee6ad93d1772be82477fe30407c768160406539Connor O'Brien LOG(ERROR) << "Unable to mark boot successful: " << result.errMsg.c_str(); 189aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo } 1903f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko return brillo::MessageLoop::current()->PostTask( 191cee6ad93d1772be82477fe30407c768160406539Connor O'Brien FROM_HERE, base::Bind(callback, result.success)) != 1923f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::MessageLoop::kTaskIdNull; 193aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo} 194aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo 195b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} // namespace chromeos_update_engine 196