关于这个ro.hardware 这个东西是怎么来的?
这个不是在我们编译之后就知道的, 是在nit进程里面算出来的
在 init main 函数里面 会call下面两个
get_hardware_name(hardware, &revision);
process_kernel_cmdline();
先看get_hardware_name,
void get_hardware_name(char *hardware, unsigned int *revision)
{
const char *cpuinfo = “/proc/cpuinfo”;
char *data = NULL;
size_t len = 0, limit = 1024;
int fd, n;
char *x, *hw, *rev;
/* Hardware string was provided on kernel command line */
if (hardware[0])
return;
fd = open(cpuinfo, O_RDONLY);
if (fd < 0) return;
for (;;) {
x = realloc(data, limit);
if (!x) {
ERROR("Failed to allocate memory to read %s\n", cpuinfo);
goto done;
}
data = x;
n = read(fd, data + len, limit - len);
if (n < 0) {
ERROR("Failed reading %s: %s (%d)\n", cpuinfo, strerror(errno), errno);
goto done;
}
len += n;
if (len < limit)
break;
/* We filled the buffer, so increase size and loop to read more */
limit *= 2;
}
data[len] = 0;
hw = strstr(data, "\nHardware");
rev = strstr(data, "\nRevision");
if (hw) {
x = strstr(hw, ": ");
if (x) {
x += 2;
n = 0;
while (*x && *x != '\n') {
if (!isspace(*x))
hardware[n++] = tolower(*x);
x++;
if (n == 31) break;
}
hardware[n] = 0;
}
}
if (rev) {
x = strstr(rev, ": ");
if (x) {
*revision = strtoul(x + 2, 0, 16);
}
}
done:
close(fd);
free(data);
这个就是从 proc cpuinfo里面 去读取 Hardware字段, 拿出来的值就保存在hardware中,
然后看
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);
/* now propogate the info given on command line to internal variables
* used by init as well as the current required properties
*/
export_kernel_boot_props();
}
这主要就是读取kernel 启动参数,kernel 启动参数保存在/proc/cmdline
对于一般进程的启动参数保存在 /proc/pid/cmdline里面,然后把一些值转成属性保存,
我们看看 import_kernel_nv这个里面主要就是把cmdline里面的东西转成属性的
static void import_kernel_nv(char *name, int for_emulator)
{
char *value = strchr(name, ‘=’);
int name_len = strlen(name);
if (value == 0) return;
*value++ = 0;
if (name_len == 0) return;
if (for_emulator) {
/* in the emulator, export any kernel option with the
* ro.kernel. prefix */
char buff[PROP_NAME_MAX];
int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
if (len < (int)sizeof(buff))
property_set( buff, value );
return;
}
if (!strcmp(name,"qemu")) {
strlcpy(qemu, value, sizeof(qemu));
} else if(!strcmp(name,"resolution")) {
strlcpy(resolution, value, sizeof(resolution));
} else if(!strcmp(name,"reproducerate")) {
strlcpy(reproducerate, value, sizeof(reproducerate));
} else if(!strcmp(name,"ENV")){
strlcpy(envtype, value, sizeof(envtype));
} else if (!strncmp(name, "androidboot.", 12) && name_len > 12) {
const char *boot_prop_name = name + 12;
char prop[PROP_NAME_MAX];
int cnt;
cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name);
if (cnt < PROP_NAME_MAX)
property_set(prop, value);
}
}
这里我就说下 androidboot. 开头的参数, 我们看一下一般kernel 启动参数
shell@sky828_8s70:/ # cat proc/cmdline
console=ttyS0,115200 androidboot.console=ttyS0 root=/dev/ram rw rootwait init=/init
CORE_DUMP_PATH=/data/core_dump.%%p.gz KDebug=1 delaylogo=true androidboot.selinux=permissive
LX_MEM=0x3D800000 LX_MEM2=0xA0000000,0x1FF00000 EMAC_MEM=0x100000 PM51_ADDR=0x20010000
PM51_LEN=0x10000 CMA0=OTHERS,miu=0,hid=23,sz=0x5800000,st=0x11000000 CMA1=XC,miu=0,
hid=22,sz=0x6000000,st=0x16800000 CMA2=OTHERS2,miu=1,hid=24,sz=0x1c00000,st=0x0 CMA3=VDEC1,
miu=1,hid=19,sz=0xc400000,st=0x1c00000 BOOTLOGO_IN_MBOOT ENV_VAR_OFFSET=0x0 ENV_VAR_SIZE=0x10000
ENV=EMMC SECURITY=ON BOOTTIME_SBOOT=295
BOOTTIME_UBOOT=3566=EMMC SECURITY=ON BOOTTIME_SBOOT=295 BOOTTIME_UBOOT=3566
其中就有androidboot打头的,
androidboot.console=ttyS0
androidboot.selinux=permissive
这段code 就会根据上面这两个, 把 其对应成属性保存在下面这两个属性里面‘
ro.boot.console
ro.boot.permissive 里面, 我们看板子里面确实是这两个。
shell@sky828_8s70:/ # getprop |grep ro.boot
在看下export_kernel_boot_props 这个函数
static void export_kernel_boot_props(void)
{
char tmp[PROP_VALUE_MAX];
int ret;
unsigned i;
struct {
const char *src_prop;
const char *dest_prop;
const char *def_val;
} prop_map[] = {
{ “ro.boot.serialno”, “ro.serialno”, “”, },
{ “ro.boot.mode”, “ro.bootmode”, “unknown”, },
{ “ro.boot.baseband”, “ro.baseband”, “unknown”, },
{ “ro.boot.bootloader”, “ro.bootloader”, “unknown”, },
};
for (i = 0; i < ARRAY_SIZE(prop_map); i++) {
ret = property_get(prop_map[i].src_prop, tmp);
if (ret > 0)
property_set(prop_map[i].dest_prop, tmp);
else
property_set(prop_map[i].dest_prop, prop_map[i].def_val);
}
ret = property_get("ro.boot.console", tmp);
if (ret)
strlcpy(console, tmp, sizeof(console));
/* save a copy for init's usage during boot */
property_get("ro.bootmode", tmp);
strlcpy(bootmode, tmp, sizeof(bootmode));
/* if this was given on kernel command line, override what we read
* before (e.g. from /proc/cpuinfo), if anything */
ret = property_get("ro.boot.hardware", tmp);
if (ret)
strlcpy(hardware, tmp, sizeof(hardware));
property_set("ro.hardware", hardware);
snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
property_set("ro.revision", tmp);
/* TODO: these are obsolete. We should delete them */
if (!strcmp(bootmode,"factory"))
property_set("ro.factorytest", "1");
else if (!strcmp(bootmode,"factory2"))
property_set("ro.factorytest", "2");
else
property_set("ro.factorytest", "0");
这段红色部分的code就是从 ro.boot.hardware 属性里面取出值来, 然后设置属性
property_set(“ro.hardware”, hardware);
这个就是ro.hardware 的来历, 而且我们kernel 启动参数里面如果有androidboot.hardware 的话, 是会覆盖proc cpuinfo里面的值的