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" 27a918f9daede277d043e5b3b8443d712c88c949daAlex Deymo#include "update_engine/utils_android.h" 28b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 29b17327ce55e7132da1f64039040df93a8c260fefAlex Deymousing std::string; 30b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 31d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo#ifdef _UE_SIDELOAD 32d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo// When called from update_engine_sideload, we don't attempt to dynamically load 33d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo// the right boot_control HAL, instead we use the only HAL statically linked in 34d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo// via the PRODUCT_STATIC_BOOT_CONTROL_HAL make variable and access the module 35d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo// struct directly. 36d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymoextern const hw_module_t HAL_MODULE_INFO_SYM; 37d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo#endif // _UE_SIDELOAD 38d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo 39b17327ce55e7132da1f64039040df93a8c260fefAlex Deymonamespace chromeos_update_engine { 40b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 41b17327ce55e7132da1f64039040df93a8c260fefAlex Deymonamespace boot_control { 42b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 43b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo// Factory defined in boot_control.h. 44b17327ce55e7132da1f64039040df93a8c260fefAlex Deymostd::unique_ptr<BootControlInterface> CreateBootControl() { 45753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen std::unique_ptr<BootControlAndroid> boot_control(new BootControlAndroid()); 46753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (!boot_control->Init()) { 47753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return nullptr; 48753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 493f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko return brillo::make_unique_ptr(boot_control.release()); 50b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 51b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 52b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} // namespace boot_control 53b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 54753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthenbool BootControlAndroid::Init() { 55753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen const hw_module_t* hw_module; 56753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen int ret; 57753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 58d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo#ifdef _UE_SIDELOAD 59d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo // For update_engine_sideload, we simulate the hw_get_module() by accessing it 60d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo // from the current process directly. 61d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo hw_module = &HAL_MODULE_INFO_SYM; 62d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo ret = 0; 63d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo if (!hw_module || 64d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) { 65d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo ret = -EINVAL; 66d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo } 67d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo#else // !_UE_SIDELOAD 68753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen ret = hw_get_module(BOOT_CONTROL_HARDWARE_MODULE_ID, &hw_module); 69d18829480c833dd9416a3778900cb4ddaad375b2Alex Deymo#endif // _UE_SIDELOAD 70753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (ret != 0) { 71753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(ERROR) << "Error loading boot_control HAL implementation."; 72753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 73753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 74753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 75753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen module_ = reinterpret_cast<boot_control_module_t*>(const_cast<hw_module_t*>(hw_module)); 76753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen module_->init(module_); 77753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 78753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(INFO) << "Loaded boot_control HAL " 79753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << "'" << hw_module->name << "' " 80753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << "version " << (hw_module->module_api_version>>8) << "." 81753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << (hw_module->module_api_version&0xff) << " " 82753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << "authored by '" << hw_module->author << "'."; 83753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return true; 84753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen} 85b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 86b17327ce55e7132da1f64039040df93a8c260fefAlex Deymounsigned int BootControlAndroid::GetNumSlots() const { 87753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return module_->getNumberSlots(module_); 88b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 89b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 90b17327ce55e7132da1f64039040df93a8c260fefAlex DeymoBootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const { 91753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return module_->getCurrentSlot(module_); 92b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 93b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 94b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::GetPartitionDevice(const string& partition_name, 95753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen Slot slot, 96b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo string* device) const { 97753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // We can't use fs_mgr to look up |partition_name| because fstab 98753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // doesn't list every slot partition (it uses the slotselect option 99753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // to mask the suffix). 100753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 101753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // We can however assume that there's an entry for the /misc mount 102753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // point and use that to get the device file for the misc 103753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // partition. This helps us locate the disk that |partition_name| 104753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // resides on. From there we'll assume that a by-name scheme is used 105753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // so we can just replace the trailing "misc" by the given 106753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // |partition_name| and suffix corresponding to |slot|, e.g. 107753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 108753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> 109753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a 110753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // 111753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // If needed, it's possible to relax the by-name assumption in the 112753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // future by trawling /sys/block looking for the appropriate sibling 113753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // of misc and then finding an entry in /dev matching the sysfs 114753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen // entry. 115753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 116a918f9daede277d043e5b3b8443d712c88c949daAlex Deymo base::FilePath misc_device; 117a918f9daede277d043e5b3b8443d712c88c949daAlex Deymo if (!utils::DeviceForMountPoint("/misc", &misc_device)) 118753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 119753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 12012542ace0f43c5afaf1e7112556b71aea8454c79Alex Deymo if (!utils::IsSymlink(misc_device.value().c_str())) { 121753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(ERROR) << "Device file " << misc_device.value() << " for /misc " 12212542ace0f43c5afaf1e7112556b71aea8454c79Alex Deymo << "is not a symlink."; 123753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 124753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 125753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 126753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen const char* suffix = module_->getSuffix(module_, slot); 127753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (suffix == nullptr) { 12831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "boot_control impl returned no suffix for slot " 12931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << SlotName(slot); 130753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 131753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 132753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 133753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen base::FilePath path = misc_device.DirName().Append(partition_name + suffix); 134753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (!base::PathExists(path)) { 135753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen LOG(ERROR) << "Device file " << path.value() << " does not exist."; 136753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 137753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 138753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen 139753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen *device = path.value(); 140753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return true; 141b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 142b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 143b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::IsSlotBootable(Slot slot) const { 144753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen int ret = module_->isSlotBootable(module_, slot); 145753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (ret < 0) { 14631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to determine if slot " << SlotName(slot) 147753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << " is bootable: " << strerror(-ret); 148753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 149753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 150753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return ret == 1; 151b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 152b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 153b17327ce55e7132da1f64039040df93a8c260fefAlex Deymobool BootControlAndroid::MarkSlotUnbootable(Slot slot) { 154753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen int ret = module_->setSlotAsUnbootable(module_, slot); 155753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen if (ret < 0) { 15631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to mark slot " << SlotName(slot) 157753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen << " as bootable: " << strerror(-ret); 158753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return false; 159753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen } 160753fadc8805f662e5af3a66f694207b04fbef8bbDavid Zeuthen return ret == 0; 161b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} 162b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo 16331d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymobool BootControlAndroid::SetActiveBootSlot(Slot slot) { 16431d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo int ret = module_->setActiveBootSlot(module_, slot); 16531d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo if (ret < 0) { 16631d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot) 16731d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo << ": " << strerror(-ret); 16831d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo } 16931d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo return ret == 0; 17031d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo} 17131d95ac85d294b2b1bfa293835013e66c010fbcfAlex Deymo 172aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymobool BootControlAndroid::MarkBootSuccessfulAsync( 173aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo base::Callback<void(bool)> callback) { 174aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo int ret = module_->markBootSuccessful(module_); 175aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo if (ret < 0) { 176aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo LOG(ERROR) << "Unable to mark boot successful: " << strerror(-ret); 177aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo } 1783f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko return brillo::MessageLoop::current()->PostTask( 179aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo FROM_HERE, base::Bind(callback, ret == 0)) != 1803f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::MessageLoop::kTaskIdNull; 181aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo} 182aa26f6240865d43f8cecc97bde7828f9b82bc17dAlex Deymo 183b17327ce55e7132da1f64039040df93a8c260fefAlex Deymo} // namespace chromeos_update_engine 184