diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 60ce43eba..df3c30034 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -744,23 +744,6 @@ static int handle_encryptable(const struct fstab_rec* rec) } } -static std::string extract_by_name_prefix(struct fstab* fstab) { - // We assume that there's an entry for the /misc mount point in the - // fstab file and use that to get the device file by-name prefix. - // The device needs not to have an actual /misc partition. - // e.g., - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ - struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); - if (fstab_entry == nullptr) { - LERROR << "/misc mount point not found in fstab"; - return ""; - } - std::string full_path(fstab_entry->blk_device); - size_t end_slash = full_path.find_last_of("/"); - return full_path.substr(0, end_slash + 1); -} - // TODO: add ueventd notifiers if they don't exist. // This is just doing a wait_for_device for maximum of 1s int fs_mgr_test_access(const char *device) { @@ -850,7 +833,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) if (fstab->recs[i].fs_mgr_flags & MF_AVB) { if (!avb_handle) { - avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab)); + avb_handle = FsManagerAvbHandle::Open(*fstab); if (!avb_handle) { LERROR << "Failed to open FsManagerAvbHandle"; return FS_MGR_MNTALL_FAIL; @@ -1060,7 +1043,7 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, if (fstab->recs[i].fs_mgr_flags & MF_AVB) { if (!avb_handle) { - avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab)); + avb_handle = FsManagerAvbHandle::Open(*fstab); if (!avb_handle) { LERROR << "Failed to open FsManagerAvbHandle"; return FS_MGR_DOMNT_FAILED; diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 31babfec2..c21139e5d 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "fs_mgr_avb.h" + #include #include #include @@ -38,9 +40,8 @@ #include #include "fs_mgr.h" -#include "fs_mgr_avb.h" -#include "fs_mgr_avb_ops.h" #include "fs_mgr_priv.h" +#include "fs_mgr_priv_avb_ops.h" #include "fs_mgr_priv_dm_ioctl.h" #include "fs_mgr_priv_sha.h" @@ -457,12 +458,21 @@ static bool get_hashtree_descriptor(const std::string& partition_name, return true; } -FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) { - if (device_file_by_name_prefix.empty()) { - LERROR << "Missing device file by-name prefix"; +FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { + FsManagerAvbOps avb_ops(fstab); + return DoOpen(&avb_ops); +} + +FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) { + if (by_name_symlink_map.empty()) { + LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle"; return nullptr; } + FsManagerAvbOps avb_ops(std::move(by_name_symlink_map)); + return DoOpen(&avb_ops); +} +FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { // Gets the expected hash value of vbmeta images from kernel cmdline. std::unique_ptr avb_verifier = FsManagerAvbVerifier::Create(); if (!avb_verifier) { @@ -476,8 +486,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by return nullptr; } - FsManagerAvbOps avb_ops(device_file_by_name_prefix); - AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify( + AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify( fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_); // Only allow two verify results: diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp index caee4ecb3..8feeb533d 100644 --- a/fs_mgr/fs_mgr_avb_ops.cpp +++ b/fs_mgr/fs_mgr_avb_ops.cpp @@ -22,6 +22,8 @@ * SOFTWARE. */ +#include "fs_mgr_priv_avb_ops.h" + #include #include #include @@ -36,7 +38,6 @@ #include #include "fs_mgr.h" -#include "fs_mgr_avb_ops.h" #include "fs_mgr_priv.h" static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset, @@ -88,11 +89,7 @@ static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNU return AVB_IO_RESULT_OK; } -FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix) - : device_file_by_name_prefix_(device_file_by_name_prefix) { - if (device_file_by_name_prefix_.back() != '/') { - device_file_by_name_prefix_ += '/'; - } +void FsManagerAvbOps::InitializeAvbOps() { // We only need to provide the implementation of read_from_partition() // operation since that's all what is being used by the avb_slot_verify(). // Other I/O operations are only required in bootloader but not in @@ -109,13 +106,31 @@ FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix) avb_ops_.user_data = this; } +FsManagerAvbOps::FsManagerAvbOps(std::map&& by_name_symlink_map) + : by_name_symlink_map_(std::move(by_name_symlink_map)) { + InitializeAvbOps(); +} + +FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) { + // Constructs the by-name symlink map for each fstab record. + // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a => + // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a" + for (int i = 0; i < fstab.num_entries; i++) { + std::string partition_name = basename(fstab.recs[i].blk_device); + by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device; + } + InitializeAvbOps(); +} + AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes, void* buffer, size_t* out_num_read) { - // Appends |partition| to the device_file_by_name_prefix_, e.g., - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ -> - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a - std::string path = device_file_by_name_prefix_ + partition; + const auto iter = by_name_symlink_map_.find(partition); + if (iter == by_name_symlink_map_.end()) { + LERROR << "by-name symlink not found for partition: '" << partition << "'"; + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + std::string path = iter->second; // Ensures the device path (a symlink created by init) is ready to // access. fs_mgr_test_access() will test a few iterations if the @@ -126,7 +141,7 @@ AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t of android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); if (fd < 0) { - PERROR << "Failed to open " << path.c_str(); + PERROR << "Failed to open " << path; return AVB_IO_RESULT_ERROR_IO; } @@ -150,8 +165,7 @@ AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t of // for EOF). ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset)); if (num_read < 0 || (size_t)num_read != num_bytes) { - PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset " - << offset; + PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset; return AVB_IO_RESULT_ERROR_IO; } diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_priv_avb_ops.h similarity index 87% rename from fs_mgr/fs_mgr_avb_ops.h rename to fs_mgr/fs_mgr_priv_avb_ops.h index ec4a8c94e..a6b52e43f 100644 --- a/fs_mgr/fs_mgr_avb_ops.h +++ b/fs_mgr/fs_mgr_priv_avb_ops.h @@ -22,8 +22,11 @@ * SOFTWARE. */ -#ifndef __CORE_FS_MGR_AVB_OPS_H -#define __CORE_FS_MGR_AVB_OPS_H +#ifndef __CORE_FS_MGR_PRIV_AVB_OPS_H +#define __CORE_FS_MGR_PRIV_AVB_OPS_H + +#include +#include #include @@ -43,7 +46,8 @@ // class FsManagerAvbOps { public: - FsManagerAvbOps(const std::string& device_file_by_name_prefix); + FsManagerAvbOps(const fstab& fstab); + FsManagerAvbOps(std::map&& by_name_symlink_map); static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) { return reinterpret_cast(ops->user_data); @@ -56,7 +60,9 @@ class FsManagerAvbOps { AvbSlotVerifyData** out_data); private: + void InitializeAvbOps(); + AvbOps avb_ops_; - std::string device_file_by_name_prefix_; + std::map by_name_symlink_map_; }; -#endif /* __CORE_FS_MGR_AVB_OPS_H */ +#endif /* __CORE_FS_MGR_PRIV_AVB_OPS_H */ diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h index 65ff99417..bbafe1a03 100644 --- a/fs_mgr/include/fs_mgr_avb.h +++ b/fs_mgr/include/fs_mgr_avb.h @@ -17,6 +17,7 @@ #ifndef __CORE_FS_MGR_AVB_H #define __CORE_FS_MGR_AVB_H +#include #include #include @@ -31,9 +32,13 @@ enum FsManagerAvbHandleStatus { kFsManagerAvbHandleErrorVerification = 2, }; +class FsManagerAvbOps; + class FsManagerAvbHandle; using FsManagerAvbUniquePtr = std::unique_ptr; +using ByNameSymlinkMap = std::map; + // Provides a factory method to return a unique_ptr pointing to itself and the // SetUpAvb() function to extract dm-verity parameters from AVB metadata to // load verity table into kernel through ioctl. @@ -49,6 +54,13 @@ class FsManagerAvbHandle { // A typical usage will be: // - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open(); // + // There are two overloaded Open() functions with a single parameter. + // The argument can be a ByNameSymlinkMap describing the mapping from partition + // name to by-name symlink, or a fstab file to which the ByNameSymlinkMap is + // constructed from. e.g., + // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a -> + // - ByNameSymlinkMap["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a" + // // Possible return values: // - nullptr: any error when reading and verifying the metadata, // e.g., I/O error, digest value mismatch, size mismatch, etc. @@ -61,7 +73,8 @@ class FsManagerAvbHandle { // - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata // is verified and can be trusted. // - static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix); + static FsManagerAvbUniquePtr Open(const fstab& fstab); + static FsManagerAvbUniquePtr Open(ByNameSymlinkMap&& by_name_symlink_map); // Sets up dm-verity on the given fstab entry. // The 'wait_for_verity_dev' parameter makes this function wait for the @@ -88,10 +101,10 @@ class FsManagerAvbHandle { } }; - protected: - FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {} - private: + FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {} + static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops); + AvbSlotVerifyData* avb_slot_data_; FsManagerAvbHandleStatus status_; std::string avb_version_; diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp index 2fa790d40..9d2a0d100 100644 --- a/init/init_first_stage.cpp +++ b/init/init_first_stage.cpp @@ -47,18 +47,22 @@ class FirstStageMount { bool InitDevices(); protected: - void InitRequiredDevices(std::set* devices_partition_names); + void InitRequiredDevices(); void InitVerityDevice(const std::string& verity_device); bool MountPartitions(); - virtual bool GetRequiredDevices(std::set* out_devices_partition_names, - bool* out_need_dm_verity) = 0; + virtual coldboot_action_t ColdbootCallback(uevent* uevent); + + // Pure virtual functions. + virtual bool GetRequiredDevices() = 0; virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0; + bool need_dm_verity_; // Device tree fstab entries. std::unique_ptr device_tree_fstab_; // Eligible first stage mount candidates, only allow /system, /vendor and/or /odm. std::vector mount_fstab_recs_; + std::set required_devices_partition_names_; }; class FirstStageMountVBootV1 : public FirstStageMount { @@ -67,27 +71,26 @@ class FirstStageMountVBootV1 : public FirstStageMount { ~FirstStageMountVBootV1() override = default; protected: - bool GetRequiredDevices(std::set* out_devices_partition_names, - bool* out_need_dm_verity) override; + bool GetRequiredDevices() override; bool SetUpDmVerity(fstab_rec* fstab_rec) override; }; class FirstStageMountVBootV2 : public FirstStageMount { public: + friend void SetInitAvbVersionInRecovery(); + FirstStageMountVBootV2(); ~FirstStageMountVBootV2() override = default; - const std::string& by_name_prefix() const { return device_tree_by_name_prefix_; } - protected: - bool GetRequiredDevices(std::set* out_devices_partition_names, - bool* out_need_dm_verity) override; + coldboot_action_t ColdbootCallback(uevent* uevent) override; + bool GetRequiredDevices() override; bool SetUpDmVerity(fstab_rec* fstab_rec) override; bool InitAvbHandle(); std::string device_tree_vbmeta_parts_; - std::string device_tree_by_name_prefix_; FsManagerAvbUniquePtr avb_handle_; + ByNameSymlinkMap by_name_symlink_map_; }; // Static Functions @@ -102,7 +105,8 @@ static bool inline IsRecoveryMode() { // Class Definitions // ----------------- -FirstStageMount::FirstStageMount() : device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) { +FirstStageMount::FirstStageMount() + : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) { if (!device_tree_fstab_) { LOG(ERROR) << "Failed to read fstab from device tree"; return; @@ -136,13 +140,30 @@ bool FirstStageMount::DoFirstStageMount() { } bool FirstStageMount::InitDevices() { - bool need_dm_verity; - std::set devices_partition_names; + if (!GetRequiredDevices()) return false; - // The partition name in devices_partition_names MUST have A/B suffix when A/B is used. - if (!GetRequiredDevices(&devices_partition_names, &need_dm_verity)) return false; + InitRequiredDevices(); - if (need_dm_verity) { + // InitRequiredDevices() will remove found partitions from required_devices_partition_names_. + // So if it isn't empty here, it means some partitions are not found. + if (!required_devices_partition_names_.empty()) { + LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: " + << android::base::Join(required_devices_partition_names_, ", "); + return false; + } else { + return true; + } +} + +// Creates devices with uevent->partition_name matching one in the member variable +// required_devices_partition_names_. Found partitions will then be removed from it +// for the subsequent member function to check which devices are NOT created. +void FirstStageMount::InitRequiredDevices() { + if (required_devices_partition_names_.empty()) { + return; + } + + if (need_dm_verity_) { const std::string dm_path = "/devices/virtual/misc/device-mapper"; device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t { if (uevent->path == dm_path) return COLDBOOT_STOP; @@ -150,58 +171,40 @@ bool FirstStageMount::InitDevices() { }); } - bool success = false; - InitRequiredDevices(&devices_partition_names); - - // InitRequiredDevices() will remove found partitions from devices_partition_names. - // So if it isn't empty here, it means some partitions are not found. - if (!devices_partition_names.empty()) { - LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: " - << android::base::Join(devices_partition_names, ", "); - } else { - success = true; - } + device_init(nullptr, + [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); }); device_close(); - return success; } -// Creates devices with uevent->partition_name matching one in the in/out -// devices_partition_names. Found partitions will then be removed from the -// devices_partition_names for the caller to check which devices are NOT created. -void FirstStageMount::InitRequiredDevices(std::set* devices_partition_names) { - if (devices_partition_names->empty()) { - return; +coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) { + // We need platform devices to create symlinks. + if (uevent->subsystem == "platform") { + return COLDBOOT_CREATE; } - device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t { - // We need platform devices to create symlinks. - if (uevent->subsystem == "platform") { - return COLDBOOT_CREATE; - } - // Ignores everything that is not a block device. - if (uevent->subsystem != "block") { - return COLDBOOT_CONTINUE; - } + // Ignores everything that is not a block device. + if (uevent->subsystem != "block") { + return COLDBOOT_CONTINUE; + } - if (!uevent->partition_name.empty()) { - // Matches partition name to create device nodes. - // Both devices_partition_names and uevent->partition_name have A/B - // suffix when A/B is used. - auto iter = devices_partition_names->find(uevent->partition_name); - if (iter != devices_partition_names->end()) { - LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter; - devices_partition_names->erase(iter); - if (devices_partition_names->empty()) { - return COLDBOOT_STOP; // Found all partitions, stop coldboot. - } else { - return COLDBOOT_CREATE; // Creates this device and continue to find others. - } + if (!uevent->partition_name.empty()) { + // Matches partition name to create device nodes. + // Both required_devices_partition_names_ and uevent->partition_name have A/B + // suffix when A/B is used. + auto iter = required_devices_partition_names_.find(uevent->partition_name); + if (iter != required_devices_partition_names_.end()) { + LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter; + required_devices_partition_names_.erase(iter); + if (required_devices_partition_names_.empty()) { + return COLDBOOT_STOP; // Found all partitions, stop coldboot. + } else { + return COLDBOOT_CREATE; // Creates this device and continue to find others. } } - // Not found a partition or find an unneeded partition, continue to find others. - return COLDBOOT_CONTINUE; - }); + } + // Not found a partition or find an unneeded partition, continue to find others. + return COLDBOOT_CONTINUE; } // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX. @@ -233,10 +236,9 @@ bool FirstStageMount::MountPartitions() { return true; } -bool FirstStageMountVBootV1::GetRequiredDevices(std::set* out_devices_partition_names, - bool* out_need_dm_verity) { +bool FirstStageMountVBootV1::GetRequiredDevices() { std::string verity_loc_device; - *out_need_dm_verity = false; + need_dm_verity_ = false; for (auto fstab_rec : mount_fstab_recs_) { // Don't allow verifyatboot in the first stage. @@ -246,7 +248,7 @@ bool FirstStageMountVBootV1::GetRequiredDevices(std::set* out_devic } // Checks for verified partitions. if (fs_mgr_is_verified(fstab_rec)) { - *out_need_dm_verity = true; + need_dm_verity_ = true; } // Checks if verity metadata is on a separate partition. Note that it is // not partition specific, so there must be only one additional partition @@ -265,11 +267,11 @@ bool FirstStageMountVBootV1::GetRequiredDevices(std::set* out_devic // Includes the partition names of fstab records and verity_loc_device (if any). // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used. for (auto fstab_rec : mount_fstab_recs_) { - out_devices_partition_names->emplace(basename(fstab_rec->blk_device)); + required_devices_partition_names_.emplace(basename(fstab_rec->blk_device)); } if (!verity_loc_device.empty()) { - out_devices_partition_names->emplace(basename(verity_loc_device.c_str())); + required_devices_partition_names_.emplace(basename(verity_loc_device.c_str())); } return true; @@ -292,15 +294,13 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) { } // FirstStageMountVBootV2 constructor. -// Gets the vbmeta configurations from device tree. -// Specifically, the 'parts' and 'by_name_prefix' below. +// Gets the vbmeta partitions from device tree. // /{ // firmware { // android { // vbmeta { // compatible = "android,vbmeta"; // parts = "vbmeta,boot,system,vendor" -// by_name_prefix = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/" // }; // }; // }; @@ -310,31 +310,24 @@ FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) { PLOG(ERROR) << "Failed to read vbmeta/parts from device tree"; return; } - - // TODO: removes by_name_prefix to allow partitions on different block devices. - if (!read_android_dt_file("vbmeta/by_name_prefix", &device_tree_by_name_prefix_)) { - PLOG(ERROR) << "Failed to read vbmeta/by_name_prefix from dt"; - return; - } } -bool FirstStageMountVBootV2::GetRequiredDevices(std::set* out_devices_partition_names, - bool* out_need_dm_verity) { - *out_need_dm_verity = false; +bool FirstStageMountVBootV2::GetRequiredDevices() { + need_dm_verity_ = false; // fstab_rec->blk_device has A/B suffix. for (auto fstab_rec : mount_fstab_recs_) { if (fs_mgr_is_avb(fstab_rec)) { - *out_need_dm_verity = true; + need_dm_verity_ = true; } - out_devices_partition_names->emplace(basename(fstab_rec->blk_device)); + required_devices_partition_names_.emplace(basename(fstab_rec->blk_device)); } // libavb verifies AVB metadata on all verified partitions at once. // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor" // for libavb to verify metadata, even if there is only /vendor in the // above mount_fstab_recs_. - if (*out_need_dm_verity) { + if (need_dm_verity_) { if (device_tree_vbmeta_parts_.empty()) { LOG(ERROR) << "Missing vbmeta parts in device tree"; return false; @@ -342,16 +335,45 @@ bool FirstStageMountVBootV2::GetRequiredDevices(std::set* out_devic std::vector partitions = android::base::Split(device_tree_vbmeta_parts_, ","); std::string ab_suffix = fs_mgr_get_slot_suffix(); for (const auto& partition : partitions) { - // out_devices_partition_names is of type std::set so it's not an issue to emplace - // a partition twice. e.g., /vendor might be in both places: + // required_devices_partition_names_ is of type std::set so it's not an issue + // to emplace a partition twice. e.g., /vendor might be in both places: // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor" // - mount_fstab_recs_: /vendor_a - out_devices_partition_names->emplace(partition + ab_suffix); + required_devices_partition_names_.emplace(partition + ab_suffix); } } return true; } +coldboot_action_t FirstStageMountVBootV2::ColdbootCallback(uevent* uevent) { + // Invokes the parent function to see if any desired partition has been found. + // If yes, record the by-name symlink for creating FsManagerAvbHandle later. + coldboot_action_t parent_callback_ret = FirstStageMount::ColdbootCallback(uevent); + + // Skips the uevent if the parent function returns COLDBOOT_CONTINUE (meaning + // that the uevent was skipped) or there is no uevent->partition_name to + // create the by-name symlink. + if (parent_callback_ret != COLDBOOT_CONTINUE && !uevent->partition_name.empty()) { + // get_block_device_symlinks() will return three symlinks at most, depending on + // the content of uevent. by-name symlink will be at [0] if uevent->partition_name + // is not empty. e.g., + // - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem + // - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1 + // - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1 + std::vector links = get_block_device_symlinks(uevent); + if (!links.empty()) { + auto[it, inserted] = by_name_symlink_map_.emplace(uevent->partition_name, links[0]); + if (!inserted) { + LOG(ERROR) << "Partition '" << uevent->partition_name + << "' already existed in the by-name symlink map with a value of '" + << it->second << "', new value '" << links[0] << "' will be ignored."; + } + } + } + + return parent_callback_ret; +} + bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) { if (fs_mgr_is_avb(fstab_rec)) { if (!InitAvbHandle()) return false; @@ -371,7 +393,14 @@ bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) { bool FirstStageMountVBootV2::InitAvbHandle() { if (avb_handle_) return true; // Returns true if the handle is already initialized. - avb_handle_ = FsManagerAvbHandle::Open(device_tree_by_name_prefix_); + if (by_name_symlink_map_.empty()) { + LOG(ERROR) << "by_name_symlink_map_ is empty"; + return false; + } + + avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_)); + by_name_symlink_map_.clear(); // Removes all elements after the above std::move(). + if (!avb_handle_) { PLOG(ERROR) << "Failed to open FsManagerAvbHandle"; return false; @@ -427,7 +456,8 @@ void SetInitAvbVersionInRecovery() { return; } - FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(avb_first_mount.by_name_prefix()); + FsManagerAvbUniquePtr avb_handle = + FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_)); if (!avb_handle) { PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION"; return;