summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorBowgo Tsai <bowgotsai@google.com>2017-02-18 18:33:13 +0800
committerBowgo Tsai <bowgotsai@google.com>2017-02-27 13:09:06 +0800
commitd4beed22e844cca43028de13ed67ead8281c1fab (patch)
treef4162207479f2e05d091a5eb8bd201e2a97b973d /init
parent16f4fb9c4e2e916a91dc87b77a7c062866a4a8ff (diff)
downloadsystem_core-d4beed22e844cca43028de13ed67ead8281c1fab.tar.gz
system_core-d4beed22e844cca43028de13ed67ead8281c1fab.tar.bz2
system_core-d4beed22e844cca43028de13ed67ead8281c1fab.zip
init: early_mount: removing hard-coded paths
Current early mount has some hard-coded paths that are not easy to extend when we switch verified boot to AVB (external/avb/libavb). This CL uses some C++ containers to replace those fixed paths. Bug: 33254008 Test: early mount /vendor with dm-verity on sailfish Test: early mount /vendor without dm-verity on sailfish Test: early mount /vendor with dm-verity on bullhead Change-Id: I32a22fe486d7649e33bb23c9018ddc0428df6069
Diffstat (limited to 'init')
-rw-r--r--init/init.cpp226
1 files changed, 114 insertions, 112 deletions
diff --git a/init/init.cpp b/init/init.cpp
index 3cb12760b..5286ce5c6 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -52,6 +52,8 @@
#include <fstream>
#include <memory>
+#include <set>
+#include <vector>
#include "action.h"
#include "bootchart.h"
@@ -700,71 +702,15 @@ 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;
- }
-
- 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;
- }
-
- // 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;
- }
-
- // 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;
- }
-
- // 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)));
-
- // 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)));
-
- // 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);
+// 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;
}
-
- 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 {
+ device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t {
if (!strncmp(uevent->subsystem, "firmware", 8)) {
return COLDBOOT_CONTINUE;
}
@@ -779,59 +725,115 @@ static bool early_mount() {
return COLDBOOT_CONTINUE;
}
- 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;
- }
-
- create_this_node = true;
- } else if (!found_system && !strncmp(uevent->partition_name, "system", 6)) {
- LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition";
-
- count_system++;
- if (!is_ab || count_system == 2) {
- found_system = true;
+ // 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;
+ });
+}
- 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;
- }
+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;
- 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;
+ 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
+ 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.
+ 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);
}
}
+ }
- // 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;
+ // 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));
+ }
+
+ if (!meta_partition.empty()) {
+ out_partitions->emplace(std::move(meta_partition));
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ // 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);
}
+ }
- return ret;
- });
+ // 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;
+ }
+
+ 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
@@ -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();