[boot_command_line,cmdline,commandline,devicetree地址]
head.S->start_kernel(), head.S mainly obtains the address of dt:
str_l x21, __fdt_pointer, x5 // Save FDT pointer
>>start_kernel() -- main.c
>>setup_arch() --setup.c
>>setup_machine_fdt()
>>early_init_dt_scan() --fdt.c
>>early_init_dt_verify() --fdt.c ; After checking __fdt_pointer , assign it to initial_boot_params
>> early_init_dt_scan_nodes() --fdt.c ; finally get devicetree parameters
>> early_init_dt_scan_chosen --fdt.c; get command line parameters
setup_arch(&command_line);
command_line is a reference to the global variable boot_command_line
setup_machine_fdt()
After __fdt_pointer is mapped by fixmap_remap_fdt(dt_phys), pass the parameters down
early_init_dt_scan_nodes
Get the command_line parameter and assign a value to boot_command_line
Get the memory parameter
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
int depth, void *data)
{
int l;
const char *p;pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
if (depth != 1 || !data ||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;early_init_dt_check_for_initrd(node);
/* Retrieve command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); //拷贝到 boot_command_line/*
* CONFIG_CMDLINE is meant to be a default in case nothing else
* managed to set the command line, unless CONFIG_CMDLINE_FORCE
* is set in which case we override whatever was found earlier.
*/
#ifdef CONFIG_CMDLINE
#if defined(CONFIG_CMDLINE_EXTEND)
strlcat(data, " ", COMMAND_LINE_SIZE);
strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
/* No arguments from boot loader, use kernel's cmdl*/
if (!((char *)data)[0])
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */pr_debug("Command line is: %s\n", (char*)data);
/* break now */
return 1;
}
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);
}
bootloader parameter passing
Our usual method is to pass directly through bootargs (arm64) in the bootload, just modify it in the BootLinuxBootParamlistPtr.CmdLine
function, and paste a string ( ql_crash_mode=0,0
) behind the variable. In the UpdateCmdLine function, a series (many, many) cmdlines are preprocessed
EFI_STATUS BootLinux (BootInfo *Info)
{xxxxxxxxxx
#ifdef QL_DEBUG_MODE
if ( Info->BootWithDebug == TRUE){
AsciiStrCatS (BootParamlistPtr.CmdLine, BOOT_ARGS_SIZE, " debug=1");
}
#endif#ifdef QL_DUMP_MODE
if ( Info->BootWithDump == TRUE){
AsciiStrCatS (BootParamlistPtr.CmdLine, BOOT_ARGS_SIZE, " ql_crash_mode=0,0");
}
#endif
Status = UpdateCmdLine (BootParamlistPtr.CmdLine, FfbmStr, Recovery,
AlarmBoot, Info->VBCmdLine, &BootParamlistPtr.FinalCmdLine,
&BootParamlistPtr.FinalBootConfig,
&BootParamlistPtr.FinalBootConfigLen,
Info->HeaderVersion,
(VOID *)BootParamlistPtr.DeviceTreeLoadAddr);xxxxxxxxxx
Status = LoadAddrAndDTUpdate (Info, &BootParamlistPtr);
if (Status != EFI_SUCCESS) {
return Status;
}
xxxxxxxxxx
}
After the processing of UpdateCmdLine is completed, LoadAddrAndDTUpdate carries the BootParamlistPtr parameter and after a series of subsequent calls, all the data recorded in cmdline will be added to the device node of bootargs in the UpdateDeviceTree function.
EFI_STATUS UpdateDeviceTree (VOID *fdt,CONST CHAR8 *cmdline,VOID *ramdisk,UINT32 RamDiskSize,BOOLEAN BootWith32Bit)
{
xxxxxxxxxxxx
if (cmdline) {
/* Adding the cmdline to the chosen node */
FdtPropUpdateFunc (fdt, offset, (CONST char *)"bootargs",
(CONST VOID *)cmdline, fdt_appendprop_string, ret);
if (ret) {
DEBUG ((EFI_D_ERROR,
"ERROR: Cannot update chosen node [bootargs] - 0x%x\n", ret));
return EFI_LOAD_ERROR;
}
}
xxxxxxxxxxxx
}
FdtPropUpdateFunc: add parameters to fdt bootargs
Parameter reception processing
After the bootload is transferred to the cmdline, we only need to add the kernel parameter processing function at the appropriate position. If the parameter passed by the bootloader when starting the kernel is "ql_crash_mode=xxx", the set_crash_mode function will be called automatically when the kernel is running, and the parameters carried by the cmdline will be brought into the function through the s parameter.
static int __init set_crash_mode(char *s)
{
xxxxxxxxxx
}
__setup("ql_crash_mode=", set_crash_mode);
Note: Refer to the kernel parameter cmdline follow-up processing source code analysis-1