linux cmdline介绍
uboot向内核传递bootargs参数有两种方式,一种是通过truct tag 数据结构,U-boot 把要传递给 kernel 的东西保存在 struct tag 数据结构中,启动 kernel 时,把这个结构体的物理地址传给 kernel ; Linux kernel 通过这个地址,用 parse_tags 分析出传递过来的参数。另一种是通过设备树的bootargs节点,uboot把bootargs参数写入到设备数的bootargs节点中,内核启动时会去设备树读取保存在cmdline中。下面讨论一下设备树的传递方式。
在run_main_loop中uboot启动等待几秒没进入命令模式就会执行bootcmd启动内核,这个命令会执行以下几个函数来设置bootargs到设备数中:
-->do_bootm_linux //uboot/arch/arm/lib/bootm.c
-->boot_prep_linux //可以在这个函数中加一些自己定义的参数
-->image_setup_linux //uboot/common/image.c
-->image_setup_libfdt //uboot/common/image-fdt.c
-->fdt_chosen //这个函数会将ubootde bootargs参数写入到设备数bootargs节点中
在kernel/init/main.c中定义了一个全局变量boot_command_line,该变量就是用来存放/proc/cmdline 的内容
下面看一/proc/cmdline是如何获取的
-->start_kernel //kernel/init/main.c
-->setup_arch //kernel/arch/arm64/kernel/setup.c
-->setup_machine_fdt
-->early_init_dt_scan
-->early_init_dt_scan_nodes //kernel/drivers/of/fdt.c
setup_machine_fdt 函数位于kernel/arch/arm64/kernel/setup.c中
static void __init setup_machine_fdt(phys_addr_t dt_phys) { void *dt_virt = fixmap_remap_fdt(dt_phys); //dt_phys是设备树的物理地址,这里转换为虚拟地址 const char *name; if (!dt_virt || !early_init_dt_scan(dt_virt)) { //这个函数将获取设备树bootargs节点的值保存在boot_command_line全局变量中 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(); //这个函数是获取设备数中model的值 if (!name) return; pr_info("Machine model: %s\n", name); dump_stack_set_arch_desc("%s (DT)", name); }