在efi_entry 中会通过下面的code从uefi中拿到cmdline
cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
if (!cmdline_ptr) {
pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
goto fail;
}
char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
efi_loaded_image_t *image,
int *cmd_line_len)
{
const u16 *s2;
u8 *s1 = NULL;
unsigned long cmdline_addr = 0;
int load_options_chars = image->load_options_size / 2; /* UTF-16 */
const u16 *options = image->load_options;
int options_bytes = 0; /* UTF-8 bytes */
int options_chars = 0; /* UTF-16 chars */
efi_status_t status;
u16 zero = 0;
if (options) {
s2 = options;
while (*s2 && *s2 != '\n'
&& options_chars < load_options_chars) {
options_bytes += efi_utf8_bytes(*s2++);
options_chars++;
}
}
if (!options_chars) {
/* No command line options, so return empty string*/
options = &zero;
}
options_bytes++; /* NUL termination */
status = efi_high_alloc(sys_table_arg, options_bytes, 0,
&cmdline_addr, MAX_CMDLINE_ADDRESS);
if (status != EFI_SUCCESS)
return NULL;
s1 = (u8 *)cmdline_addr;
s2 = (const u16 *)options;
s1 = efi_utf16_to_utf8(s1, s2, options_chars);
*s1 = '\0';
*cmd_line_len = options_bytes;
return (char *)cmdline_addr;
}
在efi_convert_cmdline 的image代表loaded image的protoc
status = sys_table->boottime->handle_protocol(handle,
&loaded_image_proto, (void *)&image);
然后在efi_convert_cmdline中首先image->load_options 拿到cmdline,然后将cmdline从utf16转成utf8返回。
然后会在allocate_new_fdt_and_exit_boot -> update_fdt中将cmdline_ptr中的内容copy到chosen中
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
unsigned long orig_fdt_size,
void *fdt, int new_fdt_size, char *cmdline_ptr,
u64 initrd_addr, u64 initrd_size,
efi_memory_desc_t *memory_map,
unsigned long map_size, unsigned long desc_size,
u32 desc_ver)
{
num_rsv = fdt_num_mem_rsv(fdt);
while (num_rsv-- > 0)
fdt_del_mem_rsv(fdt, num_rsv);
node = fdt_subnode_offset(fdt, 0, "chosen");
if (node < 0) {
node = fdt_add_subnode(fdt, 0, "chosen");
if (node < 0) {
status = node; /* node is error code when negative */
goto fdt_set_fail;
}
}
if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
strlen(cmdline_ptr) + 1);
if (status)
goto fdt_set_fail;
}
}
在update_fdt中可以看到是通过fdt_setprop 将cmdline_ptr 中的内容copy到chosen节点中的bootargs中.
cmdline_ptr = efi_convert_cmdline(sys_table, image, &cmdline_size);
if (!cmdline_ptr) {
pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n");
goto fail;
}
char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
efi_loaded_image_t *image,
int *cmd_line_len)
{
const u16 *s2;
u8 *s1 = NULL;
unsigned long cmdline_addr = 0;
int load_options_chars = image->load_options_size / 2; /* UTF-16 */
const u16 *options = image->load_options;
int options_bytes = 0; /* UTF-8 bytes */
int options_chars = 0; /* UTF-16 chars */
efi_status_t status;
u16 zero = 0;
if (options) {
s2 = options;
while (*s2 && *s2 != '\n'
&& options_chars < load_options_chars) {
options_bytes += efi_utf8_bytes(*s2++);
options_chars++;
}
}
if (!options_chars) {
/* No command line options, so return empty string*/
options = &zero;
}
options_bytes++; /* NUL termination */
status = efi_high_alloc(sys_table_arg, options_bytes, 0,
&cmdline_addr, MAX_CMDLINE_ADDRESS);
if (status != EFI_SUCCESS)
return NULL;
s1 = (u8 *)cmdline_addr;
s2 = (const u16 *)options;
s1 = efi_utf16_to_utf8(s1, s2, options_chars);
*s1 = '\0';
*cmd_line_len = options_bytes;
return (char *)cmdline_addr;
}
在efi_convert_cmdline 的image代表loaded image的protoc
status = sys_table->boottime->handle_protocol(handle,
&loaded_image_proto, (void *)&image);
然后在efi_convert_cmdline中首先image->load_options 拿到cmdline,然后将cmdline从utf16转成utf8返回。
然后会在allocate_new_fdt_and_exit_boot -> update_fdt中将cmdline_ptr中的内容copy到chosen中
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
unsigned long orig_fdt_size,
void *fdt, int new_fdt_size, char *cmdline_ptr,
u64 initrd_addr, u64 initrd_size,
efi_memory_desc_t *memory_map,
unsigned long map_size, unsigned long desc_size,
u32 desc_ver)
{
num_rsv = fdt_num_mem_rsv(fdt);
while (num_rsv-- > 0)
fdt_del_mem_rsv(fdt, num_rsv);
node = fdt_subnode_offset(fdt, 0, "chosen");
if (node < 0) {
node = fdt_add_subnode(fdt, 0, "chosen");
if (node < 0) {
status = node; /* node is error code when negative */
goto fdt_set_fail;
}
}
if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
strlen(cmdline_ptr) + 1);
if (status)
goto fdt_set_fail;
}
}
在update_fdt中可以看到是通过fdt_setprop 将cmdline_ptr 中的内容copy到chosen节点中的bootargs中.