当前位置: 首页 > 工具软件 > FDT > 使用案例 >

cmdline -[command line,__fdt_pointer,initial_boot_params] boot_command_line 获取

孟浩然
2023-12-01

[boot_command_line,cmdline,commandline,devicetree地址]

head.S->start_kernel(), head.S 中主要是获取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 ;check __fdt_pointer后,赋给initial_boot_params

                                >>early_init_dt_scan_nodes()  --fdt.c ;最终获取devicetree参数

                                     >>early_init_dt_scan_chosen --fdt.c; 获取command line 参数

setup_arch(&command_line);

command_line 是对 全局变量boot_command_line的一个引用

setup_machine_fdt()

__fdt_pointer 经过fixmap_remap_fdt(dt_phys) 映射后,往下传参

early_init_dt_scan_nodes

获取 command_line参数,给boot_command_line 赋值

获取memory参数

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 参数传递 

我们常用的方式是在bootload中通过bootargs直接传递(arm64) ,只需要在BootLinux函数中修改即可,往BootParamlistPtr.CmdLine变量后面粘贴一个字符串(ql_crash_mode=0,0)。在UpdateCmdLine函数中会对一系列(很多很多)的cmdline进行预处理

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
}
 

 

UpdateCmdLine处理完成后,由LoadAddrAndDTUpdate携带BootParamlistPtr参数经过后续一系列调用后,最终会在UpdateDeviceTree 函数中将cmdline中记录的所有数据全部添加到bootargs的设备节点中 

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 :将参数添加到fdt bootargs中

参数接收处理

 bootload传输过来cmdline之后,我们只需要在适当的位置添加内核参数的处理函数。假如bootloader在启动kernel时传递的参数是"ql_crash_mode=xxx",kernel运行的时候就会自动调用set_crash_mode函数,通过s参数将cmdline携带的参数带入函数。

static int __init set_crash_mode(char *s)

{

xxxxxxxxxx

}

__setup("ql_crash_mode=", set_crash_mode);

注:参照 内核参数cmdline后续处理源码分析-1

 类似资料: