Pull request for efi-next-20230325

Documenation:
 
 * add man-page for efi command
 
 UEFI:
 
 * Let EFI app call ExitBootServices() before legacy booting kernel
 * Support zboot and bootm in the EFI app
 * Let efi command show configuration tables
 * Support booting a 64-bit kernel from 64-bit EFI app
 * Allocate device-tree copy from high memory
 * simplify efi_str_to_u16()
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAmQfHDAACgkQxIHbvCwF
 GsRCWg/8DOCb1igYd8D2nnCTfNEQRkkRvOyc8W3O687fX04e9N3eV8eEFvgBnecL
 zF2OT+VmQPq2eWIopOfqCWrIFDr1sbSUAdcPT8aM3s/2/ONFTnnUsvt8G3Qp8vyY
 nY+M466bl8Fh841aGtmqsuwBHTddjF8WFUcsj2FAG3laHbnSsVANHDPhSe7C6Fg+
 g3FtXZf51SEudTTK8RLa/+df4tji/UX0BLOIr6JZ+xqb+y/Tg/P2N5DAqIQCBTL1
 BZ7U/yVXs8M9MHU8T5TtshUL1WvFogbZYkx1kRAH3Rkg0ArD1rxV0Xd64Gmrdoyi
 71filEFNV860ytsxBjCbE+YaczqRR1oteyPlak0ApmGf+FRKIU047hpuS2RBsJqv
 g1xZg9EsoU4wbsOfVd7FHER63YGPfmH9pa5A5ULpq60tYuoTthToV1up2XVjxiZm
 hSxWGmz7dzMlqtuJiKm1R2Nug4N6a+SPSA+l8JDWSBxXZ5Ld5HZaZ99DR+phYcbE
 nzZfIePoPq8JCVb7vMpIi7m1MdUEjNUNAWEjHa1Gug71qbgULQ4mi+z192F+h51E
 HQ8qs+T6GFzFBrNPrem4wxfNa3UeBQzyTbYiaAcQgSuY942jn9ZrZ78epZbBbPCI
 r6LSgBlmtkQoyuPzgk6oX7NRU7Mqd9jOEQaWo7RF8LjdO5UgIrM=
 =a5J7
 -----END PGP SIGNATURE-----

Merge tag 'efi-next-20230325' of https://source.denx.de/u-boot/custodians/u-boot-efi into next

Pull request for efi-next-20230325

Documenation:

* add man-page for efi command

UEFI:

* Let EFI app call ExitBootServices() before legacy booting kernel
* Support zboot and bootm in the EFI app
* Let efi command show configuration tables
* Support booting a 64-bit kernel from 64-bit EFI app
* Allocate device-tree copy from high memory
* simplify efi_str_to_u16()
This commit is contained in:
Tom Rini 2023-03-25 17:34:34 -04:00
commit fde439219f
23 changed files with 539 additions and 143 deletions

View file

@ -32,8 +32,8 @@ config X86_RUN_32BIT
config X86_RUN_64BIT
bool "64-bit"
select X86_64
select SPL
select SPL_SEPARATE_BSS
select SPL if !EFI_APP
select SPL_SEPARATE_BSS if !EFI_APP
help
Build U-Boot as a 64-bit binary with a 32-bit SPL. This is
experimental and many features are missing. U-Boot SPL starts up,

View file

@ -14,14 +14,14 @@ void bootm_announce_and_cleanup(void);
* This boots a kernel image, either 32-bit or 64-bit. It will also work with
* a self-extracting kernel, if you set @image_64bit to false.
*
* @setup_base: Pointer to the setup.bin information for the kernel
* @load_address: Pointer to the start of the kernel image
* @image_64bit: true if the image is a raw 64-bit kernel, false if it
* is raw 32-bit or any type of self-extracting kernel
* such as a bzImage.
* @setup_base: Address of the setup.bin information for the kernel
* @entry: Address of the kernel entry point
* @image_64bit: true if the image is a raw 64-bit kernel, or a kernel
* which supports booting in 64-bit mode; false if it is raw 32-bit or any type
* of self-extracting kernel such as a bzImage.
* Return: -ve error code. This function does not return if the kernel was
* booted successfully.
*/
int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit);
int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit);
#endif

View file

