Now that we have support for calling protocols that need additional marshalling for mixed mode, wire up the initrd command line loader. Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> --- arch/x86/include/asm/efi.h | 11 +++ drivers/firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 81 +++++++++++++------- drivers/firmware/efi/libstub/file.c | 34 ++++---- 4 files changed, 84 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 8edead8568ec..9e56bd489b29 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -325,6 +325,17 @@ static inline u32 efi64_convert_status(efi_status_t status) #define __efi64_argmap_set_memory_space_attributes(phys, size, flags) \ (__efi64_split(phys), __efi64_split(size), __efi64_split(flags)) +/* file protocol */ +#define __efi64_argmap_open(prot, newh, fname, mode, attr) \ + ((prot), efi64_zero_upper(newh), (fname), __efi64_split(mode), \ + __efi64_split(attr)) + +#define __efi64_argmap_set_position(pos) (__efi64_split(pos)) + +/* file system protocol */ +#define __efi64_argmap_open_volume(prot, file) \ + ((prot), efi64_zero_upper(file)) + /* * The macros below handle the plumbing for the argument mapping. To add a * mapping for a specific EFI method, simply define a macro diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 3249d7927c88..37f42a1d1777 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -682,7 +682,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, unsigned long hard_limit) { if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) || - (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) + (IS_ENABLED(CONFIG_X86) && image == NULL)) return EFI_UNSUPPORTED; return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index d26d3d7b99c0..23b7880be11a 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -593,36 +593,63 @@ typedef struct { efi_char16_t filename[]; } efi_file_info_t; -typedef struct efi_file_protocol efi_file_protocol_t; - -struct efi_file_protocol { - u64 revision; - efi_status_t (__efiapi *open) (efi_file_protocol_t *, - efi_file_protocol_t **, - efi_char16_t *, u64, u64); - efi_status_t (__efiapi *close) (efi_file_protocol_t *); - efi_status_t (__efiapi *delete) (efi_file_protocol_t *); - efi_status_t (__efiapi *read) (efi_file_protocol_t *, - unsigned long *, void *); - efi_status_t (__efiapi *write) (efi_file_protocol_t *, - unsigned long, void *); - efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, u64 *); - efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, u64); - efi_status_t (__efiapi *get_info) (efi_file_protocol_t *, - efi_guid_t *, unsigned long *, - void *); - efi_status_t (__efiapi *set_info) (efi_file_protocol_t *, - efi_guid_t *, unsigned long, - void *); - efi_status_t (__efiapi *flush) (efi_file_protocol_t *); +typedef union efi_file_protocol efi_file_protocol_t; + +union efi_file_protocol { + struct { + u64 revision; + efi_status_t (__efiapi *open) (efi_file_protocol_t *, + efi_file_protocol_t **, + efi_char16_t *, u64, + u64); + efi_status_t (__efiapi *close) (efi_file_protocol_t *); + efi_status_t (__efiapi *delete) (efi_file_protocol_t *); + efi_status_t (__efiapi *read) (efi_file_protocol_t *, + unsigned long *, + void *); + efi_status_t (__efiapi *write) (efi_file_protocol_t *, + unsigned long, void *); + efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, + u64 *); + efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, + u64); + efi_status_t (__efiapi *get_info) (efi_file_protocol_t *, + efi_guid_t *, + unsigned long *, + void *); + efi_status_t (__efiapi *set_info) (efi_file_protocol_t *, + efi_guid_t *, + unsigned long, + void *); + efi_status_t (__efiapi *flush) (efi_file_protocol_t *); + }; + struct { + u64 revision; + u32 open; + u32 close; + u32 delete; + u32 read; + u32 write; + u32 get_position; + u32 set_position; + u32 get_info; + u32 set_info; + u32 flush; + } mixed_mode; }; -typedef struct efi_simple_file_system_protocol efi_simple_file_system_protocol_t; +typedef union efi_simple_file_system_protocol efi_simple_file_system_protocol_t; -struct efi_simple_file_system_protocol { - u64 revision; - int (__efiapi *open_volume)(efi_simple_file_system_protocol_t *, - efi_file_protocol_t **); +union efi_simple_file_system_protocol { + struct { + u64 revision; + efi_status_t (__efiapi *open_volume)(efi_simple_file_system_protocol_t *, + efi_file_protocol_t **); + }; + struct { + u64 revision; + u32 open_volume; + } mixed_mode; }; #define EFI_FILE_MODE_READ 0x0000000000000001 diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c index 972ecc97b1d1..b16c6bdc9359 100644 --- a/drivers/firmware/efi/libstub/file.c +++ b/drivers/firmware/efi/libstub/file.c @@ -51,17 +51,18 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, *c = L'\\'; } - status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); + status = efi_call_proto(volume, open, &fh, fi->filename, + EFI_FILE_MODE_READ, 0); if (status != EFI_SUCCESS) { efi_err("Failed to open file: %ls\n", fi->filename); return status; } info_sz = sizeof(struct finfo); - status = fh->get_info(fh, &info_guid, &info_sz, fi); + status = efi_call_proto(fh, get_info, &info_guid, &info_sz, fi); if (status != EFI_SUCCESS) { efi_err("Failed to get file info\n"); - fh->close(fh); + efi_call_proto(fh, close); return status; } @@ -73,7 +74,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, static efi_status_t efi_open_volume(efi_loaded_image_t *image, efi_file_protocol_t **fh) { - struct efi_vendor_dev_path *dp = image->file_path; + struct efi_vendor_dev_path *dp = efi_table_attr(image, file_path); efi_guid_t li_proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; efi_simple_file_system_protocol_t *io; @@ -95,14 +96,14 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image, } } - status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, - (void **)&io); + status = efi_bs_call(handle_protocol, efi_table_attr(image, device_handle), + &fs_proto, (void **)&io); if (status != EFI_SUCCESS) { efi_err("Failed to handle fs_proto\n"); return status; } - status = io->open_volume(io, fh); + status = efi_call_proto(io, open_volume, fh); if (status != EFI_SUCCESS) efi_err("Failed to open volume\n"); @@ -162,7 +163,8 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume, /* Convert the filename wide string into a device path */ - initrd_dp = text_to_dp->convert_text_to_device_path(fi->filename); + initrd_dp = efi_fn_call(text_to_dp, convert_text_to_device_path, + fi->filename); /* Check whether the device path in question implements simple FS */ if ((efi_bs_call(locate_device_path, &fs_proto, &initrd_dp, &handle) ?: @@ -184,7 +186,7 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume, min(sizeof(fi->filename), fpath->header.length - sizeof(fpath->header))); - status = io->open_volume(io, volume); + status = efi_call_proto(io, open_volume, volume); if (status != EFI_SUCCESS) efi_err("Failed to open volume\n"); @@ -205,8 +207,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, unsigned long *load_addr, unsigned long *load_size) { - const efi_char16_t *cmdline = image->load_options; - u32 cmdline_len = image->load_options_size; + const efi_char16_t *cmdline = efi_table_attr(image, load_options); + u32 cmdline_len = efi_table_attr(image, load_options_size); unsigned long efi_chunk_size = ULONG_MAX; efi_file_protocol_t *volume = NULL; efi_file_protocol_t *file; @@ -294,7 +296,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, while (size) { unsigned long chunksize = min(size, efi_chunk_size); - status = file->read(file, &chunksize, addr); + status = efi_call_proto(file, read, &chunksize, addr); if (status != EFI_SUCCESS) { efi_err("Failed to read file\n"); goto err_close_file; @@ -302,8 +304,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, addr += chunksize; size -= chunksize; } - file->close(file); - volume->close(volume); + efi_call_proto(file, close); + efi_call_proto(volume, close); } while (offset > 0); *load_addr = alloc_addr; @@ -312,10 +314,10 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, return EFI_SUCCESS; err_close_file: - file->close(file); + efi_call_proto(file, close); err_close_volume: - volume->close(volume); + efi_call_proto(volume, close); err_free_alloc: efi_free(alloc_size, alloc_addr); -- 2.35.1