Loading init/init.cpp +114 −112 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include <fstream> #include <memory> #include <set> #include <vector> #include "action.h" #include "bootchart.h" Loading Loading @@ -700,138 +702,138 @@ static bool early_mount_one(struct fstab_rec* rec) { return true; } /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { // first check if device tree fstab entries are compatible if (!is_dt_fstab_compatible()) { LOG(INFO) << "Early mount skipped (missing/incompatible fstab in device tree)"; return true; // Creates devices with uevent->partition_name matching one in the in/out // partition_names. Note that the partition_names MUST have A/B suffix // when A/B is used. Found partitions will then be removed from the // partition_names for caller to check which devices are NOT created. static void early_device_init(std::set<std::string>* partition_names) { if (partition_names->empty()) { return; } device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t { if (!strncmp(uevent->subsystem, "firmware", 8)) { return COLDBOOT_CONTINUE; } std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> tab( fs_mgr_read_fstab_dt(), fs_mgr_free_fstab); if (!tab) { LOG(ERROR) << "Early mount failed to read fstab from device tree"; return false; // we need platform devices to create symlinks if (!strncmp(uevent->subsystem, "platform", 8)) { return COLDBOOT_CREATE; } // find out fstab records for odm, system and vendor // TODO: add std::map<std::string, fstab_rec*> so all required information about // them can be gathered at once in a single loop fstab_rec* odm_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/odm"); fstab_rec* system_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/system"); fstab_rec* vendor_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/vendor"); if (!odm_rec && !system_rec && !vendor_rec) { // nothing to early mount return true; // Ignore everything that is not a block device if (strncmp(uevent->subsystem, "block", 5)) { return COLDBOOT_CONTINUE; } // don't allow verifyatboot for early mounted partitions if ((odm_rec && fs_mgr_is_verifyatboot(odm_rec)) || (system_rec && fs_mgr_is_verifyatboot(system_rec)) || (vendor_rec && fs_mgr_is_verifyatboot(vendor_rec))) { LOG(ERROR) << "Early mount partitions can't be verified at boot"; return false; if (uevent->partition_name) { // match partition names to create device nodes for partitions // both partition_names and uevent->partition_name have A/B suffix when A/B is used auto iter = partition_names->find(uevent->partition_name); if (iter != partition_names->end()) { LOG(VERBOSE) << "early_mount: found partition: " << *iter; partition_names->erase(iter); if (partition_names->empty()) { return COLDBOOT_STOP; // found all partitions, stop coldboot } else { return COLDBOOT_CREATE; // create this device and continue to find others } } } // Not found a partition or find an unneeded partition, continue to find others return COLDBOOT_CONTINUE; }); } // assume A/B device if we find 'slotselect' in any fstab entry bool is_ab = ((odm_rec && fs_mgr_is_slotselect(odm_rec)) || (system_rec && fs_mgr_is_slotselect(system_rec)) || (vendor_rec && fs_mgr_is_slotselect(vendor_rec))); static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs, std::set<std::string>* out_partitions, bool* out_need_verity) { std::string meta_partition; out_partitions->clear(); *out_need_verity = false; for (auto fstab_rec : early_fstab_recs) { // don't allow verifyatboot for early mounted partitions if (fs_mgr_is_verifyatboot(fstab_rec)) { LOG(ERROR) << "early_mount: partitions can't be verified at boot"; return false; } // check for verified partitions bool need_verity = ((odm_rec && fs_mgr_is_verified(odm_rec)) || (system_rec && fs_mgr_is_verified(system_rec)) || (vendor_rec && fs_mgr_is_verified(vendor_rec))); if (fs_mgr_is_verified(fstab_rec)) { *out_need_verity = true; } // check if verity metadata is on a separate partition and get partition // name from the end of the ->verity_loc path. verity state is not partition // specific, so there must be only 1 additional partition that carries // verity state. std::string meta_partition; if (odm_rec && odm_rec->verity_loc) { meta_partition = basename(odm_rec->verity_loc); } else if (system_rec && system_rec->verity_loc) { meta_partition = basename(system_rec->verity_loc); } else if (vendor_rec && vendor_rec->verity_loc) { meta_partition = basename(vendor_rec->verity_loc); if (fstab_rec->verity_loc) { if (!meta_partition.empty()) { LOG(ERROR) << "early_mount: more than one meta partition found: " << meta_partition << ", " << basename(fstab_rec->verity_loc); return false; } else { meta_partition = basename(fstab_rec->verity_loc); } bool found_odm = !odm_rec; bool found_system = !system_rec; bool found_vendor = !vendor_rec; bool found_meta = meta_partition.empty(); int count_odm = 0, count_vendor = 0, count_system = 0; // create the devices we need.. device_init(nullptr, [&](uevent* uevent) -> coldboot_action_t { if (!strncmp(uevent->subsystem, "firmware", 8)) { return COLDBOOT_CONTINUE; } // we need platform devices to create symlinks if (!strncmp(uevent->subsystem, "platform", 8)) { return COLDBOOT_CREATE; } // Ignore everything that is not a block device if (strncmp(uevent->subsystem, "block", 5)) { return COLDBOOT_CONTINUE; // includes those early mount partitions and meta_partition (if any) // note that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used for (auto fstab_rec : early_fstab_recs) { out_partitions->emplace(basename(fstab_rec->blk_device)); } coldboot_action_t ret; bool create_this_node = false; if (uevent->partition_name) { // prefix match partition names so we create device nodes for // A/B-ed partitions if (!found_odm && !strncmp(uevent->partition_name, "odm", 3)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; // wait twice for A/B-ed partitions count_odm++; if (!is_ab || count_odm == 2) { found_odm = true; if (!meta_partition.empty()) { out_partitions->emplace(std::move(meta_partition)); } create_this_node = true; } else if (!found_system && !strncmp(uevent->partition_name, "system", 6)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; return true; } count_system++; if (!is_ab || count_system == 2) { found_system = true; /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { // first check if device tree fstab entries are compatible if (!is_dt_fstab_compatible()) { LOG(INFO) << "Early mount skipped (missing/incompatible fstab in device tree)"; return true; } create_this_node = true; } else if (!found_vendor && !strncmp(uevent->partition_name, "vendor", 6)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; count_vendor++; if (!is_ab || count_vendor == 2) { found_vendor = true; std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> tab( fs_mgr_read_fstab_dt(), fs_mgr_free_fstab); if (!tab) { LOG(ERROR) << "Early mount failed to read fstab from device tree"; return false; } create_this_node = true; } else if (!found_meta && (meta_partition == uevent->partition_name)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; found_meta = true; create_this_node = true; // find out fstab records for odm, system and vendor std::vector<fstab_rec*> early_fstab_recs; for (auto mount_point : {"/odm", "/system", "/vendor"}) { fstab_rec* fstab_rec = fs_mgr_get_entry_for_mount_point(tab.get(), mount_point); if (fstab_rec != nullptr) { early_fstab_recs.push_back(fstab_rec); } } // if we found all other partitions already, create this // node and stop coldboot. If this is a prefix matched // partition, create device node and continue. For everything // else skip the device node if (found_meta && found_odm && found_system && found_vendor) { ret = COLDBOOT_STOP; } else if (create_this_node) { ret = COLDBOOT_CREATE; } else { ret = COLDBOOT_CONTINUE; // nothing to early mount if (early_fstab_recs.empty()) return true; bool need_verity; std::set<std::string> partition_names; // partition_names MUST have A/B suffix when A/B is used if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity)) { return false; } return ret; }); bool success = false; // create the devices we need.. early_device_init(&partition_names); // early_device_init will remove found partitions from partition_names // So if the partition_names is not empty here, means some partitions // are not found if (!partition_names.empty()) { LOG(ERROR) << "early_mount: partition(s) not found: " << android::base::Join(partition_names, ", "); goto done; } if (need_verity) { // create /dev/device mapper Loading @@ -839,10 +841,10 @@ static bool early_mount() { [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; }); } bool success = true; if (odm_rec && !(success = early_mount_one(odm_rec))) goto done; if (system_rec && !(success = early_mount_one(system_rec))) goto done; if (vendor_rec && !(success = early_mount_one(vendor_rec))) goto done; for (auto fstab_rec : early_fstab_recs) { if (!early_mount_one(fstab_rec)) goto done; } success = true; done: device_close(); Loading Loading
init/init.cpp +114 −112 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include <fstream> #include <memory> #include <set> #include <vector> #include "action.h" #include "bootchart.h" Loading Loading @@ -700,138 +702,138 @@ static bool early_mount_one(struct fstab_rec* rec) { return true; } /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { // first check if device tree fstab entries are compatible if (!is_dt_fstab_compatible()) { LOG(INFO) << "Early mount skipped (missing/incompatible fstab in device tree)"; return true; // Creates devices with uevent->partition_name matching one in the in/out // partition_names. Note that the partition_names MUST have A/B suffix // when A/B is used. Found partitions will then be removed from the // partition_names for caller to check which devices are NOT created. static void early_device_init(std::set<std::string>* partition_names) { if (partition_names->empty()) { return; } device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t { if (!strncmp(uevent->subsystem, "firmware", 8)) { return COLDBOOT_CONTINUE; } std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> tab( fs_mgr_read_fstab_dt(), fs_mgr_free_fstab); if (!tab) { LOG(ERROR) << "Early mount failed to read fstab from device tree"; return false; // we need platform devices to create symlinks if (!strncmp(uevent->subsystem, "platform", 8)) { return COLDBOOT_CREATE; } // find out fstab records for odm, system and vendor // TODO: add std::map<std::string, fstab_rec*> so all required information about // them can be gathered at once in a single loop fstab_rec* odm_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/odm"); fstab_rec* system_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/system"); fstab_rec* vendor_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/vendor"); if (!odm_rec && !system_rec && !vendor_rec) { // nothing to early mount return true; // Ignore everything that is not a block device if (strncmp(uevent->subsystem, "block", 5)) { return COLDBOOT_CONTINUE; } // don't allow verifyatboot for early mounted partitions if ((odm_rec && fs_mgr_is_verifyatboot(odm_rec)) || (system_rec && fs_mgr_is_verifyatboot(system_rec)) || (vendor_rec && fs_mgr_is_verifyatboot(vendor_rec))) { LOG(ERROR) << "Early mount partitions can't be verified at boot"; return false; if (uevent->partition_name) { // match partition names to create device nodes for partitions // both partition_names and uevent->partition_name have A/B suffix when A/B is used auto iter = partition_names->find(uevent->partition_name); if (iter != partition_names->end()) { LOG(VERBOSE) << "early_mount: found partition: " << *iter; partition_names->erase(iter); if (partition_names->empty()) { return COLDBOOT_STOP; // found all partitions, stop coldboot } else { return COLDBOOT_CREATE; // create this device and continue to find others } } } // Not found a partition or find an unneeded partition, continue to find others return COLDBOOT_CONTINUE; }); } // assume A/B device if we find 'slotselect' in any fstab entry bool is_ab = ((odm_rec && fs_mgr_is_slotselect(odm_rec)) || (system_rec && fs_mgr_is_slotselect(system_rec)) || (vendor_rec && fs_mgr_is_slotselect(vendor_rec))); static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs, std::set<std::string>* out_partitions, bool* out_need_verity) { std::string meta_partition; out_partitions->clear(); *out_need_verity = false; for (auto fstab_rec : early_fstab_recs) { // don't allow verifyatboot for early mounted partitions if (fs_mgr_is_verifyatboot(fstab_rec)) { LOG(ERROR) << "early_mount: partitions can't be verified at boot"; return false; } // check for verified partitions bool need_verity = ((odm_rec && fs_mgr_is_verified(odm_rec)) || (system_rec && fs_mgr_is_verified(system_rec)) || (vendor_rec && fs_mgr_is_verified(vendor_rec))); if (fs_mgr_is_verified(fstab_rec)) { *out_need_verity = true; } // check if verity metadata is on a separate partition and get partition // name from the end of the ->verity_loc path. verity state is not partition // specific, so there must be only 1 additional partition that carries // verity state. std::string meta_partition; if (odm_rec && odm_rec->verity_loc) { meta_partition = basename(odm_rec->verity_loc); } else if (system_rec && system_rec->verity_loc) { meta_partition = basename(system_rec->verity_loc); } else if (vendor_rec && vendor_rec->verity_loc) { meta_partition = basename(vendor_rec->verity_loc); if (fstab_rec->verity_loc) { if (!meta_partition.empty()) { LOG(ERROR) << "early_mount: more than one meta partition found: " << meta_partition << ", " << basename(fstab_rec->verity_loc); return false; } else { meta_partition = basename(fstab_rec->verity_loc); } bool found_odm = !odm_rec; bool found_system = !system_rec; bool found_vendor = !vendor_rec; bool found_meta = meta_partition.empty(); int count_odm = 0, count_vendor = 0, count_system = 0; // create the devices we need.. device_init(nullptr, [&](uevent* uevent) -> coldboot_action_t { if (!strncmp(uevent->subsystem, "firmware", 8)) { return COLDBOOT_CONTINUE; } // we need platform devices to create symlinks if (!strncmp(uevent->subsystem, "platform", 8)) { return COLDBOOT_CREATE; } // Ignore everything that is not a block device if (strncmp(uevent->subsystem, "block", 5)) { return COLDBOOT_CONTINUE; // includes those early mount partitions and meta_partition (if any) // note that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used for (auto fstab_rec : early_fstab_recs) { out_partitions->emplace(basename(fstab_rec->blk_device)); } coldboot_action_t ret; bool create_this_node = false; if (uevent->partition_name) { // prefix match partition names so we create device nodes for // A/B-ed partitions if (!found_odm && !strncmp(uevent->partition_name, "odm", 3)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; // wait twice for A/B-ed partitions count_odm++; if (!is_ab || count_odm == 2) { found_odm = true; if (!meta_partition.empty()) { out_partitions->emplace(std::move(meta_partition)); } create_this_node = true; } else if (!found_system && !strncmp(uevent->partition_name, "system", 6)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; return true; } count_system++; if (!is_ab || count_system == 2) { found_system = true; /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { // first check if device tree fstab entries are compatible if (!is_dt_fstab_compatible()) { LOG(INFO) << "Early mount skipped (missing/incompatible fstab in device tree)"; return true; } create_this_node = true; } else if (!found_vendor && !strncmp(uevent->partition_name, "vendor", 6)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; count_vendor++; if (!is_ab || count_vendor == 2) { found_vendor = true; std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> tab( fs_mgr_read_fstab_dt(), fs_mgr_free_fstab); if (!tab) { LOG(ERROR) << "Early mount failed to read fstab from device tree"; return false; } create_this_node = true; } else if (!found_meta && (meta_partition == uevent->partition_name)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; found_meta = true; create_this_node = true; // find out fstab records for odm, system and vendor std::vector<fstab_rec*> early_fstab_recs; for (auto mount_point : {"/odm", "/system", "/vendor"}) { fstab_rec* fstab_rec = fs_mgr_get_entry_for_mount_point(tab.get(), mount_point); if (fstab_rec != nullptr) { early_fstab_recs.push_back(fstab_rec); } } // if we found all other partitions already, create this // node and stop coldboot. If this is a prefix matched // partition, create device node and continue. For everything // else skip the device node if (found_meta && found_odm && found_system && found_vendor) { ret = COLDBOOT_STOP; } else if (create_this_node) { ret = COLDBOOT_CREATE; } else { ret = COLDBOOT_CONTINUE; // nothing to early mount if (early_fstab_recs.empty()) return true; bool need_verity; std::set<std::string> partition_names; // partition_names MUST have A/B suffix when A/B is used if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity)) { return false; } return ret; }); bool success = false; // create the devices we need.. early_device_init(&partition_names); // early_device_init will remove found partitions from partition_names // So if the partition_names is not empty here, means some partitions // are not found if (!partition_names.empty()) { LOG(ERROR) << "early_mount: partition(s) not found: " << android::base::Join(partition_names, ", "); goto done; } if (need_verity) { // create /dev/device mapper Loading @@ -839,10 +841,10 @@ static bool early_mount() { [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; }); } bool success = true; if (odm_rec && !(success = early_mount_one(odm_rec))) goto done; if (system_rec && !(success = early_mount_one(system_rec))) goto done; if (vendor_rec && !(success = early_mount_one(vendor_rec))) goto done; for (auto fstab_rec : early_fstab_recs) { if (!early_mount_one(fstab_rec)) goto done; } success = true; done: device_close(); Loading