Android设备ro.boot.serialno的前世今生

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013686019/article/details/53239302

http://blog.csdn.net/u013686019/article/details/53239302

为了找到ro.boot.serialno的赋值位置,在源码最可能出现它的目录下比如/system/、/device/、/hardware/、/u-boot/进行搜索:

grep -rn "ro.boot.serialno"

没想到这么做已经掉入坑里了!这个属性是通过字符串拼接形成的,看下产生位置:

/system/core/init/init.c
// name: "androidboot.serialno=H201611200859"
static void import_kernel_nv(char *name, int for_emulator)
{
    char *value = strchr(name, '='); // value: "=H201611200859"
    int name_len = strlen(name);

    if (value == 0) return;
    *value++ = 0; // value: "H201611200859"
    if (name_len == 0) return;

    if (!strcmp(name,"qemu")) {
        strlcpy(qemu, value, sizeof(qemu));
    } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) {
        const char *boot_prop_name = name + 12; // boot_prop_name: "serialno\0"
        char prop[PROP_NAME_MAX];
        int cnt;

		// prop: "ro.boot.serialno"
        cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name);
        if (cnt < PROP_NAME_MAX)
            property_set(prop, value); // ro.boot.serialno = H201611200859
    }
}

以上import_kernel_nv()函数在解析bootloader传进来的cmdline参数时得到调用:

/system/core/init/init.c
cat /proc/cmdline                                    
vmalloc=512M console=ttyS0 androidboot.hardware=fbiboard androidboot.console=ttyS0 board.ap_has_alsa=0 init=/init  mtdparts=fbixxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(misc),0x00008000@0x00006000(resource),0x00008000@0x0000e000(kernel),0x00010000@0x00016000(boot),0x00010000@0x00026000(recovery),0x0001a000@0x00036000(backup),0x00040000@0x00050000(cache),0x00002000@0x00090000(kpanic),0x00100000@0x00092000(system),0x00002000@0x00192000(metadata),0x00600000@0x00194000(userdata),0x00020000@0x00794000(radical_update),-@0x007B4000(user) storagemedia=emmc loader.timestamp=2017-07-29_17:37:57 androidboot.serialno=H201611200859 androidboot.mode=emmc
static void process_kernel_cmdline(void)
{
    /* don't expose the raw commandline to nonpriv processes */
    chmod("/proc/cmdline", 0440);

    /* first pass does the common stuff, and finds if we are in qemu.
     * second pass is only necessary for qemu to export all kernel params
     * as props.
     */
    import_kernel_cmdline(0, import_kernel_nv);
    if (qemu[0])
        import_kernel_cmdline(1, import_kernel_nv);

    export_kernel_boot_props();
}

cmdline由u-传给kernel:

// 设置SN,即ro.boot.serialno的值
int board_late_init(void)
{
	char tmp_buf[32];
	memset(tmp_buf, 0, 32);
	if (get_sn(tmp_buf)) {
		setenv("fbt_sn#", tmp_buf);
	}
}

// 拼接cmdline
#define FASTBOOT_SERIALNO_BOOTARG "androidboot.serialno"
static void rk_commandline_setenv(const char *boot_name, rk_boot_img_hdr *hdr, bool charge)
{
#ifdef CONFIG_CMDLINE_TAG
	static char command_line[1024];
	char *sn = getenv("fbt_sn#");
	if (sn != NULL) {
		/* append serial number if it wasn't in device_info already */
		if (!strstr(command_line, FASTBOOT_SERIALNO_BOOTARG)) {
			snprintf(command_line, sizeof(command_line),
					"%s %s=%s", command_line, FASTBOOT_SERIALNO_BOOTARG, sn);
		}
	}

	command_line[sizeof(command_line) - 1] = 0;

	setenv("bootargs", command_line);
#endif /* CONFIG_CMDLINE_TAG */
}


那么SN的值最初来自哪里呢?一种通用的做法是设备出厂时通过工具把SN烧到Flash的存储器中,在bootloader中读取出来,然后通过cmdline的方式传给kernel,kernel进行相应属性的设置,本例就是如此。

展开阅读全文

没有更多推荐了,返回首页