cmdline
1、向linux kernel添加cmdline的四种方式
(1)、 在dts中的bootargs中添加
(2)、在BoardConfig中添加
(3)、在uboot中添加
(4)、在android的Makefile中添加
2、在uboot中,将cmdline统一放置在FDT中
3、在kernel中,从FDT中解析处cmdline并使用
(1)、跳转linux kernel之前-准备cmdline
(2)、kernel启动-解析cmdline
1、向linux kernel添加cmdline的四种方式
在linux启动时候,串口log中会打印cmdline
[ 0.000000] c0 0 (swapper) Kernel command line: earlycon androidboot.selinux=permissive uart_dma keep_dbgclk_on clk_ignore_unused initrd=0xd0000000,38711808 rw crash_page=0x8f040000 initrd=/recoveryrc boot_reason=0x2000 ota_status=0x1001
在linux启动完成后,通过 cat /proc/cmdline也是可以看到cmdline. 那么cmdline是如何添加的呢?
(1)、 在dts中的bootargs中添加
-
/ {
-
model = "yyyyyyy";
-
compatible = "yyyyyyy", "xxxxxxxx";
-
chosen {
-
/*
-
* initrd parameters not set in dts file since the ramdisk.img size
-
* need to check in uboot, and the initrd load address and size will
-
* set in uboot stage.
-
*/
-
bootargs = "earlycon androidboot.selinux=permissive uart_dma keep_dbgclk_on clk_ignore_unused";
-
stdout-path = "serial0:115200";
-
};
-
......
-
}
(2)、在BoardConfig中添加
vim device/xxx/xxx_evb/BoardConfigCommon.mk
BOARD_KERNEL_CMDLINE += androidboot.selinux=enforcing androidboot.hardware=xxxx_phone androidboot.dtbo_idx=0
(3)、在uboot中添加
vim u-boot/common/cmd_bootm.c
-
append_bootargs("recovery=1");
-
sprintf(dm_buf,"init=/init skip_initramfs rootwait root=/dev/dm-0 dm="system none ro,0 1 android-verity /dev/mmcblk0p%d"",ret);
-
append_bootargs((const char *)dm_buf);
2、在uboot中,将cmdline统一放置在FDT中
以后再写,哈哈哈哈
3、在kernel中,从FDT中解析处cmdline并使用
(1)、跳转linux kernel之前-准备cmdline
在跳转linux kernel之前(如uboot中),将cmdline数据放到了FDT中,然后将FDT的地址写入到了X0中。然后再跳转linux kernel.
别问我怎么知道的,请看kernel-4.14/Documentation/arm64/booting.txt
-
Before jumping into the kernel, the following conditions must be met:
-
- Quiesce all DMA capable devices so that memory does not get
-
corrupted by bogus network packets or disk data. This will save
-
you many hours of debug.
-
- Primary CPU general-purpose register settings
-
x0 = physical address of device tree blob (dtb) in system RAM.
-
x1 = 0 (reserved for future use)
-
x2 = 0 (reserved for future use)
-
x3 = 0 (reserved for future use)
(2)、kernel启动-解析cmdline
linux kernel从stext开始启动,整个流程大概就是读取X0(FDT地址)保存到X21中,又将X21保存到__fdt_pointer全局变量中
然后再将__fdt_pointer解析处cmdline数据到boot_command_line全局变量中
-
/*
-
- The following callee saved general purpose registers are used on the
-
- primary lowlevel boot path:
-
-
* Register Scope Purpose
-
* x21 stext() .. start_kernel() FDT pointer passed at boot in x0
-
* x23 stext() .. start_kernel() physical misalignment/KASLR offset
-
* x28 __create_page_tables() callee preserved temp register
-
* x19/x20 __primary_switch() callee preserved temp registers
-
*/
-
ENTRY(stext)
-
bl preserve_boot_args
-
bl el2_setup // Drop to EL1, w0=cpu_boot_mode
-
adrp x23, __PHYS_OFFSET
-
and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0
-
bl set_cpu_boot_mode_flag
-
bl __create_page_tables
-
/*
-
- The following calls CPU setup code, see arch/arm64/mm/proc.S for
-
- details.
-
- On return, the CPU will be ready for the MMU to be turned on and
-
- the TCR will have been set.
-
*/
-
bl __cpu_setup // initialise processor
-
b __primary_switch
-
ENDPROC(stext)
这里调用了:
preserve_boot_args
__primary_switch
在preserve_boot_args将X0(fdt地址)暂时先保存到了X21中
-
preserve_boot_args:
-
mov x21, x0 // x21=FDT
-
adr_l x0, boot_args // record the contents of
-
stp x21, x1, [x0] // x0 .. x3 at kernel entry
-
stp x2, x3, [x0, #16]
-
dmb sy // needed before dc ivac with
-
// MMU off
-
mov x1, #0x20 // 4 x 8 bytes
-
b __inval_dcache_area // tail call
-
ENDPROC(preserve_boot_args)
-
__primary_switch调用了__primary_switched
-
__primary_switch:
-
#ifdef CONFIG_RANDOMIZE_BASE
-
mov x19, x0 // preserve new SCTLR_EL1 value
-
mrs x20, sctlr_el1 // preserve old SCTLR_EL1 value
-
#endif
-
bl __enable_mmu
-
#ifdef CONFIG_RELOCATABLE
-
bl __relocate_kernel
-
#ifdef CONFIG_RANDOMIZE_BASE
-
ldr x8, =__primary_switched
-
adrp x0, __PHYS_OFFSET
-
blr x8
__primary_switched将X21(fdt地址)保存到了__fdt_pointer全局变量中
-
__primary_switched:
-
adrp x4, init_thread_union
-
add sp, x4, #THREAD_SIZE
-
adr_l x5, init_task
-
msr sp_el0, x5 // Save thread_info
-
adr_l x8, vectors // load VBAR_EL1 with virtual
-
msr vbar_el1, x8 // vector table address
-
isb
-
stp xzr, x30, [sp, #-16]!
-
mov x29, sp
-
str_l x21, __fdt_pointer, x5 // Save FDT pointer
-
ldr_l x4, kimage_vaddr // Save the offset between
-
sub x4, x4, x0 // the kernel virtual and
-
str_l x4, kimage_voffset, x5 // physical mappings
-
// Clear BSS
-
adr_l x0, __bss_start
-
mov x1, xzr
-
adr_l x2, __bss_stop
-
sub x2, x2, x0
-
bl __pi_memset
-
dsb ishst // Make zero page visible to PTW
在setup_arch()的时候,调用setup_machine_fdt将fdt解析到了boot_command_line全局变量中
-
void __init setup_arch(char **cmdline_p)
-
{
-
pr_info("Boot CPU: AArch64 Processor [%08x]\n", read_cpuid_id());
-
......
-
*cmdline_p = boot_command_line;
-
......
-
setup_machine_fdt(__fdt_pointer);
-
......
-
}
setup_machine_fdt()—>early_init_dt_scan()—>early_init_dt_scan_nodes()
在中,将fdt解析到了boot_command_line中
-
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line)
-
static void __init setup_machine_fdt(phys_addr_t dt_phys)
-
{
-
void *dt_virt = fixmap_remap_fdt(dt_phys);
-
const char *name;
-
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
-
pr_crit("\n"
-
"Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n"
-
"The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
-
"\nPlease check your bootloader.",
-
&dt_phys, dt_virt);
-
while (true)
-
cpu_relax();
-
}
-
name = of_flat_dt_get_machine_name();
-
if (!name)
-
return;
-
/* backward-compatibility for third-party applications */
-
machine_desc_set(name);
-
pr_info("Machine model: %s\n", name);
-
dump_stack_set_arch_desc("%s (DT)", name);
-
}
-
bool __init early_init_dt_scan(void *params)
-
{
-
bool status;
-
-
status = early_init_dt_verify(params);
-
if (!status)
-
return false;
-
-
early_init_dt_scan_nodes();
-
return true;
-
}
-
void __init early_init_dt_scan_nodes(void)
-
{
-
/* Retrieve various information from the /chosen node */
-
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-
-
/* Initialize {size,address}-cells info */
-
of_scan_flat_dt(early_init_dt_scan_root, NULL);
-
-
/* Setup memory, calling early_init_dt_add_memory_arch */
-
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
}
在start_kernel()打印了cmdline.
asmlinkage __visible void __init start_kernel(void)
{
…
pr_notice(“Kernel command line: %s\n”, boot_command_line);
…
}