system设置ro_boot_属性

将kernel cmdline的属性,设置为"ro.boot."/"ro.kernel."

我们在cmdline自定义的属性也可以通过这种方式传递给上层,

我们看一下源码是如何实现的:

Android8.1/9.0:

static char qemu[32];

int main(int argc, char** argv)

 ->process_kernel_cmdline();

  ->import_kernel_cmdline(false, import_kernel_nv);

   ->android::base::ReadFileToString("/proc/cmdline", &cmdline);

   ->for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { //遍历cmdline

    ->std::vector<std::string> pieces = android::base::Split(entry, "=");  //字符串分隔成 “名字” =  “值”

    ->fn(pieces[0], pieces[1], in_qemu);

     ->import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {

      ->if (key == "qemu") {  //模拟器的属性

       ->strlcpy(qemu, value.c_str(), sizeof(qemu)); //设置模拟器标志位

      ->else if (android::base::StartsWith(key, "androidboot.")) {  //如果是一般的"androidboot."属性,全部设置为"ro.boot."

       ->property_set("ro.boot." + key.substr(12), value);

  ->if (qemu[0])    //如果模拟器存在

   ->import_kernel_cmdline(true, import_kernel_nv);

    ->for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { //再次遍历cmdline

     ->std::vector<std::string> pieces = android::base::Split(entry, "=");  //字符串分隔成 “名字” =  “值”

     ->fn(pieces[0], pieces[1], in_qemu);

      ->import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {

       ->if (for_emulator) {

        ->property_set("ro.kernel." + key, value);  //将cmdline的所有属性都设置为"ro.kernel."

        ->return;

 /system/core/init/init.cpp 

1
2
3
4
5
6
7
8
9

static char qemu[32];
int main(int argc, char** argv) {
    ... ...
    property_init();
    ... ...
    process_kernel_dt();
    process_kernel_cmdline();
    ... ...
}

 /system/core/init/init.cpp 

1
2
3
4
5
6
7

static void process_kernel_cmdline() {
    // The first pass does the common stuff, and finds if we are in qemu.
    // The second pass is only necessary for qemu to export all kernel params
    // as properties.
    import_kernel_cmdline(false, import_kernel_nv);
    if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
}

 /system/core/init/util.cpp

1
2
3
4
5
6
7
8
9
10
11
12

void import_kernel_cmdline(bool in_qemu,
                           const std::function<void(const std::string&, const std::string&, bool)>& fn) {
    std::string cmdline;
    android::base::ReadFileToString("/proc/cmdline", &cmdline);

    for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
        std::vector<std::string> pieces = android::base::Split(entry, "=");
        if (pieces.size() == 2) {
            fn(pieces[0], pieces[1], in_qemu);
        }
    }
}

 /system/core/init/init.cpp 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
    if (key.empty()) return;

    if (for_emulator) {
        // In the emulator, export any kernel option with the "ro.kernel." prefix.
        property_set("ro.kernel." + key, value);
        return;
    }

    if (key == "qemu") {
        strlcpy(qemu, value.c_str(), sizeof(qemu));
    } else if (android::base::StartsWith(key, "androidboot.")) {
        property_set("ro.boot." + key.substr(12), value);
    }
}

Android 10.0之后:

将之前的main函数分成了几部分,读取cmdline并设置ro.boot属性的功能放到了SecondStageMain()函数

int main(int argc, char** argv)

 ->SecondStageMain()

  ->process_kernel_cmdline(); //以下流程和8.1/9.0差不多

   ->import_kernel_cmdline

    ->... ...

 /system/core/init/main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif
    // Boost prio which will be restored later
    setpriority(PRIO_PROCESS, 0, -20);
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }

    return FirstStageMain(argc, argv);
}

Android11.0之后,调用流程再次做了一点改动:

int main(int argc, char** argv)

 ->SecondStageMain()            /system/core/init/main.cpp

  ->PropertyInit();           /system/core/init/property_service.cpp

   ->process_kernel_cmdline();      /system/core/init/property_service.cpp  //以下流程没有变化

    ->ImportKernelCmdline  /system/core/init/util.cpp

     ->... ...

 /system/core/init/property_service.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

void PropertyInit() {
    selinux_callback cb;
    cb.func_audit = PropertyAuditCallback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
    CreateSerializedPropertyInfo();
    if (__system_property_area_init()) {
        LOG(FATAL) << "Failed to initialize property area";
    }
    if (!property_info_area.LoadDefaultPath()) {
        LOG(FATAL) << "Failed to load serialized property info file";
    }

    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    ProcessKernelDt();
    ProcessKernelCmdline();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    ExportKernelBootProps();

    PropertyLoadBootDefaults();
}

 /system/core/init/property_service.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

static void ProcessKernelCmdline() {
    bool for_emulator = false;
    ImportKernelCmdline([&](const std::string& key, const std::string& value) {  //以前的import_kernel_nv()现在变成了匿名函数
        if (key == "qemu") {
            for_emulator = true;
        } else if (StartsWith(key, "androidboot.")) {
            InitPropertySet("ro.boot." + key.substr(12), value);
        }
    });

    if (for_emulator) {
        ImportKernelCmdline([&](const std::string& key, const std::string& value) {
            // In the emulator, export any kernel option with the "ro.kernel." prefix.
            InitPropertySet("ro.kernel." + key, value);
        });
    }
}

 /system/core/init/util.cpp

1
2
3
4
5
6
7
8
9
10
11

void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>& fn) {
    std::string cmdline;
    android::base::ReadFileToString("/proc/cmdline", &cmdline);

    for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
        std::vector<std::string> pieces = android::base::Split(entry, "=");
        if (pieces.size() == 2) {
            fn(pieces[0], pieces[1]);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值