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

为了找到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进行相应属性的设置,本例就是如此。