#include <common.h>
#include <command.h>
+#include <dm/device.h>
#include <efi_loader.h>
#include <errno.h>
#include <libfdt.h>
#include <libfdt_env.h>
#include <memalign.h>
#include <asm/global_data.h>
+#include <asm-generic/sections.h>
+#include <linux/linkage.h>
DECLARE_GLOBAL_DATA_PTR;
}
};
-static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
+static efi_status_t EFIAPI bootefi_open_dp(void *handle, efi_guid_t *protocol,
void **protocol_interface, void *agent_handle,
void *controller_handle, uint32_t attributes)
{
* Load an EFI payload into a newly allocated piece of memory, register all
* EFI objects it would want to access and jump to it.
*/
-static unsigned long do_bootefi_exec(void *efi)
+static unsigned long do_bootefi_exec(void *efi, void *fdt)
{
- ulong (*entry)(void *image_handle, struct efi_system_table *st);
+ ulong (*entry)(void *image_handle, struct efi_system_table *st)
+ asmlinkage;
ulong fdt_pages, fdt_size, fdt_start, fdt_end;
bootm_headers_t img = { 0 };
- void *fdt = working_fdt;
/*
* gd lives in a fixed register which may get clobbered while we execute
*/
efi_save_gd();
- /* Update system table to point to our currently loaded FDT */
-
- /* Fall back to included fdt if none was manually loaded */
- if (!fdt && gd->fdt_blob)
- fdt = (void *)gd->fdt_blob;
-
- if (fdt) {
+ if (fdt && !fdt_check_header(fdt)) {
/* Prepare fdt for payload */
fdt = copy_fdt(fdt);
efi_add_memory_map(fdt_start, fdt_pages,
EFI_BOOT_SERVICES_DATA, true);
} else {
- printf("WARNING: No device tree loaded, expect boot to fail\n");
+ printf("WARNING: Invalid device tree, expect boot to fail\n");
systab.nr_tables = 0;
}
#ifdef CONFIG_LCD
efi_gop_register();
#endif
+#ifdef CONFIG_NET
+ void *nethandle = loaded_image_info.device_handle;
+ efi_net_register(&nethandle);
+
+ if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
+ loaded_image_info.device_handle = nethandle;
+ else
+ loaded_image_info.device_handle = bootefi_device_path;
+#endif
+#ifdef CONFIG_GENERATE_SMBIOS_TABLE
+ efi_smbios_register();
+#endif
+
+ /* Initialize EFI runtime services */
+ efi_reset_system_init();
+ efi_get_time_init();
/* Call our payload! */
-#ifdef DEBUG_EFI
- printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
-#endif
+ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
+
+ if (setjmp(&loaded_image_info.exit_jmp)) {
+ efi_status_t status = loaded_image_info.exit_status;
+ return status == EFI_SUCCESS ? 0 : -EINVAL;
+ }
+
return entry(&loaded_image_info, &systab);
}
/* Interpreter command to boot an arbitrary EFI image from memory */
static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- char *saddr;
- unsigned long addr;
+ char *saddr, *sfdt;
+ unsigned long addr, fdt_addr = 0;
int r = 0;
if (argc < 2)
- return 1;
- saddr = argv[1];
+ return CMD_RET_USAGE;
+#ifdef CONFIG_CMD_BOOTEFI_HELLO
+ if (!strcmp(argv[1], "hello")) {
+ ulong size = __efi_hello_world_end - __efi_hello_world_begin;
+
+ addr = CONFIG_SYS_LOAD_ADDR;
+ memcpy((char *)addr, __efi_hello_world_begin, size);
+ } else
+#endif
+ {
+ saddr = argv[1];
- addr = simple_strtoul(saddr, NULL, 16);
+ addr = simple_strtoul(saddr, NULL, 16);
+
+ if (argc > 2) {
+ sfdt = argv[2];
+ fdt_addr = simple_strtoul(sfdt, NULL, 16);
+ }
+ }
- printf("## Starting EFI application at 0x%08lx ...\n", addr);
- r = do_bootefi_exec((void *)addr);
+ printf("## Starting EFI application at %08lx ...\n", addr);
+ r = do_bootefi_exec((void *)addr, (void*)fdt_addr);
printf("## Application terminated, r = %d\n", r);
if (r != 0)
#ifdef CONFIG_SYS_LONGHELP
static char bootefi_help_text[] =
- "<image address>\n"
- " - boot EFI payload stored at address <image address>\n"
- "\n"
- "Since most EFI payloads want to have a device tree provided, please\n"
- "make sure you load a device tree using the fdt addr command before\n"
- "executing bootefi.\n";
+ "<image address> [fdt address]\n"
+ " - boot EFI payload stored at address <image address>.\n"
+ " If specified, the device tree located at <fdt address> gets\n"
+ " exposed as EFI configuration table.\n"
+#ifdef CONFIG_CMD_BOOTEFI_HELLO
+ "hello\n"
+ " - boot a sample Hello World application stored within U-Boot"
+#endif
+ ;
#endif
U_BOOT_CMD(
- bootefi, 2, 0, do_bootefi,
- "Boots an EFI payload from memory\n",
+ bootefi, 3, 0, do_bootefi,
+ "Boots an EFI payload from memory",
bootefi_help_text
);
char devname[32] = { 0 }; /* dp->str is u16[32] long */
char *colon;
- /* Assemble the condensed device name we use in efi_disk.c */
- snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+#if defined(CONFIG_BLK) || defined(CONFIG_ISO_PARTITION)
+ desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
+#endif
+
+#ifdef CONFIG_BLK
+ if (desc) {
+ snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
+ } else
+#endif
+
+ {
+ /* Assemble the condensed device name we use in efi_disk.c */
+ snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
+ }
+
colon = strchr(devname, ':');
#ifdef CONFIG_ISO_PARTITION
/* For ISOs we create partition block devices */
- desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
(desc->part_type == PART_TYPE_ISO)) {
if (!colon)
- snprintf(devname, sizeof(devname), "%s%s:1", dev,
- devnr);
+ snprintf(devname, sizeof(devname), "%s:1", devname);
+
colon = NULL;
}
#endif
/* Patch bootefi_image_path to the target file path */
memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
- snprintf(devname, sizeof(devname), "%s", path);
+ if (strcmp(dev, "Net")) {
+ /* Add leading / to fs paths, because they're absolute */
+ snprintf(devname, sizeof(devname), "/%s", path);
+ } else {
+ snprintf(devname, sizeof(devname), "%s", path);
+ }
ascii2unicode(bootefi_image_path[0].str, devname);
}