@ -9,19 +9,54 @@
#include <asm/ist.h>
#include <asm/video/edid.h>
/* setup data types */
enum {
SETUP_NONE = 0,
SETUP_E820_EXT,
SETUP_DTB,
};
/* setup_data/setup_indirect types */
#define SETUP_NONE 0
#define SETUP_E820_EXT 1
#define SETUP_DTB 2
#define SETUP_PCI 3
#define SETUP_EFI 4
#define SETUP_APPLE_PROPERTIES 5
#define SETUP_JAILHOUSE 6
#define SETUP_CC_BLOB 7
#define SETUP_IMA 8
#define SETUP_RNG_SEED 9
#define SETUP_ENUM_MAX SETUP_RNG_SEED
#define SETUP_INDIRECT BIT(31)
#define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT)
/* ram_size flags */
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
/* loadflags */
#define LOADED_HIGH BIT(0)
#define KASLR_FLAG BIT(1)
#define QUIET_FLAG BIT(5)
#define KEEP_SEGMENTS BIT(6)
#define CAN_USE_HEAP BIT(7)
#define XLF_KERNEL_64 BIT(0)
#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1)
#define XLF_EFI_HANDOVER_32 BIT(2)
#define XLF_EFI_HANDOVER_64 BIT(3)
#define XLF_EFI_KEXEC BIT(4)
/* extensible setup data list node */
struct setup_data {
__u64 next;
__u32 type;
__u32 len;
__u8 data[0];
__u8 data[];
};
/* extensible setup indirect data node */
struct setup_indirect {
__u32 type;
__u32 reserved; /* Reserved, must be set to zero. */
__u64 len;
__u64 addr;
};
/**
@ -34,9 +69,6 @@ struct setup_header {
__u16 root_flags;
__u32 syssize;
__u16 ram_size;
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
__u16 vid_mode;
__u16 root_dev;
__u16 boot_flag;
@ -44,15 +76,10 @@ struct setup_header {
__u32 header;
__u16 version;
__u32 realmode_swtch;
__u16 start_sys;
__u16 start_sys_seg;
__u16 kernel_version;
__u8 type_of_loader;
__u8 loadflags;
#define LOADED_HIGH BIT(0)
#define KASLR_FLAG BIT(1)
#define QUIET_FLAG BIT(5)
#define KEEP_SEGMENTS BIT(6) /* Obsolete */
#define CAN_USE_HEAP BIT(7)
__u16 setup_move_size;
__u32 code32_start;
__u32 ramdisk_image;
@ -65,13 +92,8 @@ struct setup_header {
__u32 initrd_addr_max;
__u32 kernel_alignment;
__u8 relocatable_kernel;
u8 min_alignment;
#define XLF_KERNEL_64 BIT(0)
#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1)
#define XLF_EFI_HANDOVER_32 BIT(2)
#define XLF_EFI_HANDOVER_64 BIT(3)
#define XLF_EFI_KEXEC BIT(4)
u16 xloadflags;
__u8 min_alignment;
__u16 xloadflags;
__u32 cmdline_size;
__u32 hardware_subarch;
__u64 hardware_subarch_data;
@ -81,7 +103,7 @@ struct setup_header {
__u64 pref_address;
__u32 init_size;
__u32 handover_offset;
u32 kernel_info_offset;
__u32 kernel_info_offset;
} __attribute__((packed));
struct sys_desc_table {

View file

@ -262,6 +262,7 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table);
*
* @setup_base: Pointer to the setup.bin information for the kernel
* @target: Pointer to the start of the kernel image
* Return: -EFAULT if the kernel returned; otherwise does not return
*/
int cpu_jump_to_64bit(ulong setup_base, ulong target);

View file

@ -10,6 +10,7 @@
#include <common.h>
#include <bootstage.h>
#include <command.h>
#include <efi.h>
#include <hang.h>
#include <log.h>
#include <asm/global_data.h>
@ -149,26 +150,52 @@ error:
return 1;
}
int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
{
bootm_announce_and_cleanup();
#ifdef CONFIG_SYS_COREBOOT
timestamp_add_now(TS_U_BOOT_START_KERNEL);
#endif
/*
* Exit EFI boot services just before jumping, after all console
* output, since the console won't be available afterwards.
*/
if (IS_ENABLED(CONFIG_EFI_APP)) {
int ret;
ret = efi_store_memory_map(efi_get_priv());
if (ret)
return ret;
printf("Exiting EFI boot services\n");
ret = efi_call_exit_boot_services();
if (ret)
return ret;
}
if (image_64bit) {
if (!cpu_has_64bit()) {
puts("Cannot boot 64-bit kernel on 32-bit machine\n");
return -EFAULT;
}
/* At present 64-bit U-Boot does not support booting a
/*
* At present 64-bit U-Boot only supports booting a 64-bit
* kernel.
* TODO(sjg@chromium.org): Support booting both 32-bit and
* 64-bit kernels from 64-bit U-Boot.
*
* TODO(sjg@chromium.org): Support booting 32-bit kernels from
* 64-bit U-Boot
*/
#if !CONFIG_IS_ENABLED(X86_64)
return cpu_jump_to_64bit(setup_base, load_address);
#endif
if (CONFIG_IS_ENABLED(X86_64)) {
typedef void (*h_func)(ulong zero, ulong setup);
h_func func;
/* jump to Linux with rdi=0, rsi=setup_base */
func = (h_func)entry;
func(0, setup_base);
} else {
return cpu_jump_to_64bit(setup_base, entry);
}
} else {
/*
* Set %ebx, %ebp, and %edi to 0, %esi to point to the
@ -190,7 +217,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit)
"movl $0, %%ebp\n"
"cli\n"
"jmp *%[kernel_entry]\n"
:: [kernel_entry]"a"(load_address),
:: [kernel_entry]"a"(entry),
[boot_params] "S"(setup_base),
"b"(0), "D"(0)
);

View file

@ -504,13 +504,24 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct boot_params *params = state.base_ptr;
struct setup_header *hdr = &params->hdr;
bool image_64bit;
ulong entry;
int ret;
disable_interrupts();
entry = state.load_address;
image_64bit = false;
if (IS_ENABLED(CONFIG_X86_RUN_64BIT) &&
(hdr->xloadflags & XLF_KERNEL_64)) {
entry += 0x200;
image_64bit = true;
}
/* we assume that the kernel is in place */
ret = boot_linux_kernel((ulong)state.base_ptr, state.load_address,
false);
ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit);
printf("Kernel returned! (err=%d)\n", ret);
return CMD_RET_FAILURE;
@ -655,7 +666,7 @@ void zimage_dump(struct boot_params *base_ptr)
printf("%-20s %s\n", "", "Ancient kernel, using version 100");
print_num("Version", hdr->version);
print_num("Real mode switch", hdr->realmode_swtch);
print_num("Start sys", hdr->start_sys);
print_num("Start sys seg", hdr->start_sys_seg);
print_num("Kernel version", hdr->kernel_version);
version = get_kernel_version(base_ptr, (void *)state.bzimage_addr);
if (version)

View file

@ -62,8 +62,8 @@ obj-$(CONFIG_CMD_EXTENSION) += extension_board.o
obj-$(CONFIG_CMD_ECHO) += echo.o
obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
obj-$(CONFIG_CMD_EEPROM) += eeprom.o
obj-$(CONFIG_EFI) += efi.o
obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
obj-$(CONFIG_EFI) += efi.o efi_common.o
obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o efi_common.o
obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
ifdef CONFIG_CMD_EFICONFIG
ifdef CONFIG_EFI_MM_COMM_TEE

View file

@ -204,25 +204,12 @@ static efi_status_t copy_fdt(void **fdtp)
fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
fdt_size = fdt_pages << EFI_PAGE_SHIFT;
/*
* Safe fdt location is at 127 MiB.
* On the sandbox convert from the sandbox address space.
*/
new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 +
fdt_size, 0);
ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
&new_fdt_addr);
if (ret != EFI_SUCCESS) {
/* If we can't put it there, put it somewhere */
new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
&new_fdt_addr);
if (ret != EFI_SUCCESS) {
log_err("ERROR: Failed to reserve space for FDT\n");
goto done;
}
log_err("ERROR: Failed to reserve space for FDT\n");
goto done;
}
new_fdt = (void *)(uintptr_t)new_fdt_addr;
memcpy(new_fdt, fdt, fdt_totalsize(fdt));

