diff --git a/fs_mgr/fs_mgr_boot_config.cpp b/fs_mgr/fs_mgr_boot_config.cpp index 911766752..9c5d3f3bb 100644 --- a/fs_mgr/fs_mgr_boot_config.cpp +++ b/fs_mgr/fs_mgr_boot_config.cpp @@ -23,19 +23,11 @@ #include "fs_mgr_priv.h" -// Tries to get the boot config value in properties, kernel cmdline and -// device tree (in that order). returns 'true' if successfully found, 'false' -// otherwise -bool fs_mgr_get_boot_config(const std::string& key, std::string* 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) { FS_MGR_CHECK(out_val != nullptr); - // first check if we have "ro.boot" property already - *out_val = android::base::GetProperty("ro.boot." + key, ""); - if (!out_val->empty()) { - return true; - } - - // fallback to kernel cmdline, properties may not be ready yet std::string cmdline; std::string cmdline_key("androidboot." + key); if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { @@ -50,9 +42,29 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } } + return false; +} + +// Tries to get the boot config value in properties, kernel cmdline and +// device tree (in that order). returns 'true' if successfully found, 'false' +// otherwise +bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { + FS_MGR_CHECK(out_val != nullptr); + + // first check if we have "ro.boot" property already + *out_val = android::base::GetProperty("ro.boot." + key, ""); + if (!out_val->empty()) { + return true; + } + + // fallback to kernel cmdline, properties may not be ready yet + if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) { + return true; + } + // lastly, check the device tree if (is_dt_compatible()) { - std::string file_name = kAndroidDtDir + "/" + key; + std::string file_name = get_android_dt_dir() + "/" + key; if (android::base::ReadFileToString(file_name, out_val)) { if (!out_val->empty()) { out_val->pop_back(); // Trims the trailing '\0' out. diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index b68875b97..8f5d3ad2c 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -29,6 +29,8 @@ #include "fs_mgr_priv.h" +const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android"); + struct fs_mgr_flag_values { char *key_loc; char *verity_loc; @@ -313,9 +315,26 @@ static int parse_flags(char *flags, struct flag_list *fl, return f; } +static std::string init_android_dt_dir() { + std::string android_dt_dir; + // The platform may specify a custom Android DT path in kernel cmdline + if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) { + // Fall back to the standard procfs-based path + android_dt_dir = kDefaultAndroidDtDir; + } + return android_dt_dir; +} + +// FIXME: The same logic is duplicated in system/core/init/ +const std::string& get_android_dt_dir() { + // Set once and saves time for subsequent calls to this function + static const std::string kAndroidDtDir = init_android_dt_dir(); + return kAndroidDtDir; +} + static bool is_dt_fstab_compatible() { std::string dt_value; - std::string file_name = kAndroidDtDir + "/fstab/compatible"; + std::string file_name = get_android_dt_dir() + "/fstab/compatible"; if (read_dt_file(file_name, &dt_value)) { if (dt_value == "android,fstab") { return true; @@ -331,7 +350,7 @@ static std::string read_fstab_from_dt() { return fstab; } - std::string fstabdir_name = kAndroidDtDir + "/fstab"; + std::string fstabdir_name = get_android_dt_dir() + "/fstab"; std::unique_ptr fstabdir(opendir(fstabdir_name.c_str()), closedir); if (!fstabdir) return fstab; @@ -394,7 +413,7 @@ static std::string read_fstab_from_dt() { } bool is_dt_compatible() { - std::string file_name = kAndroidDtDir + "/compatible"; + std::string file_name = get_android_dt_dir() + "/compatible"; std::string dt_value; if (read_dt_file(file_name, &dt_value)) { if (dt_value == "android,firmware") { diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 5ea6e9829..7423c1f8a 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -119,6 +119,7 @@ bool fs_mgr_wait_for_file(const std::string& filename, const std::chrono::milliseconds relative_timeout); bool fs_mgr_update_for_slotselect(struct fstab *fstab); bool fs_mgr_is_device_unlocked(); +const std::string& get_android_dt_dir(); bool is_dt_compatible(); bool is_device_secure(); int load_verity_state(struct fstab_rec* fstab, int* mode); diff --git a/fs_mgr/fs_mgr_priv_boot_config.h b/fs_mgr/fs_mgr_priv_boot_config.h index 8773d33b0..d98dc02c1 100644 --- a/fs_mgr/fs_mgr_priv_boot_config.h +++ b/fs_mgr/fs_mgr_priv_boot_config.h @@ -20,8 +20,7 @@ #include #include -const std::string kAndroidDtDir("/proc/device-tree/firmware/android"); - +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); #endif /* __CORE_FS_MGR_PRIV_BOOTCONFIG_H */ diff --git a/init/init.cpp b/init/init.cpp index f063c3f53..c003c3de1 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -543,7 +543,7 @@ static void process_kernel_dt() { return; } - std::unique_ptr dir(opendir(kAndroidDtDir.c_str()), closedir); + std::unique_ptr dir(opendir(get_android_dt_dir().c_str()), closedir); if (!dir) return; std::string dt_file; @@ -553,7 +553,7 @@ static void process_kernel_dt() { continue; } - std::string file_name = kAndroidDtDir + dp->d_name; + std::string file_name = get_android_dt_dir() + dp->d_name; android::base::ReadFileToString(file_name, &dt_file); std::replace(dt_file.begin(), dt_file.end(), ',', '.'); diff --git a/init/util.cpp b/init/util.cpp index 2792794c5..fdcb22d1c 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -53,6 +53,8 @@ using namespace std::literals::string_literals; namespace android { namespace init { +const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/"); + // DecodeUid() - decodes and returns the given string, which can be either the // numeric or name representation, into the integer uid or gid. Returns // UINT_MAX on error. @@ -374,10 +376,31 @@ void panic() { DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false); } -// Reads the content of device tree file under kAndroidDtDir directory. +static std::string init_android_dt_dir() { + // Use the standard procfs-based path by default + std::string android_dt_dir = kDefaultAndroidDtDir; + // The platform may specify a custom Android DT path in kernel cmdline + import_kernel_cmdline(false, + [&](const std::string& key, const std::string& value, bool in_qemu) { + if (key == "androidboot.android_dt_dir") { + android_dt_dir = value; + } + }); + LOG(INFO) << "Using Android DT directory " << android_dt_dir; + return android_dt_dir; +} + +// FIXME: The same logic is duplicated in system/core/fs_mgr/ +const std::string& get_android_dt_dir() { + // Set once and saves time for subsequent calls to this function + static const std::string kAndroidDtDir = init_android_dt_dir(); + return kAndroidDtDir; +} + +// Reads the content of device tree file under the platform's Android DT directory. // Returns true if the read is success, false otherwise. bool read_android_dt_file(const std::string& sub_path, std::string* dt_content) { - const std::string file_name = kAndroidDtDir + sub_path; + const std::string file_name = get_android_dt_dir() + sub_path; if (android::base::ReadFileToString(file_name, dt_content)) { if (!dt_content->empty()) { dt_content->pop_back(); // Trims the trailing '\0' out. diff --git a/init/util.h b/init/util.h index 452df2d00..29c10cba2 100644 --- a/init/util.h +++ b/init/util.h @@ -30,8 +30,6 @@ #define COLDBOOT_DONE "/dev/.coldboot_done" -const std::string kAndroidDtDir("/proc/device-tree/firmware/android/"); - using android::base::boot_clock; using namespace std::chrono_literals; @@ -57,7 +55,10 @@ bool expand_props(const std::string& src, std::string* dst); void panic() __attribute__((__noreturn__)); -// Reads or compares the content of device tree file under kAndroidDtDir directory. +// Returns the platform's Android DT directory as specified in the kernel cmdline. +// If the platform does not configure a custom DT path, returns the standard one (based in procfs). +const std::string& get_android_dt_dir(); +// Reads or compares the content of device tree file under the platform's Android DT directory. bool read_android_dt_file(const std::string& sub_path, std::string* dt_content); bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);