u-boot 要傳參數到kernel可使用 setenv bootargs
cmd line sample
# setenv bootargs androidboot.selinux=disable
# saveenv
code sample
setenv("bootargs", "androidboot.selinux=disable");
但是在android時, 會在image-android.c中的android_image_get_kernel讀取boot.img中的bootargs
boot.img的bootargs放在 BOARD_KERNEL_CMDLINE
BOARD_KERNEL_CMDLINE := console=ttymxc4,115200 init=/init
需注意的是如果code當中有設bootargs的話, 那在android_image_get_kernel就不會使用BOARD_KERNEL_CMDLINE設定的bootargs
int len = 0;
if (*hdr->cmdline) {
len += strlen(hdr->cmdline);
}
char *bootargs = getenv("bootargs");
if (bootargs)
len += strlen(bootargs);
char *newbootargs = malloc(len + 2);
if (!newbootargs) {
puts("Error: malloc in android_image_get_kernel failed!\n");
return -ENOMEM;
}
*newbootargs = '\0';
if (bootargs) {
strcpy(newbootargs, bootargs);
} else if (*hdr->cmdline) {
strcat(newbootargs, hdr->cmdline);
}
接著bootargs會傳到proc/cmdline, 可使用cat來確認傳入的parameter.
若要再交給android做為properties使用, 那可以在bootargs增加androidboot.xxx=xxx
在system/core/init/init.c當中會去處理bootargs.
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); //read kernel parameter here
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();
}
void import_kernel_cmdline(int in_qemu,
void (*import_kernel_nv)(char *name, int in_qemu))
{
char cmdline[2048];
char *ptr;
int fd;
fd = open("/proc/cmdline", O_RDONLY);
if (fd >= 0) {
int n = read(fd, cmdline, sizeof(cmdline) - 1);
if (n < 0) n = 0;
/* get rid of trailing newline, it happens */
if (n > 0 && cmdline[n-1] == '\n') n--;
cmdline[n] = 0;
close(fd);
} else {
cmdline[0] = 0;
}
ptr = cmdline;
while (ptr && *ptr) {
char *x = strchr(ptr, ' ');
if (x != 0) *x++ = 0;
import_kernel_nv(ptr, in_qemu);
ptr = x;
}
}
在import_kernel_nv當中會將androidboot.xxx都換成ro.boot.xxx
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 (!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); //change to ro.boot.xxx here
if (cnt < PROP_NAME_MAX)
property_set(prop, value);
}
}
所以如果一開始有設置androidboot.selinux=disable的話, 在經過這邊之後會被換成ro.boot.selinux=disable, boot進android之後使用getprop就可以看到了.
另外一些特定的properties則會經過export_kernel_boot_props再parsing一次.
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", },
};