View file

@ -7,10 +7,12 @@
#include <common.h>
#include <command.h>
#include <efi.h>
#include <efi_api.h>
#include <errno.h>
#include <log.h>
#include <malloc.h>
#include <sort.h>
#include <uuid.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
@ -273,8 +275,34 @@ done:
return ret ? CMD_RET_FAILURE : 0;
}
static int do_efi_tables(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct efi_system_table *systab;
if (IS_ENABLED(CONFIG_EFI_APP)) {
systab = efi_get_sys_table();
if (!systab) {
printf("Cannot read system table\n");
return CMD_RET_FAILURE;
}
} else {
int size;
int ret;
ret = efi_info_get(EFIET_SYS_TABLE, (void **)&systab, &size);
if (ret) /* this should not happen */
return CMD_RET_FAILURE;
}
efi_show_tables(systab);
return 0;
}
static struct cmd_tbl efi_commands[] = {
U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""),
U_BOOT_CMD_MKENT(tables, 1, 1, do_efi_tables, "", ""),
};
static int do_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
@ -298,5 +326,6 @@ static int do_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
U_BOOT_CMD(
efi, 3, 1, do_efi,
"EFI access",
"mem [all] Dump memory information [include boot services]"
"mem [all] Dump memory information [include boot services]\n"
"tables Dump tables"
);

26
cmd/efi_common.c Normal file
View file

@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Common code for EFI commands
*
* Copyright 2023 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <efi.h>
#include <efi_api.h>
#include <uuid.h>
void efi_show_tables(struct efi_system_table *systab)
{
int i;
for (i = 0; i < systab->nr_tables; i++) {
struct efi_configuration_table *tab = &systab->tables[i];
char guid_str[37];
uuid_bin_to_str(tab->guid.b, guid_str, 1);
printf("%p %pUl %s\n", tab->table, guid_str,
uuid_guid_get_str(tab->guid.b) ?: "(unknown)");
}
}

View file

@ -649,11 +649,7 @@ static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
{
efi_uintn_t i;
for (i = 0; i < systab.nr_tables; ++i)
printf("%pUl (%pUs)\n",
&systab.tables[i].guid, &systab.tables[i].guid);
efi_show_tables(&systab);
return CMD_RET_SUCCESS;
}

View file

@ -19,7 +19,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=532
# CONFIG_CMD_BOOTM is not set
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_PART=y
# CONFIG_CMD_NET is not set
CONFIG_CMD_TIME=y

View file

@ -4,6 +4,7 @@ CONFIG_ENV_SIZE=0x1000
CONFIG_DEFAULT_DEVICE_TREE="efi-x86_app"
CONFIG_DEBUG_UART_BASE=0
CONFIG_DEBUG_UART_CLOCK=0
CONFIG_X86_RUN_64BIT=y
CONFIG_VENDOR_EFI=y
CONFIG_TARGET_EFI_APP64=y
CONFIG_DEBUG_UART=y
@ -19,7 +20,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=532
# CONFIG_CMD_BOOTM is not set
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_PART=y
# CONFIG_CMD_NET is not set
CONFIG_CMD_CACHE=y

219
doc/usage/cmd/efi.rst Normal file
View file

@ -0,0 +1,219 @@
.. SPDX-License-Identifier: GPL-2.0+
.. Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
efi command
===========
Synopsis
--------
::
efi mem [all]
efi tables
Description
-----------
The *efi* command provides information about the EFI environment U-Boot is
running in, when it is started from EFI.
When running as an EFI app, this command queries EFI boot services for the
information. When running as an EFI payload, EFI boot services have been
stopped, so it uses the information collected by the boot stub before that
happened.
efi mem
~~~~~~~
This shows the EFI memory map, sorted in order of physical address.
This is normally a very large table. To help reduce the amount of detritus,
boot-time memory is normally merged with conventional memory. Use the 'all'
argument to show everything.
The fields are as follows:
#
Entry number (sequentially from 0)
Type
Memory type. EFI has a large number of memory types. The type is shown in
the format <n>:<name> where in is the format number in hex and <name> is the
name.
Physical
Physical address
Virtual
Virtual address
Size
Size of memory area in bytes
Attributes
Shows a code for memory attributes. The key for this is shown below the
table.
efi tables
~~~~~~~~~~
This shows a list of the EFI tables provided in the system table. These use
GUIDs so it is not possible in general to show the name of a table. But some
effort is made to provide a useful table, where the GUID is known by U-Boot.
Example
-------
::
=> efi mem
EFI table at 0, memory map 000000001ad38b60, size 1260, key a79, version 1, descr. size 0x30
# Type Physical Virtual Size Attributes
0 7:conv 0000000000 0000000000 00000a0000 f
<gap> 00000a0000 0000060000
1 7:conv 0000100000 0000000000 0000700000 f
2 a:acpi_nvs 0000800000 0000000000 0000008000 f
3 7:conv 0000808000 0000000000 0000008000 f
4 a:acpi_nvs 0000810000 0000000000 00000f0000 f
5 7:conv 0000900000 0000000000 001efef000 f
6 6:rt_data 001f8ef000 0000000000 0000100000 rf
7 5:rt_code 001f9ef000 0000000000 0000100000 rf
8 0:reserved 001faef000 0000000000 0000080000 f
9 9:acpi_reclaim 001fb6f000 0000000000 0000010000 f
10 a:acpi_nvs 001fb7f000 0000000000 0000080000 f
11 7:conv 001fbff000 0000000000 0000359000 f
12 6:rt_data 001ff58000 0000000000 0000020000 rf
13 a:acpi_nvs 001ff78000 0000000000 0000088000 f
<gap> 0020000000 0090000000
14 0:reserved 00b0000000 0000000000 0010000000 1
Attributes key:
f: uncached, write-coalescing, write-through, write-back
rf: uncached, write-coalescing, write-through, write-back, needs runtime mapping
1: uncached
*Some areas are merged (use 'all' to see)
=> efi mem all
EFI table at 0, memory map 000000001ad38bb0, size 1260, key a79, version 1, descr. size 0x30
# Type Physical Virtual Size Attributes
0 3:bs_code 0000000000 0000000000 0000001000 f
1 7:conv 0000001000 0000000000 000009f000 f
<gap> 00000a0000 0000060000
2 7:conv 0000100000 0000000000 0000700000 f
3 a:acpi_nvs 0000800000 0000000000 0000008000 f
4 7:conv 0000808000 0000000000 0000008000 f
5 a:acpi_nvs 0000810000 0000000000 00000f0000 f
6 4:bs_data 0000900000 0000000000 0000c00000 f
7 7:conv 0001500000 0000000000 000aa36000 f
8 2:loader_data 000bf36000 0000000000 0010000000 f
9 4:bs_data 001bf36000 0000000000 0000020000 f
10 7:conv 001bf56000 0000000000 00021e1000 f
11 1:loader_code 001e137000 0000000000 00000c4000 f
12 7:conv 001e1fb000 0000000000 000009b000 f
13 1:loader_code 001e296000 0000000000 00000e2000 f
14 7:conv 001e378000 0000000000 000005b000 f
15 4:bs_data 001e3d3000 0000000000 000001e000 f
16 7:conv 001e3f1000 0000000000 0000016000 f
17 4:bs_data 001e407000 0000000000 0000016000 f
18 2:loader_data 001e41d000 0000000000 0000002000 f
19 4:bs_data 001e41f000 0000000000 0000828000 f
20 3:bs_code 001ec47000 0000000000 0000045000 f
21 4:bs_data 001ec8c000 0000000000 0000001000 f
22 3:bs_code 001ec8d000 0000000000 000000e000 f
23 4:bs_data 001ec9b000 0000000000 0000001000 f
24 3:bs_code 001ec9c000 0000000000 000002c000 f
25 4:bs_data 001ecc8000 0000000000 0000001000 f
26 3:bs_code 001ecc9000 0000000000 000000c000 f
27 4:bs_data 001ecd5000 0000000000 0000006000 f
28 3:bs_code 001ecdb000 0000000000 0000014000 f
29 4:bs_data 001ecef000 0000000000 0000001000 f
30 3:bs_code 001ecf0000 0000000000 000005b000 f
31 4:bs_data 001ed4b000 0000000000 000000b000 f
32 3:bs_code 001ed56000 0000000000 0000024000 f
33 4:bs_data 001ed7a000 0000000000 0000006000 f
34 3:bs_code 001ed80000 0000000000 0000010000 f
35 4:bs_data 001ed90000 0000000000 0000002000 f
36 3:bs_code 001ed92000 0000000000 0000025000 f
37 4:bs_data 001edb7000 0000000000 0000003000 f
38 3:bs_code 001edba000 0000000000 0000011000 f
39 4:bs_data 001edcb000 0000000000 0000008000 f
40 3:bs_code 001edd3000 0000000000 000002d000 f
41 4:bs_data 001ee00000 0000000000 0000201000 f
42 3:bs_code 001f001000 0000000000 0000024000 f
43 4:bs_data 001f025000 0000000000 0000002000 f
44 3:bs_code 001f027000 0000000000 0000009000 f
45 4:bs_data 001f030000 0000000000 0000005000 f
46 3:bs_code 001f035000 0000000000 000002f000 f
47 4:bs_data 001f064000 0000000000 0000001000 f
48 3:bs_code 001f065000 0000000000 0000005000 f
49 4:bs_data 001f06a000 0000000000 0000005000 f
50 3:bs_code 001f06f000 0000000000 0000007000 f
51 4:bs_data 001f076000 0000000000 0000007000 f
52 3:bs_code 001f07d000 0000000000 000000d000 f
53 4:bs_data 001f08a000 0000000000 0000001000 f
54 3:bs_code 001f08b000 0000000000 0000006000 f
55 4:bs_data 001f091000 0000000000 0000004000 f
56 3:bs_code 001f095000 0000000000 000000d000 f
57 4:bs_data 001f0a2000 0000000000 0000003000 f
58 3:bs_code 001f0a5000 0000000000 0000026000 f
59 4:bs_data 001f0cb000 0000000000 0000005000 f
60 3:bs_code 001f0d0000 0000000000 0000019000 f
61 4:bs_data 001f0e9000 0000000000 0000004000 f
62 3:bs_code 001f0ed000 0000000000 0000024000 f
63 4:bs_data 001f111000 0000000000 0000008000 f
64 3:bs_code 001f119000 0000000000 000000b000 f
65 4:bs_data 001f124000 0000000000 0000001000 f
66 3:bs_code 001f125000 0000000000 0000002000 f
67 4:bs_data 001f127000 0000000000 0000002000 f
68 3:bs_code 001f129000 0000000000 0000009000 f
69 4:bs_data 001f132000 0000000000 0000003000 f
70 3:bs_code 001f135000 0000000000 0000005000 f
71 4:bs_data 001f13a000 0000000000 0000003000 f
72 3:bs_code 001f13d000 0000000000 0000005000 f
73 4:bs_data 001f142000 0000000000 0000003000 f
74 3:bs_code 001f145000 0000000000 0000011000 f
75 4:bs_data 001f156000 0000000000 000000b000 f
76 3:bs_code 001f161000 0000000000 0000009000 f
77 4:bs_data 001f16a000 0000000000 0000400000 f
78 3:bs_code 001f56a000 0000000000 0000006000 f
79 4:bs_data 001f570000 0000000000 0000001000 f
80 3:bs_code 001f571000 0000000000 0000001000 f
81 4:bs_data 001f572000 0000000000 0000002000 f
82 3:bs_code 001f574000 0000000000 0000017000 f
83 4:bs_data 001f58b000 0000000000 0000364000 f
84 6:rt_data 001f8ef000 0000000000 0000100000 rf
85 5:rt_code 001f9ef000 0000000000 0000100000 rf
86 0:reserved 001faef000 0000000000 0000080000 f
87 9:acpi_reclaim 001fb6f000 0000000000 0000010000 f
88 a:acpi_nvs 001fb7f000 0000000000 0000080000 f
89 4:bs_data 001fbff000 0000000000 0000201000 f
90 7:conv 001fe00000 0000000000 00000e8000 f
91 4:bs_data 001fee8000 0000000000 0000020000 f
92 3:bs_code 001ff08000 0000000000 0000026000 f
93 4:bs_data 001ff2e000 0000000000 0000009000 f
94 3:bs_code 001ff37000 0000000000 0000021000 f
95 6:rt_data 001ff58000 0000000000 0000020000 rf
96 a:acpi_nvs 001ff78000 0000000000 0000088000 f
<gap> 0020000000 0090000000
97 0:reserved 00b0000000 0000000000 0010000000 1
Attributes key:
f: uncached, write-coalescing, write-through, write-back
rf: uncached, write-coalescing, write-through, write-back, needs runtime mapping
1: uncached
=> efi tables
000000001f8edf98 ee4e5898-3914-4259-9d6e-dc7bd79403cf EFI_LZMA_COMPRESSED
000000001ff2ace0 05ad34ba-6f02-4214-952e-4da0398e2bb9 EFI_DXE_SERVICES
000000001f8ea018 7739f24c-93d7-11d4-9a3a-0090273fc14d EFI_HOB_LIST
000000001ff2bac0 4c19049f-4137-4dd3-9c10-8b97a83ffdfa EFI_MEMORY_TYPE
000000001ff2cb10 49152e77-1ada-4764-b7a2-7afefed95e8b (unknown)
000000001f9ac018 060cc026-4c0d-4dda-8f41-595fef00a502 EFI_MEM_STATUS_CODE_REC
000000001f9ab000 eb9d2d31-2d88-11d3-9a16-0090273fc14d SMBIOS table
000000001fb7e000 eb9d2d30-2d88-11d3-9a16-0090273fc14d EFI_GUID_EFI_ACPI1
000000001fb7e014 8868e871-e4f1-11d3-bc22-0080c73c8881 ACPI table
000000001e654018 dcfa911d-26eb-469f-a220-38b7dc461220 (unknown)

View file

@ -43,6 +43,7 @@ Shell commands
cmd/dm
cmd/ebtupdate
cmd/echo
cmd/efi
cmd/eficonfig
cmd/env
cmd/event

View file

@ -52,7 +52,18 @@
#define EFI32_LOADER_SIGNATURE "EL32"
#define EFI64_LOADER_SIGNATURE "EL64"
struct efi_device_path;
/**
* struct efi_device_path - device path protocol
*
* @type: device path type
* @sub_type: device path sub-type
* @length: length of the device path node including the header
*/
struct efi_device_path {
u8 type;
u8 sub_type;
u16 length;
} __packed;
/*
* The EFI spec defines the EFI_GUID as
@ -637,4 +648,13 @@ int efi_call_exit_boot_services(void);
int efi_get_mmap(struct efi_mem_desc **descp, int *sizep, uint *keyp,
int *desc_sizep, uint *versionp);
/**
* efi_show_tables() - Show a list of available tables
*
* Shows the address, GUID (and name where known) for each table
*
* @systab: System table containing the list of tables
*/
void efi_show_tables(struct efi_system_table *systab);
#endif /* _LINUX_EFI_H */

View file

@ -557,12 +557,6 @@ struct efi_loaded_image {
# define DEVICE_PATH_SUB_TYPE_INSTANCE_END 0x01
# define DEVICE_PATH_SUB_TYPE_END 0xff
struct efi_device_path {
u8 type;
u8 sub_type;
u16 length;
} __packed;
struct efi_mac_addr {
u8 addr[32];
} __packed;
@ -570,6 +564,7 @@ struct efi_mac_addr {
#define DEVICE_PATH_TYPE_HARDWARE_DEVICE 0x01
# define DEVICE_PATH_SUB_TYPE_MEMORY 0x03
# define DEVICE_PATH_SUB_TYPE_VENDOR 0x04
# define DEVICE_PATH_SUB_TYPE_CONTROLLER 0x05
struct efi_device_path_memory {
struct efi_device_path dp;
@ -584,6 +579,11 @@ struct efi_device_path_vendor {
u8 vendor_data[];
} __packed;
struct efi_device_path_controller {
struct efi_device_path dp;
u32 controller_number;
} __packed;
#define DEVICE_PATH_TYPE_ACPI_DEVICE 0x02
# define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE 0x01
@ -1909,6 +1909,25 @@ struct efi_system_resource_table {
EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \
0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
#define EFI_LZMA_COMPRESSED \
EFI_GUID(0xee4e5898, 0x3914, 0x4259, 0x9d, 0x6e, \
0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf)
#define EFI_DXE_SERVICES \
EFI_GUID(0x05ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, \
0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9)
#define EFI_HOB_LIST \
EFI_GUID(0x7739f24c, 0x93d7, 0x11d4, 0x9a, 0x3a, \
0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
#define EFI_MEMORY_TYPE \
EFI_GUID(0x4c19049f, 0x4137, 0x4dd3, 0x9c, 0x10, \
0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa)
#define EFI_MEM_STATUS_CODE_REC \
EFI_GUID(0x060cc026, 0x4c0d, 0x4dda, 0x8f, 0x41, \
0x59, 0x5f, 0xef, 0x00, 0xa5, 0x02)
#define EFI_GUID_EFI_ACPI1 \
EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, \
0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
/**
* struct win_certificate_uefi_guid - A certificate that encapsulates
* a GUID-specific signature

View file

@ -724,8 +724,8 @@ efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf,
* Return: size in pages
*/
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
/* Generic EFI memory allocator, call this to get memory */
void *efi_alloc(uint64_t len, int memory_type);
/* Allocate boot service data pool memory */
void *efi_alloc(size_t len);
/* Allocate pages on the specified alignment */
void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align);
/* More specific EFI memory allocator, called by EFI payloads */

View file

@ -63,20 +63,6 @@ static bool is_sd(struct blk_desc *desc)
}
#endif
static void *dp_alloc(size_t sz)
{
void *buf;
if (efi_allocate_pool(EFI_BOOT_SERVICES_DATA, sz, &buf) !=
EFI_SUCCESS) {
debug("EFI: ERROR: out of memory in %s\n", __func__);
return NULL;
}
memset(buf, 0, sz);
return buf;
}
/*
* Iterate to next block in device-path, terminating (returning NULL)
* at /End* node.
@ -147,7 +133,7 @@ struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp)
* in practice fallback.efi just uses MEDIA:HARD_DRIVE
* so not sure when we would see these other cases.
*/
if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB) ||
EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
return dp;
@ -302,7 +288,7 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
if (!dp)
return NULL;
ndp = dp_alloc(sz);
ndp = efi_alloc(sz);
if (!ndp)
return NULL;
memcpy(ndp, dp, sz);
@ -346,7 +332,7 @@ efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1,
/* both dp1 and dp2 are non-null */
unsigned sz1 = efi_dp_size(dp1);
unsigned sz2 = efi_dp_size(dp2);
void *p = dp_alloc(sz1 + sz2 + end_size);
void *p = efi_alloc(sz1 + sz2 + end_size);
if (!p)
return NULL;
ret = p;
@ -409,7 +395,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
ret = efi_dp_dup(dp);
} else if (!dp) {
size_t sz = node->length;
void *p = dp_alloc(sz + sizeof(END));
void *p = efi_alloc(sz + sizeof(END));
if (!p)
return NULL;
memcpy(p, node, sz);
@ -418,7 +404,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
} else {
/* both dp and node are non-null */
size_t sz = efi_dp_size(dp);
void *p = dp_alloc(sz + node->length + sizeof(END));
void *p = efi_alloc(sz + node->length + sizeof(END));
if (!p)
return NULL;
memcpy(p, dp, sz);
@ -439,7 +425,7 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type,
if (length < sizeof(struct efi_device_path))
return NULL;
ret = dp_alloc(length);
ret = efi_alloc(length);
if (!ret)
return ret;
ret->type = type;
@ -461,7 +447,7 @@ struct efi_device_path *efi_dp_append_instance(
return efi_dp_dup(dpi);
sz = efi_dp_size(dp);
szi = efi_dp_instance_size(dpi);
p = dp_alloc(sz + szi + 2 * sizeof(END));
p = efi_alloc(sz + szi + 2 * sizeof(END));
if (!p)
return NULL;
ret = p;
@ -486,7 +472,7 @@ struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp,
if (!dp || !*dp)
return NULL;
sz = efi_dp_instance_size(*dp);
p = dp_alloc(sz + sizeof(END));
p = efi_alloc(sz + sizeof(END));
if (!p)
return NULL;
memcpy(p, *dp, sz + sizeof(END));
@ -564,6 +550,11 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
return dp_size(dev->parent)
+ sizeof(struct efi_device_path_vendor) + 1;
#endif
#ifdef CONFIG_USB
case UCLASS_MASS_STORAGE:
return dp_size(dev->parent)
+ sizeof(struct efi_device_path_controller);
#endif
#ifdef CONFIG_VIRTIO_BLK
case UCLASS_VIRTIO:
/*
@ -585,7 +576,7 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
case UCLASS_MASS_STORAGE:
case UCLASS_USB_HUB:
return dp_size(dev->parent) +
sizeof(struct efi_device_path_usb_class);
sizeof(struct efi_device_path_usb);
default:
/* just skip over unknown classes: */
return dp_size(dev->parent);
@ -741,6 +732,19 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
memcpy(&dp->ns_id, &ns_id, sizeof(ns_id));
return &dp[1];
}
#endif
#if defined(CONFIG_USB)
case UCLASS_MASS_STORAGE: {
struct blk_desc *desc = desc = dev_get_uclass_plat(dev);
struct efi_device_path_controller *dp =
dp_fill(buf, dev->parent);
dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CONTROLLER;
dp->dp.length = sizeof(*dp);
dp->controller_number = desc->lun;
return &dp[1];
}
#endif
default:
debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
@ -767,19 +771,22 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
#endif
case UCLASS_MASS_STORAGE:
case UCLASS_USB_HUB: {
struct efi_device_path_usb_class *udp =
dp_fill(buf, dev->parent);
struct usb_device *udev = dev_get_parent_priv(dev);
struct usb_device_descriptor *desc = &udev->descriptor;
struct efi_device_path_usb *udp = dp_fill(buf, dev->parent);
switch (device_get_uclass_id(dev->parent)) {
case UCLASS_USB_HUB: {
struct usb_device *udev = dev_get_parent_priv(dev);
udp->parent_port_number = udev->portnr;
break;
}
default:
udp->parent_port_number = 0;
}
udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
udp->dp.length = sizeof(*udp);
udp->vendor_id = desc->idVendor;
udp->product_id = desc->idProduct;
udp->device_class = desc->bDeviceClass;
udp->device_subclass = desc->bDeviceSubClass;
udp->device_protocol = desc->bDeviceProtocol;
udp->usb_interface = 0;
return &udp[1];
}
@ -906,7 +913,7 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
{
void *buf, *start;
start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
start = buf = efi_alloc(dp_part_size(desc, part) + sizeof(END));
if (!buf)
return NULL;
@ -933,7 +940,7 @@ struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
dpsize = sizeof(struct efi_device_path_cdrom_path);
else
dpsize = sizeof(struct efi_device_path_hard_drive_path);
buf = dp_alloc(dpsize);
buf = efi_alloc(dpsize);
if (buf)
dp_part_node(buf, desc, part);
@ -1007,7 +1014,7 @@ struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
dpsize += fpsize;
start = buf = dp_alloc(dpsize + sizeof(END));
start = buf = efi_alloc(dpsize + sizeof(END));
if (!buf)
return NULL;
@ -1035,7 +1042,7 @@ struct efi_device_path *efi_dp_from_uart(void)
struct efi_device_path_uart *uart;
size_t dpsize = sizeof(ROOT) + sizeof(*uart) + sizeof(END);
buf = dp_alloc(dpsize);
buf = efi_alloc(dpsize);
if (!buf)
return NULL;
pos = buf;
@ -1061,7 +1068,7 @@ struct efi_device_path *efi_dp_from_eth(void)
dpsize += dp_size(eth_get_dev());
start = buf = dp_alloc(dpsize + sizeof(END));
start = buf = efi_alloc(dpsize + sizeof(END));
if (!buf)
return NULL;
@ -1081,7 +1088,7 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
struct efi_device_path_memory *mdp;
void *buf, *start;
start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
start = buf = efi_alloc(sizeof(*mdp) + sizeof(END));
if (!buf)
return NULL;

View file

@ -32,11 +32,10 @@ static u16 *efi_str_to_u16(char *str)
{
efi_uintn_t len;
u16 *out, *dst;
efi_status_t ret;
len = sizeof(u16) * (utf8_utf16_strlen(str) + 1);
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, len, (void **)&out);
if (ret != EFI_SUCCESS)
out = efi_alloc(len);
if (!out)
return NULL;
dst = out;
utf8_utf16_strcpy(&dst, str);
@ -77,6 +76,13 @@ static char *dp_hardware(char *s, struct efi_device_path *dp)
s += sprintf(s, ")");
break;
}
case DEVICE_PATH_SUB_TYPE_CONTROLLER: {
struct efi_device_path_controller *cdp =
(struct efi_device_path_controller *)dp;
s += sprintf(s, "Ctrl(0x%0x)", cdp->controller_number);
break;
}
default:
s = dp_unknown(s, dp);
break;

View file

@ -5,9 +5,12 @@
* Copyright (c) 2016 Alexander Graf
*/
#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <efi_loader.h>
#include <init.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#include <watchdog.h>
@ -533,27 +536,6 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
return EFI_SUCCESS;
}
/**
* efi_alloc() - allocate memory pages
*
* @len: size of the memory to be allocated
* @memory_type: usage type of the allocated memory
* Return: pointer to the allocated memory area or NULL
*/
void *efi_alloc(uint64_t len, int memory_type)
{
uint64_t ret = 0;
uint64_t pages = efi_size_in_pages(len);
efi_status_t r;
r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages,
&ret);
if (r == EFI_SUCCESS)
return (void*)(uintptr_t)ret;
return NULL;
}
/**
* efi_free_pages() - free memory pages
*
@ -672,6 +654,28 @@ efi_status_t efi_allocate_pool(enum efi_memory_type pool_type, efi_uintn_t size,
return r;
}
/**
* efi_alloc() - allocate boot services data pool memory
*
* Allocate memory from pool and zero it out.
*
* @size: number of bytes to allocate
* Return: pointer to allocated memory or NULL
*/
void *efi_alloc(size_t size)
{
void *buf;
if (efi_allocate_pool(EFI_BOOT_SERVICES_DATA, size, &buf) !=
EFI_SUCCESS) {
log_err("out of memory");
return NULL;
}
memset(buf, 0, size);
return buf;
}
/**
* efi_free_pool() - free memory from pool
*

View file

@ -102,7 +102,7 @@ static const struct {
{"lvm", PARTITION_LINUX_LVM_GUID},
{"u-boot-env", PARTITION_U_BOOT_ENVIRONMENT},
#endif
#ifdef CONFIG_CMD_EFIDEBUG
#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI)
{
"Device Path",
EFI_DEVICE_PATH_PROTOCOL_GUID,
@ -255,6 +255,14 @@ static const struct {
EFI_CERT_TYPE_PKCS7_GUID,
},
#endif
#ifdef CONFIG_EFI
{ "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED },
{ "EFI_DXE_SERVICES", EFI_DXE_SERVICES },
{ "EFI_HOB_LIST", EFI_HOB_LIST },
{ "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE },
{ "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC },
{ "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 },
#endif
};
/*

View file

@ -18,12 +18,15 @@
# OVMF-pure-efi.x64.fd at
# https://drive.google.com/file/d/1c39YI9QtpByGQ4V0UNNQtGqttEzS-eFV/view?usp=sharing
bzimage_fname=/tmp/kernel/arch/x86/boot/bzImage
set -e
usage() {
echo "Usage: $0 [-a | -p] [other opts]" 1>&2
echo 1>&2
echo " -a - Package up the app" 1>&2
echo " -k - Add a kernel" 1>&2
echo " -o - Use old EFI app build (before 32/64 split)" 1>&2
echo " -p - Package up the payload" 1>&2
echo " -P - Create a partition table" 1>&2
@ -52,11 +55,14 @@ serial=
# before the 32/64 split of the app
old=
# package up a kernel as well
kernel=
# Set ubdir to the build directory where you build U-Boot out-of-tree
# We avoid in-tree build because it gets confusing trying different builds
ubdir=/tmp/b/
while getopts "aopPrsw" opt; do
while getopts "akopPrsw" opt; do
case "${opt}" in
a)
type=app
@ -64,6 +70,9 @@ while getopts "aopPrsw" opt; do
p)
type=payload
;;
k)
kernel=1
;;
r)
run=1
;;
@ -124,6 +133,9 @@ EOF
# Copy files into the filesystem
copy_files() {
sudo cp $TMP/* $MNT
if [[ -n "${kernel}" ]]; then
sudo cp ${bzimage_fname} $MNT/vmlinuz
fi
}
# Create a filesystem on a raw device and copy in the files