arm64 device tree - boot_command_line的获取
作者:互联网
调用顺序
setup_arch(&command_line)->setup_machine_fdt(__fdt_pointer); 需要注意的是*command_line 是指向到 boot_command_line;而boot_command_line是一个静态数组,在 init/main.c 里面 char __initdata boot_command_line[COMMAND_LINE_SIZE]; 在arm64的环境下是2048,也就是说bootloader传递给kernel的commandline超过2048就要修改kernel源代码加这个数组加大。注意这个__fdt_pointer 是bootloader传递过来的,在 head.S 中保存到__fdt_pointer 这个变量里面的。
参考: https://www.cnblogs.com/zhangzhiwei122/p/16030978.html 中 primary_switched 函数
setup_machine_fdt
参考: https://www.cnblogs.com/zhangzhiwei122/p/16060453.html 在setup_machine_fdt 中现将代表devicetree的物理地址转成虚拟地址,然后调用early_init_dt_scan 来扫描devicetree中的chosen节点, 其中 chosen节点就表示bootloader传递给kernel的commandlineearly_init_dt_scan->early_init_dt_scan_nodes
drivers/of/fdt.c
1185void __init early_init_dt_scan_nodes(void) 1186{ 1187 int rc = 0; 1188 1189 /* Retrieve various information from the /chosen node */ 1190 rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); 1191 if (!rc) 1192 pr_warn("No chosen node found, continuing without\n"); 1193 1194 /* Initialize {size,address}-cells info */ 1195 of_scan_flat_dt(early_init_dt_scan_root, NULL); 1196 1197 /* Setup memory, calling early_init_dt_add_memory_arch */ 1198 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 1199}
1190 行,对每一个 node 调用 early_init_dt_scan_chosen 函数来处理。
early_init_dt_scan_chosen
1039int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, 1040 int depth, void *data) 1041{ 1042 int l; 1043 const char *p; 1044 const void *rng_seed; 1045 1046 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 1047 1048 if (depth != 1 || !data || 1049 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) 1050 return 0; 1051 1052 early_init_dt_check_for_initrd(node); 1053 1054 /* Retrieve command line */ 1055 p = of_get_flat_dt_prop(node, "bootargs", &l); 1056 if (p != NULL && l > 0) 1057 strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); 1058 1059 /* 1060 * CONFIG_CMDLINE is meant to be a default in case nothing else 1061 * managed to set the command line, unless CONFIG_CMDLINE_FORCE 1062 * is set in which case we override whatever was found earlier. 1063 */ 1064#ifdef CONFIG_CMDLINE 1065#if defined(CONFIG_CMDLINE_EXTEND) 1066 strlcat(data, " ", COMMAND_LINE_SIZE); 1067 strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 1068#elif defined(CONFIG_CMDLINE_FORCE) 1069 strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 1070#else 1071 /* No arguments from boot loader, use kernel's cmdl*/ 1072 if (!((char *)data)[0]) 1073 strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 1074#endif 1075#endif /* CONFIG_CMDLINE */ 1076 1077 pr_debug("Command line is: %s\n", (char *)data); 1078 1079 rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l); 1080 if (rng_seed && l > 0) { 1081 add_bootloader_randomness(rng_seed, l); 1082 1083 /* try to clear seed so it won't be found. */ 1084 fdt_nop_property(initial_boot_params, node, "rng-seed"); 1085 1086 /* update CRC check value */ 1087 of_fdt_crc32 = crc32_be(~0, initial_boot_params, 1088 fdt_totalsize(initial_boot_params)); 1089 } 1090 1091 /* break now */ 1092 return 1; 1093}1048 ~ 1050 如果不是 choose 节点,就 return .
1055 是 choose 节点, 通过p = of_get_flat_dt_prop(node, "bootargs", &l); 得到chosen节点中的bootargs,这个就代表commandline
1057 strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));将commandline copy到boot_command_line中 1064 ~ 1075 处理 CONFIG_CMDLINE 宏,这个宏是 meke menuconfig 时,填入的字符串。 默认操作,如果 bootloader 没有传递参数,才使用 CONFIG_CMDLINE CMDLINE_EXTEND , 追加 CONFIG_CMDLINE CMDLINE_FORCE,使用 CONFIG_CMDLINE 覆盖 bootloader 的参数。
devicetree 中的chosen 节点大概是下面这样
chosen {
bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
stdout-path = "serial0:115200n8";
};
标签:scan,chosen,tree,boot,CMDLINE,init,command,dt,CONFIG 来源: https://www.cnblogs.com/zhangzhiwei122/p/16060542.html