Signed-off-by: Michael Olbrich <m.olbrich@xxxxxxxxxxxxxx> --- v2: use xstrdup_char_to_wchar() arch/efi/efi/efi-image.c | 57 ++++++++++++++++++++++++++++++++++++++---------- include/efi.h | 2 +- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c index f7bda8dfcb2a..c88b3a0766ed 100644 --- a/arch/efi/efi/efi-image.c +++ b/arch/efi/efi/efi-image.c @@ -37,14 +37,13 @@ #include <mach/efi.h> #include <mach/efi-device.h> -static int efi_execute_image(const char *file) +int efi_load_image(const char *file, efi_loaded_image_t **loaded_image, + efi_handle_t *h) { void *exe; size_t size; efi_handle_t handle; - efi_status_t efiret; - const char *options; - efi_loaded_image_t *loaded_image; + efi_status_t efiret = EFI_SUCCESS; exe = read_file(file, &size); if (!exe) @@ -54,25 +53,59 @@ static int efi_execute_image(const char *file) &handle); if (EFI_ERROR(efiret)) { pr_err("failed to LoadImage: %s\n", efi_strerror(efiret)); - return -efi_errno(efiret);; + goto out; }; efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid, - (void **)&loaded_image, + (void **)loaded_image, efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (EFI_ERROR(efiret)) - return -efi_errno(efiret); + if (EFI_ERROR(efiret)) { + pr_err("failed to OpenProtocol: %s\n", efi_strerror(efiret)); + BS->unload_image(handle); + goto out; + } - options = linux_bootargs_get(); - loaded_image->load_options = strdup_char_to_wchar(options); - loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t); + *h = handle; +out: + memset(exe, 0, size); + free(exe); + return -efi_errno(efiret); +} + +static int efi_execute_image(const char *file) +{ + efi_handle_t handle; + efi_loaded_image_t *loaded_image; + efi_status_t efiret; + struct linux_kernel_header *image_header; + const char *options; + int ret; + + ret = efi_load_image(file, &loaded_image, &handle); + if (ret) + return ret; + + image_header = (struct linux_kernel_header *)loaded_image->image_base; + if (image_header->boot_flag == 0xAA55 && + image_header->header == 0x53726448) { + pr_debug("Linux kernel detected. Adding bootargs."); + options = linux_bootargs_get(); + pr_err("add linux options '%s'\n", options); + loaded_image->load_options = xstrdup_char_to_wchar(options); + loaded_image->load_options_size = + (strlen(options) + 1) * sizeof(wchar_t); + } efiret = BS->start_image(handle, NULL, NULL); + if (EFI_ERROR(efiret)) + pr_err("failed to StartImage: %s\n", efi_strerror(efiret)); + + BS->unload_image(handle); efi_connect_all(); efi_register_devices(); - return 0; + return -efi_errno(efiret); } static int do_bootm_efi(struct image_data *data) diff --git a/include/efi.h b/include/efi.h index 9b4f16bd9f54..e79a407bc2c8 100644 --- a/include/efi.h +++ b/include/efi.h @@ -211,7 +211,7 @@ typedef struct { unsigned long *exitdata_size, s16 **exitdata); efi_status_t(EFIAPI *exit)(efi_handle_t handle, efi_status_t exit_status, unsigned long exitdata_size, s16 *exitdata); - void *unload_image; + efi_status_t (EFIAPI *unload_image)(efi_handle_t handle); efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long); void *get_next_monotonic_count; efi_status_t (EFIAPI *stall)(unsigned long usecs); -- 2.1.4 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox