Loading fs_mgr/libfstab/boot_config.cpp +62 −51 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ const std::string& GetAndroidDtDir() { // Set once and saves time for subsequent calls to this function static const std::string kAndroidDtDir = [] { std::string android_dt_dir; if ((fs_mgr_get_boot_config_from_bootconfig_source("android_dt_dir", &android_dt_dir) || if ((GetBootconfig("androidboot.android_dt_dir", &android_dt_dir) || fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) && !android_dt_dir.empty()) { // Ensure the returned path ends with a / Loading @@ -51,6 +51,65 @@ const std::string& GetAndroidDtDir() { return kAndroidDtDir; } void ImportBootconfigFromString(const std::string& bootconfig, const std::function<void(std::string, std::string)>& fn) { for (std::string_view line : android::base::Split(bootconfig, "\n")) { const auto equal_pos = line.find('='); std::string key = android::base::Trim(line.substr(0, equal_pos)); if (key.empty()) { continue; } std::string value; if (equal_pos != line.npos) { value = android::base::Trim(line.substr(equal_pos + 1)); // If the value is a comma-delimited list, the kernel would insert a space between the // list elements when read from /proc/bootconfig. // BoardConfig.mk: // BOARD_BOOTCONFIG := key=value1,value2,value3 // /proc/bootconfig: // key = "value1", "value2", "value3" if (key == "androidboot.boot_device" || key == "androidboot.boot_devices") { // boot_device[s] is a special case where a list element can contain comma and the // caller expects a space-delimited list, so don't remove space here. value.erase(std::remove(value.begin(), value.end(), '"'), value.end()); } else { // In order to not break the expectations of existing code, we modify the value to // keep the format consistent with the kernel cmdline by removing quote and space. std::string_view sv(value); android::base::ConsumePrefix(&sv, "\""); android::base::ConsumeSuffix(&sv, "\""); value = android::base::StringReplace(sv, R"(", ")", ",", true); } } // "key" and "key =" means empty value. fn(std::move(key), std::move(value)); } } bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out) { bool found = false; ImportBootconfigFromString(bootconfig, [&](std::string config_key, std::string value) { if (!found && config_key == key) { *out = std::move(value); found = true; } }); return found; } void ImportBootconfig(const std::function<void(std::string, std::string)>& fn) { std::string bootconfig; android::base::ReadFileToString("/proc/bootconfig", &bootconfig); ImportBootconfigFromString(bootconfig, fn); } bool GetBootconfig(const std::string& key, std::string* out) { std::string bootconfig; android::base::ReadFileToString("/proc/bootconfig", &bootconfig); return GetBootconfigFromString(bootconfig, key, out); } } // namespace fs_mgr } // namespace android Loading Loading @@ -88,44 +147,6 @@ std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std: return result; } std::vector<std::pair<std::string, std::string>> fs_mgr_parse_proc_bootconfig( const std::string& cmdline) { static constexpr char quote = '"'; std::vector<std::pair<std::string, std::string>> result; for (auto& line : android::base::Split(cmdline, "\n")) { line.erase(std::remove(line.begin(), line.end(), quote), line.end()); auto equal_sign = line.find('='); if (equal_sign == line.npos) { if (!line.empty()) { // no difference between <key> and <key>= result.emplace_back(std::move(line), ""); } } else { result.emplace_back(android::base::Trim(line.substr(0, equal_sign)), android::base::Trim(line.substr(equal_sign + 1))); } } return result; } bool fs_mgr_get_boot_config_from_bootconfig(const std::string& bootconfig, const std::string& android_key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); const std::string bootconfig_key("androidboot." + android_key); for (const auto& [key, value] : fs_mgr_parse_proc_bootconfig(bootconfig)) { if (key == bootconfig_key) { *out_val = value; return true; } } *out_val = ""; return false; } bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& android_key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); Loading @@ -142,17 +163,6 @@ bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::s return false; } // Tries to get the given boot config value from bootconfig. // Returns true if successfully found, false otherwise. bool fs_mgr_get_boot_config_from_bootconfig_source(const std::string& key, std::string* out_val) { std::string bootconfig; if (!android::base::ReadFileToString("/proc/bootconfig", &bootconfig)) return false; if (!bootconfig.empty() && bootconfig.back() == '\n') { bootconfig.pop_back(); } return fs_mgr_get_boot_config_from_bootconfig(bootconfig, key, out_val); } // Tries to get the given boot config value from kernel cmdline. // Returns true if successfully found, false otherwise. bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) { Loading Loading @@ -188,7 +198,8 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } // next, check if we have the property in bootconfig if (fs_mgr_get_boot_config_from_bootconfig_source(key, out_val)) { const std::string config_key = "androidboot." + key; if (android::fs_mgr::GetBootconfig(config_key, out_val)) { return true; } Loading fs_mgr/libfstab/fstab.cpp +5 −7 Original line number Diff line number Diff line Loading @@ -864,21 +864,19 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p std::set<std::string> GetBootDevices() { // First check bootconfig, then kernel commandline, then the device tree std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; std::string value; if (fs_mgr_get_boot_config_from_bootconfig_source("boot_devices", &value) || fs_mgr_get_boot_config_from_bootconfig_source("boot_device", &value)) { if (GetBootconfig("androidboot.boot_devices", &value) || GetBootconfig("androidboot.boot_device", &value)) { std::set<std::string> boot_devices; // remove quotes and split by spaces auto boot_device_strings = base::Split(base::StringReplace(value, "\"", "", true), " "); for (std::string_view device : boot_device_strings) { // trim the trailing comma, keep the rest. // split by spaces and trim the trailing comma. for (std::string_view device : android::base::Split(value, " ")) { base::ConsumeSuffix(&device, ","); boot_devices.emplace(device); } return boot_devices; } std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) || ReadDtFile(dt_file_name, &value)) { auto boot_devices = Split(value, ","); Loading fs_mgr/libfstab/fstab_priv.h +7 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <functional> #include <string> #include <utility> #include <vector> Loading @@ -29,11 +30,6 @@ bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::s std::string* out_val); bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val); bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val); std::vector<std::pair<std::string, std::string>> fs_mgr_parse_proc_bootconfig( const std::string& bootconfig); bool fs_mgr_get_boot_config_from_bootconfig(const std::string& bootconfig, const std::string& key, std::string* out_val); bool fs_mgr_get_boot_config_from_bootconfig_source(const std::string& key, std::string* out_val); bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab); bool is_dt_compatible(); Loading @@ -46,5 +42,11 @@ bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* bool SkipMountWithConfig(const std::string& skip_config, Fstab* fstab, bool verbose); std::string GetFstabPath(); void ImportBootconfigFromString(const std::string& bootconfig, const std::function<void(std::string, std::string)>& fn); bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android fs_mgr/libfstab/include/fstab/fstab.h +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <stdint.h> #include <sys/types.h> #include <functional> #include <set> #include <string> #include <vector> Loading Loading @@ -128,5 +129,13 @@ std::string GetVerityDeviceName(const FstabEntry& entry); // If the platform does not configure a custom DT path, returns the standard one (based in procfs). const std::string& GetAndroidDtDir(); // Import the kernel bootconfig by calling the callback |fn| with each key-value pair. void ImportBootconfig(const std::function<void(std::string, std::string)>& fn); // Get the kernel bootconfig value for |key|. // Returns true if |key| is found in bootconfig. // Otherwise returns false and |*out| is not modified. bool GetBootconfig(const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android fs_mgr/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ cc_test { ], static_libs: [ "libfs_mgr", "libgmock", "libgtest", ], srcs: [ "file_wait_test.cpp", Loading Loading
fs_mgr/libfstab/boot_config.cpp +62 −51 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ const std::string& GetAndroidDtDir() { // Set once and saves time for subsequent calls to this function static const std::string kAndroidDtDir = [] { std::string android_dt_dir; if ((fs_mgr_get_boot_config_from_bootconfig_source("android_dt_dir", &android_dt_dir) || if ((GetBootconfig("androidboot.android_dt_dir", &android_dt_dir) || fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) && !android_dt_dir.empty()) { // Ensure the returned path ends with a / Loading @@ -51,6 +51,65 @@ const std::string& GetAndroidDtDir() { return kAndroidDtDir; } void ImportBootconfigFromString(const std::string& bootconfig, const std::function<void(std::string, std::string)>& fn) { for (std::string_view line : android::base::Split(bootconfig, "\n")) { const auto equal_pos = line.find('='); std::string key = android::base::Trim(line.substr(0, equal_pos)); if (key.empty()) { continue; } std::string value; if (equal_pos != line.npos) { value = android::base::Trim(line.substr(equal_pos + 1)); // If the value is a comma-delimited list, the kernel would insert a space between the // list elements when read from /proc/bootconfig. // BoardConfig.mk: // BOARD_BOOTCONFIG := key=value1,value2,value3 // /proc/bootconfig: // key = "value1", "value2", "value3" if (key == "androidboot.boot_device" || key == "androidboot.boot_devices") { // boot_device[s] is a special case where a list element can contain comma and the // caller expects a space-delimited list, so don't remove space here. value.erase(std::remove(value.begin(), value.end(), '"'), value.end()); } else { // In order to not break the expectations of existing code, we modify the value to // keep the format consistent with the kernel cmdline by removing quote and space. std::string_view sv(value); android::base::ConsumePrefix(&sv, "\""); android::base::ConsumeSuffix(&sv, "\""); value = android::base::StringReplace(sv, R"(", ")", ",", true); } } // "key" and "key =" means empty value. fn(std::move(key), std::move(value)); } } bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out) { bool found = false; ImportBootconfigFromString(bootconfig, [&](std::string config_key, std::string value) { if (!found && config_key == key) { *out = std::move(value); found = true; } }); return found; } void ImportBootconfig(const std::function<void(std::string, std::string)>& fn) { std::string bootconfig; android::base::ReadFileToString("/proc/bootconfig", &bootconfig); ImportBootconfigFromString(bootconfig, fn); } bool GetBootconfig(const std::string& key, std::string* out) { std::string bootconfig; android::base::ReadFileToString("/proc/bootconfig", &bootconfig); return GetBootconfigFromString(bootconfig, key, out); } } // namespace fs_mgr } // namespace android Loading Loading @@ -88,44 +147,6 @@ std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std: return result; } std::vector<std::pair<std::string, std::string>> fs_mgr_parse_proc_bootconfig( const std::string& cmdline) { static constexpr char quote = '"'; std::vector<std::pair<std::string, std::string>> result; for (auto& line : android::base::Split(cmdline, "\n")) { line.erase(std::remove(line.begin(), line.end(), quote), line.end()); auto equal_sign = line.find('='); if (equal_sign == line.npos) { if (!line.empty()) { // no difference between <key> and <key>= result.emplace_back(std::move(line), ""); } } else { result.emplace_back(android::base::Trim(line.substr(0, equal_sign)), android::base::Trim(line.substr(equal_sign + 1))); } } return result; } bool fs_mgr_get_boot_config_from_bootconfig(const std::string& bootconfig, const std::string& android_key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); const std::string bootconfig_key("androidboot." + android_key); for (const auto& [key, value] : fs_mgr_parse_proc_bootconfig(bootconfig)) { if (key == bootconfig_key) { *out_val = value; return true; } } *out_val = ""; return false; } bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& android_key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); Loading @@ -142,17 +163,6 @@ bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::s return false; } // Tries to get the given boot config value from bootconfig. // Returns true if successfully found, false otherwise. bool fs_mgr_get_boot_config_from_bootconfig_source(const std::string& key, std::string* out_val) { std::string bootconfig; if (!android::base::ReadFileToString("/proc/bootconfig", &bootconfig)) return false; if (!bootconfig.empty() && bootconfig.back() == '\n') { bootconfig.pop_back(); } return fs_mgr_get_boot_config_from_bootconfig(bootconfig, key, out_val); } // Tries to get the given boot config value from kernel cmdline. // Returns true if successfully found, false otherwise. bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) { Loading Loading @@ -188,7 +198,8 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } // next, check if we have the property in bootconfig if (fs_mgr_get_boot_config_from_bootconfig_source(key, out_val)) { const std::string config_key = "androidboot." + key; if (android::fs_mgr::GetBootconfig(config_key, out_val)) { return true; } Loading
fs_mgr/libfstab/fstab.cpp +5 −7 Original line number Diff line number Diff line Loading @@ -864,21 +864,19 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p std::set<std::string> GetBootDevices() { // First check bootconfig, then kernel commandline, then the device tree std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; std::string value; if (fs_mgr_get_boot_config_from_bootconfig_source("boot_devices", &value) || fs_mgr_get_boot_config_from_bootconfig_source("boot_device", &value)) { if (GetBootconfig("androidboot.boot_devices", &value) || GetBootconfig("androidboot.boot_device", &value)) { std::set<std::string> boot_devices; // remove quotes and split by spaces auto boot_device_strings = base::Split(base::StringReplace(value, "\"", "", true), " "); for (std::string_view device : boot_device_strings) { // trim the trailing comma, keep the rest. // split by spaces and trim the trailing comma. for (std::string_view device : android::base::Split(value, " ")) { base::ConsumeSuffix(&device, ","); boot_devices.emplace(device); } return boot_devices; } std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) || ReadDtFile(dt_file_name, &value)) { auto boot_devices = Split(value, ","); Loading
fs_mgr/libfstab/fstab_priv.h +7 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <functional> #include <string> #include <utility> #include <vector> Loading @@ -29,11 +30,6 @@ bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::s std::string* out_val); bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val); bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val); std::vector<std::pair<std::string, std::string>> fs_mgr_parse_proc_bootconfig( const std::string& bootconfig); bool fs_mgr_get_boot_config_from_bootconfig(const std::string& bootconfig, const std::string& key, std::string* out_val); bool fs_mgr_get_boot_config_from_bootconfig_source(const std::string& key, std::string* out_val); bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab); bool is_dt_compatible(); Loading @@ -46,5 +42,11 @@ bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* bool SkipMountWithConfig(const std::string& skip_config, Fstab* fstab, bool verbose); std::string GetFstabPath(); void ImportBootconfigFromString(const std::string& bootconfig, const std::function<void(std::string, std::string)>& fn); bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android
fs_mgr/libfstab/include/fstab/fstab.h +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <stdint.h> #include <sys/types.h> #include <functional> #include <set> #include <string> #include <vector> Loading Loading @@ -128,5 +129,13 @@ std::string GetVerityDeviceName(const FstabEntry& entry); // If the platform does not configure a custom DT path, returns the standard one (based in procfs). const std::string& GetAndroidDtDir(); // Import the kernel bootconfig by calling the callback |fn| with each key-value pair. void ImportBootconfig(const std::function<void(std::string, std::string)>& fn); // Get the kernel bootconfig value for |key|. // Returns true if |key| is found in bootconfig. // Otherwise returns false and |*out| is not modified. bool GetBootconfig(const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android
fs_mgr/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ cc_test { ], static_libs: [ "libfs_mgr", "libgmock", "libgtest", ], srcs: [ "file_wait_test.cpp", Loading