diff options
Diffstat (limited to 'arch/efi/efi/efi-image.c')
-rw-r--r-- | arch/efi/efi/efi-image.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c new file mode 100644 index 0000000000..18757d2697 --- /dev/null +++ b/arch/efi/efi/efi-image.c @@ -0,0 +1,105 @@ +/* + * efi-image.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <sizes.h> +#include <memory.h> +#include <command.h> +#include <magicvar.h> +#include <init.h> +#include <driver.h> +#include <io.h> +#include <efi.h> +#include <malloc.h> +#include <string.h> +#include <linux/err.h> +#include <boot.h> +#include <fs.h> +#include <binfmt.h> +#include <wchar.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +static int efi_execute_image(const char *file) +{ + void *exe; + size_t size; + efi_handle_t handle; + efi_status_t efiret; + const char *options; + efi_loaded_image_t *loaded_image; + + exe = read_file(file, &size); + if (!exe) + return -EINVAL; + + efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size, + &handle); + if (EFI_ERROR(efiret)) { + pr_err("failed to LoadImage: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret);; + }; + + efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid, + (void **)&loaded_image, + efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + options = linux_bootargs_get(); + loaded_image->load_options = strdup_char_to_wchar(options); + loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t); + + efiret = BS->start_image(handle, NULL, NULL); + + efi_connect_all(); + efi_register_devices(); + + return 0; +} + +static int do_bootm_efi(struct image_data *data) +{ + return efi_execute_image(data->os_file); +} + +static struct image_handler efi_handle_tr = { + .name = "EFI Application", + .bootm = do_bootm_efi, + .filetype = filetype_exe, +}; + +static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv) +{ + return efi_execute_image(file); +} + +static struct binfmt_hook binfmt_efi_hook = { + .type = filetype_exe, + .hook = efi_execute, +}; + +static int efi_register_image_handler(void) +{ + register_image_handler(&efi_handle_tr); + binfmt_register(&binfmt_efi_hook); + + return 0; +} +late_initcall(efi_register_image_handler); |