Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 67e3e637 authored by Yi-Yo Chiang's avatar Yi-Yo Chiang Committed by Automerger Merge Worker
Browse files

Merge "init: Unify kernel bootconfig parser with libfs_mgr" into main am: f2368d07

parents cf244ae1 f2368d07
Loading
Loading
Loading
Loading
+62 −51
Original line number Diff line number Diff line
@@ -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 /
@@ -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

@@ -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);
@@ -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) {
@@ -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;
    }

+5 −7
Original line number Diff line number Diff line
@@ -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, ",");
+7 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <functional>
#include <string>
#include <utility>
#include <vector>
@@ -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();
@@ -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
+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>

#include <functional>
#include <set>
#include <string>
#include <vector>
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ cc_test {
    ],
    static_libs: [
        "libfs_mgr",
        "libgmock",
        "libgtest",
    ],
    srcs: [
        "file_wait_test.cpp",
Loading