Loading fs_mgr/libfstab/boot_config.cpp +29 −36 Original line number Diff line number Diff line Loading @@ -17,11 +17,9 @@ #include <algorithm> #include <iterator> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include "fstab_priv.h" Loading @@ -35,7 +33,7 @@ const std::string& GetAndroidDtDir() { static const std::string kAndroidDtDir = [] { std::string 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)) && GetKernelCmdline("androidboot.android_dt_dir", &android_dt_dir)) && !android_dt_dir.empty()) { // Ensure the returned path ends with a / if (android_dt_dir.back() != '/') { Loading Loading @@ -110,13 +108,10 @@ bool GetBootconfig(const std::string& key, std::string* out) { return GetBootconfigFromString(bootconfig, key, out); } } // namespace fs_mgr } // namespace android std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std::string& cmdline) { void ImportKernelCmdlineFromString(const std::string& cmdline, const std::function<void(std::string, std::string)>& fn) { static constexpr char quote = '"'; std::vector<std::pair<std::string, std::string>> result; size_t base = 0; while (true) { // skip quoted spans Loading @@ -135,48 +130,46 @@ std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std: if (equal_sign == piece.npos) { if (!piece.empty()) { // no difference between <key> and <key>= result.emplace_back(std::move(piece), ""); fn(std::move(piece), ""); } } else { result.emplace_back(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); fn(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); } if (found == cmdline.npos) break; base = found + 1; } return result; } 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); const std::string cmdline_key("androidboot." + android_key); for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { if (key == cmdline_key) { *out_val = value; return true; bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, std::string* out) { bool found = false; ImportKernelCmdlineFromString(cmdline, [&](std::string config_key, std::string value) { if (!found && config_key == key) { *out = std::move(value); found = true; } }); return found; } *out_val = ""; return false; void ImportKernelCmdline(const std::function<void(std::string, std::string)>& fn) { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); ImportKernelCmdlineFromString(android::base::Trim(cmdline), fn); } // 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) { bool GetKernelCmdline(const std::string& key, std::string* out) { std::string cmdline; if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) return false; if (!cmdline.empty() && cmdline.back() == '\n') { cmdline.pop_back(); } return fs_mgr_get_boot_config_from_kernel(cmdline, key, out_val); android::base::ReadFileToString("/proc/cmdline", &cmdline); return GetKernelCmdlineFromString(android::base::Trim(cmdline), key, out); } // Tries to get the boot config value in device tree, properties and // kernel cmdline (in that order). Returns 'true' if successfully // found, 'false' otherwise. } // namespace fs_mgr } // namespace android // Tries to get the boot config value in device tree, properties, kernel bootconfig and kernel // cmdline (in that order). // Returns 'true' if successfully found, 'false' otherwise. bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); Loading Loading @@ -204,7 +197,7 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } // finally, fallback to kernel cmdline, properties may not be ready yet if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) { if (android::fs_mgr::GetKernelCmdline(config_key, out_val)) { return true; } Loading fs_mgr/libfstab/fstab.cpp +11 −17 Original line number Diff line number Diff line Loading @@ -863,11 +863,11 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p } std::set<std::string> GetBootDevices() { std::set<std::string> boot_devices; // First check bootconfig, then kernel commandline, then the device tree std::string value; if (GetBootconfig("androidboot.boot_devices", &value) || GetBootconfig("androidboot.boot_device", &value)) { std::set<std::string> boot_devices; // split by spaces and trim the trailing comma. for (std::string_view device : android::base::Split(value, " ")) { base::ConsumeSuffix(&device, ","); Loading @@ -876,26 +876,20 @@ std::set<std::string> GetBootDevices() { 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, ","); return std::set<std::string>(boot_devices.begin(), boot_devices.end()); const std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; if (GetKernelCmdline("androidboot.boot_devices", &value) || ReadDtFile(dt_file_name, &value)) { auto boot_devices_list = Split(value, ","); return {boot_devices_list.begin(), boot_devices_list.end()}; } std::string cmdline; if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { std::set<std::string> boot_devices; const std::string cmdline_key = "androidboot.boot_device"; for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { if (key == cmdline_key) { boot_devices.emplace(value); } ImportKernelCmdline([&](std::string key, std::string value) { if (key == "androidboot.boot_device") { boot_devices.emplace(std::move(value)); } }); if (!boot_devices.empty()) { return boot_devices; } } // Fallback to extract boot devices from fstab. Fstab fstab; Loading fs_mgr/libfstab/fstab_priv.h +6 −6 Original line number Diff line number Diff line Loading @@ -18,17 +18,11 @@ #include <functional> #include <string> #include <utility> #include <vector> #include <fstab/fstab.h> // Do not include logging_macros.h here as this header is used by fs_mgr, too. std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std::string& cmdline); bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& key, 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); bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab); Loading @@ -48,5 +42,11 @@ void ImportBootconfigFromString(const std::string& bootconfig, bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out); void ImportKernelCmdlineFromString(const std::string& cmdline, const std::function<void(std::string, std::string)>& fn); bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android fs_mgr/libfstab/include/fstab/fstab.h +8 −0 Original line number Diff line number Diff line Loading @@ -137,5 +137,13 @@ void ImportBootconfig(const std::function<void(std::string, std::string)>& fn); // Otherwise returns false and |*out| is not modified. bool GetBootconfig(const std::string& key, std::string* out); // Import the kernel cmdline by calling the callback |fn| with each key-value pair. void ImportKernelCmdline(const std::function<void(std::string, std::string)>& fn); // Get the kernel cmdline value for |key|. // Returns true if |key| is found in the kernel cmdline. // Otherwise returns false and |*out| is not modified. bool GetKernelCmdline(const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android fs_mgr/tests/fs_mgr_test.cpp +25 −18 Original line number Diff line number Diff line Loading @@ -224,23 +224,32 @@ bool CompareFlags(FstabEntry::FsMgrFlags& lhs, FstabEntry::FsMgrFlags& rhs) { } // namespace TEST(fs_mgr, fs_mgr_parse_cmdline) { EXPECT_EQ(result_space, fs_mgr_parse_cmdline(cmdline)); TEST(fs_mgr, ImportKernelCmdline) { std::vector<std::pair<std::string, std::string>> result; ImportKernelCmdlineFromString( cmdline, [&](std::string key, std::string value) { result.emplace_back(key, value); }); EXPECT_THAT(result, ContainerEq(result_space)); } TEST(fs_mgr, fs_mgr_get_boot_config_from_kernel_cmdline) { TEST(fs_mgr, GetKernelCmdline) { std::string content; for (const auto& entry : result_space) { static constexpr char androidboot[] = "androidboot."; if (!android::base::StartsWith(entry.first, androidboot)) continue; auto key = entry.first.substr(strlen(androidboot)); EXPECT_TRUE(fs_mgr_get_boot_config_from_kernel(cmdline, key, &content)) << " for " << key; EXPECT_EQ(entry.second, content); for (const auto& [key, value] : result_space) { EXPECT_TRUE(GetKernelCmdlineFromString(cmdline, key, &content)) << " for " << key; EXPECT_EQ(content, value); } EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "vbmeta.avb_versio", &content)); EXPECT_TRUE(content.empty()) << content; EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content)); EXPECT_TRUE(content.empty()) << content; const std::string kUnmodifiedToken = "<UNMODIFIED>"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "androidboot.vbmeta.avb_versio", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } TEST(fs_mgr, ImportBootconfig) { Loading @@ -260,17 +269,15 @@ TEST(fs_mgr, GetBootconfig) { const std::string kUnmodifiedToken = "<UNMODIFIED>"; content = kUnmodifiedToken; EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString(bootconfig, "", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString( bootconfig, "androidboot.vbmeta.avb_versio", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.vbmeta.avb_versio", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE( android::fs_mgr::GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } Loading Loading
fs_mgr/libfstab/boot_config.cpp +29 −36 Original line number Diff line number Diff line Loading @@ -17,11 +17,9 @@ #include <algorithm> #include <iterator> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include "fstab_priv.h" Loading @@ -35,7 +33,7 @@ const std::string& GetAndroidDtDir() { static const std::string kAndroidDtDir = [] { std::string 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)) && GetKernelCmdline("androidboot.android_dt_dir", &android_dt_dir)) && !android_dt_dir.empty()) { // Ensure the returned path ends with a / if (android_dt_dir.back() != '/') { Loading Loading @@ -110,13 +108,10 @@ bool GetBootconfig(const std::string& key, std::string* out) { return GetBootconfigFromString(bootconfig, key, out); } } // namespace fs_mgr } // namespace android std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std::string& cmdline) { void ImportKernelCmdlineFromString(const std::string& cmdline, const std::function<void(std::string, std::string)>& fn) { static constexpr char quote = '"'; std::vector<std::pair<std::string, std::string>> result; size_t base = 0; while (true) { // skip quoted spans Loading @@ -135,48 +130,46 @@ std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std: if (equal_sign == piece.npos) { if (!piece.empty()) { // no difference between <key> and <key>= result.emplace_back(std::move(piece), ""); fn(std::move(piece), ""); } } else { result.emplace_back(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); fn(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); } if (found == cmdline.npos) break; base = found + 1; } return result; } 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); const std::string cmdline_key("androidboot." + android_key); for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { if (key == cmdline_key) { *out_val = value; return true; bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, std::string* out) { bool found = false; ImportKernelCmdlineFromString(cmdline, [&](std::string config_key, std::string value) { if (!found && config_key == key) { *out = std::move(value); found = true; } }); return found; } *out_val = ""; return false; void ImportKernelCmdline(const std::function<void(std::string, std::string)>& fn) { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); ImportKernelCmdlineFromString(android::base::Trim(cmdline), fn); } // 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) { bool GetKernelCmdline(const std::string& key, std::string* out) { std::string cmdline; if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) return false; if (!cmdline.empty() && cmdline.back() == '\n') { cmdline.pop_back(); } return fs_mgr_get_boot_config_from_kernel(cmdline, key, out_val); android::base::ReadFileToString("/proc/cmdline", &cmdline); return GetKernelCmdlineFromString(android::base::Trim(cmdline), key, out); } // Tries to get the boot config value in device tree, properties and // kernel cmdline (in that order). Returns 'true' if successfully // found, 'false' otherwise. } // namespace fs_mgr } // namespace android // Tries to get the boot config value in device tree, properties, kernel bootconfig and kernel // cmdline (in that order). // Returns 'true' if successfully found, 'false' otherwise. bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); Loading Loading @@ -204,7 +197,7 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } // finally, fallback to kernel cmdline, properties may not be ready yet if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) { if (android::fs_mgr::GetKernelCmdline(config_key, out_val)) { return true; } Loading
fs_mgr/libfstab/fstab.cpp +11 −17 Original line number Diff line number Diff line Loading @@ -863,11 +863,11 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p } std::set<std::string> GetBootDevices() { std::set<std::string> boot_devices; // First check bootconfig, then kernel commandline, then the device tree std::string value; if (GetBootconfig("androidboot.boot_devices", &value) || GetBootconfig("androidboot.boot_device", &value)) { std::set<std::string> boot_devices; // split by spaces and trim the trailing comma. for (std::string_view device : android::base::Split(value, " ")) { base::ConsumeSuffix(&device, ","); Loading @@ -876,26 +876,20 @@ std::set<std::string> GetBootDevices() { 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, ","); return std::set<std::string>(boot_devices.begin(), boot_devices.end()); const std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; if (GetKernelCmdline("androidboot.boot_devices", &value) || ReadDtFile(dt_file_name, &value)) { auto boot_devices_list = Split(value, ","); return {boot_devices_list.begin(), boot_devices_list.end()}; } std::string cmdline; if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { std::set<std::string> boot_devices; const std::string cmdline_key = "androidboot.boot_device"; for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { if (key == cmdline_key) { boot_devices.emplace(value); } ImportKernelCmdline([&](std::string key, std::string value) { if (key == "androidboot.boot_device") { boot_devices.emplace(std::move(value)); } }); if (!boot_devices.empty()) { return boot_devices; } } // Fallback to extract boot devices from fstab. Fstab fstab; Loading
fs_mgr/libfstab/fstab_priv.h +6 −6 Original line number Diff line number Diff line Loading @@ -18,17 +18,11 @@ #include <functional> #include <string> #include <utility> #include <vector> #include <fstab/fstab.h> // Do not include logging_macros.h here as this header is used by fs_mgr, too. std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std::string& cmdline); bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& key, 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); bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab); Loading @@ -48,5 +42,11 @@ void ImportBootconfigFromString(const std::string& bootconfig, bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out); void ImportKernelCmdlineFromString(const std::string& cmdline, const std::function<void(std::string, std::string)>& fn); bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android
fs_mgr/libfstab/include/fstab/fstab.h +8 −0 Original line number Diff line number Diff line Loading @@ -137,5 +137,13 @@ void ImportBootconfig(const std::function<void(std::string, std::string)>& fn); // Otherwise returns false and |*out| is not modified. bool GetBootconfig(const std::string& key, std::string* out); // Import the kernel cmdline by calling the callback |fn| with each key-value pair. void ImportKernelCmdline(const std::function<void(std::string, std::string)>& fn); // Get the kernel cmdline value for |key|. // Returns true if |key| is found in the kernel cmdline. // Otherwise returns false and |*out| is not modified. bool GetKernelCmdline(const std::string& key, std::string* out); } // namespace fs_mgr } // namespace android
fs_mgr/tests/fs_mgr_test.cpp +25 −18 Original line number Diff line number Diff line Loading @@ -224,23 +224,32 @@ bool CompareFlags(FstabEntry::FsMgrFlags& lhs, FstabEntry::FsMgrFlags& rhs) { } // namespace TEST(fs_mgr, fs_mgr_parse_cmdline) { EXPECT_EQ(result_space, fs_mgr_parse_cmdline(cmdline)); TEST(fs_mgr, ImportKernelCmdline) { std::vector<std::pair<std::string, std::string>> result; ImportKernelCmdlineFromString( cmdline, [&](std::string key, std::string value) { result.emplace_back(key, value); }); EXPECT_THAT(result, ContainerEq(result_space)); } TEST(fs_mgr, fs_mgr_get_boot_config_from_kernel_cmdline) { TEST(fs_mgr, GetKernelCmdline) { std::string content; for (const auto& entry : result_space) { static constexpr char androidboot[] = "androidboot."; if (!android::base::StartsWith(entry.first, androidboot)) continue; auto key = entry.first.substr(strlen(androidboot)); EXPECT_TRUE(fs_mgr_get_boot_config_from_kernel(cmdline, key, &content)) << " for " << key; EXPECT_EQ(entry.second, content); for (const auto& [key, value] : result_space) { EXPECT_TRUE(GetKernelCmdlineFromString(cmdline, key, &content)) << " for " << key; EXPECT_EQ(content, value); } EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "vbmeta.avb_versio", &content)); EXPECT_TRUE(content.empty()) << content; EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content)); EXPECT_TRUE(content.empty()) << content; const std::string kUnmodifiedToken = "<UNMODIFIED>"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "androidboot.vbmeta.avb_versio", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(GetKernelCmdlineFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } TEST(fs_mgr, ImportBootconfig) { Loading @@ -260,17 +269,15 @@ TEST(fs_mgr, GetBootconfig) { const std::string kUnmodifiedToken = "<UNMODIFIED>"; content = kUnmodifiedToken; EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString(bootconfig, "", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString( bootconfig, "androidboot.vbmeta.avb_versio", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.vbmeta.avb_versio", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; EXPECT_FALSE( android::fs_mgr::GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } Loading