Skip to content

Commit

Permalink
efi/libstub: Rewrite file I/O routine
Browse files Browse the repository at this point in the history
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
  pointless since we only handle initrd or dtb arguments provided via
  the loaded image protocol anyway, which is where we got the UTF-16[]
  command line from in the first place when booting via the PE entry
  point,
- in the far majority of cases, only a single initrd= option is present,
  but it optimizes for multiple options, by going over the command line
  twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
  including string parsing etc all combined in a single routine.

Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
  • Loading branch information
Ard Biesheuvel committed Feb 23, 2020
1 parent 5193a33 commit 9302c1b
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 228 deletions.
12 changes: 4 additions & 8 deletions drivers/firmware/efi/libstub/arm-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
unsigned long dram_base;
/* addr/point and size pairs for memory management*/
unsigned long initrd_addr;
u64 initrd_size = 0;
unsigned long initrd_size = 0;
unsigned long fdt_addr = 0; /* Original DTB */
unsigned long fdt_size = 0;
char *cmdline_ptr = NULL;
Expand Down Expand Up @@ -247,8 +247,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
if (strstr(cmdline_ptr, "dtb="))
pr_efi("Ignoring DTB from command line.\n");
} else {
status = handle_cmdline_files(image, cmdline_ptr, "dtb=",
~0UL, &fdt_addr, &fdt_size);
status = efi_load_dtb(image, &fdt_addr, &fdt_size);

if (status != EFI_SUCCESS) {
pr_efi_err("Failed to load device tree!\n");
Expand All @@ -268,11 +267,8 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
if (!fdt_addr)
pr_efi("Generating empty DTB\n");

status = handle_cmdline_files(image, cmdline_ptr, "initrd=",
efi_get_max_initrd_addr(dram_base,
image_addr),
(unsigned long *)&initrd_addr,
(unsigned long *)&initrd_size);
status = efi_load_initrd(image, &initrd_addr, &initrd_size,
efi_get_max_initrd_addr(dram_base, image_addr));
if (status != EFI_SUCCESS)
pr_efi_err("Failed initrd from command line!\n");

Expand Down
17 changes: 10 additions & 7 deletions drivers/firmware/efi/libstub/efistub.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ typedef struct {
efi_time_t last_access_time;
efi_time_t modification_time;
__aligned_u64 attribute;
efi_char16_t filename[1];
efi_char16_t filename[];
} efi_file_info_t;

typedef struct efi_file_protocol efi_file_protocol_t;
Expand Down Expand Up @@ -607,15 +607,18 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
unsigned long alignment,
unsigned long min_addr);

efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
char *cmd_line, char *option_string,
unsigned long max_addr,
unsigned long *load_addr,
unsigned long *load_size);

efi_status_t efi_parse_options(char const *cmdline);

efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
unsigned long size);

efi_status_t efi_load_dtb(efi_loaded_image_t *image,
unsigned long *load_addr,
unsigned long *load_size);

efi_status_t efi_load_initrd(efi_loaded_image_t *image,
unsigned long *load_addr,
unsigned long *load_size,
unsigned long max_addr);

#endif
Loading

0 comments on commit 9302c1b

Please sign in to comment.