提交 5dcf7cc5 编写于 作者: T Tom Rini

Merge tag 'efi-2021-01-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for efi-2021-01-rc1

The following bugs in the UEFI system are resolved:

* illegal free in EFI_LOAD_FILE2_PROTOCOL implementation
* incorrect documentation of EFI_LOAD_FILE2_PROTOCOL implementation
* output of CRC32 as decimal instead hexadecimal in unit test
* use EfiReservedMemoryType for no-map reserved memory
* avoid unnecessary resets in UEFI unit tests
* call EFI bootmgr even without having /EFI/boot
...@@ -135,12 +135,29 @@ done: ...@@ -135,12 +135,29 @@ done:
return ret; return ret;
} }
static void efi_reserve_memory(u64 addr, u64 size) /**
* efi_reserve_memory() - add reserved memory to memory map
*
* @addr: start address of the reserved memory range
* @size: size of the reserved memory range
* @nomap: indicates that the memory range shall not be accessed by the
* UEFI payload
*/
static void efi_reserve_memory(u64 addr, u64 size, bool nomap)
{ {
int type;
efi_uintn_t ret;
/* Convert from sandbox address space. */ /* Convert from sandbox address space. */
addr = (uintptr_t)map_sysmem(addr, 0); addr = (uintptr_t)map_sysmem(addr, 0);
if (efi_add_memory_map(addr, size,
EFI_RESERVED_MEMORY_TYPE) != EFI_SUCCESS) if (nomap)
type = EFI_RESERVED_MEMORY_TYPE;
else
type = EFI_BOOT_SERVICES_DATA;
ret = efi_add_memory_map(addr, size, type);
if (ret != EFI_SUCCESS)
log_err("Reserved memory mapping failed addr %llx size %llx\n", log_err("Reserved memory mapping failed addr %llx size %llx\n",
addr, size); addr, size);
} }
...@@ -166,7 +183,7 @@ static void efi_carve_out_dt_rsv(void *fdt) ...@@ -166,7 +183,7 @@ static void efi_carve_out_dt_rsv(void *fdt)
for (i = 0; i < nr_rsv; i++) { for (i = 0; i < nr_rsv; i++) {
if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
continue; continue;
efi_reserve_memory(addr, size); efi_reserve_memory(addr, size, false);
} }
/* process reserved-memory */ /* process reserved-memory */
...@@ -186,8 +203,13 @@ static void efi_carve_out_dt_rsv(void *fdt) ...@@ -186,8 +203,13 @@ static void efi_carve_out_dt_rsv(void *fdt)
* a size instead of a reg property. * a size instead of a reg property.
*/ */
if (fdt_addr != FDT_ADDR_T_NONE && if (fdt_addr != FDT_ADDR_T_NONE &&
fdtdec_get_is_enabled(fdt, subnode)) fdtdec_get_is_enabled(fdt, subnode)) {
efi_reserve_memory(fdt_addr, fdt_size); bool nomap;
nomap = !!fdt_getprop(fdt, subnode, "no-map",
NULL);
efi_reserve_memory(fdt_addr, fdt_size, nomap);
}
subnode = fdt_next_subnode(fdt, subnode); subnode = fdt_next_subnode(fdt, subnode);
} }
} }
......
...@@ -56,4 +56,3 @@ CONFIG_USB=y ...@@ -56,4 +56,3 @@ CONFIG_USB=y
CONFIG_DM_USB=y CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_PCI=y CONFIG_USB_EHCI_PCI=y
# CONFIG_EFI_GRUB_ARM32_WORKAROUND is not set
...@@ -123,12 +123,14 @@ ...@@ -123,12 +123,14 @@
#define BOOTENV_SHARED_EFI \ #define BOOTENV_SHARED_EFI \
"boot_efi_binary=" \ "boot_efi_bootmgr=" \
"if fdt addr ${fdt_addr_r}; then " \ "if fdt addr ${fdt_addr_r}; then " \
"bootefi bootmgr ${fdt_addr_r};" \ "bootefi bootmgr ${fdt_addr_r};" \
"else " \ "else " \
"bootefi bootmgr ${fdtcontroladdr};" \ "bootefi bootmgr;" \
"fi;" \ "fi\0" \
\
"boot_efi_binary=" \
"load ${devtype} ${devnum}:${distro_bootpart} " \ "load ${devtype} ${devnum}:${distro_bootpart} " \
"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; " \ "${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; " \
"if fdt addr ${fdt_addr_r}; then " \ "if fdt addr ${fdt_addr_r}; then " \
...@@ -152,6 +154,7 @@ ...@@ -152,6 +154,7 @@
"run load_efi_dtb; " \ "run load_efi_dtb; " \
"fi;" \ "fi;" \
"done;" \ "done;" \
"run boot_efi_bootmgr;" \
"if test -e ${devtype} ${devnum}:${distro_bootpart} " \ "if test -e ${devtype} ${devnum}:${distro_bootpart} " \
"efi/boot/"BOOTEFI_NAME"; then " \ "efi/boot/"BOOTEFI_NAME"; then " \
"echo Found EFI removable media binary " \ "echo Found EFI removable media binary " \
......
...@@ -164,6 +164,7 @@ config EFI_HAVE_RUNTIME_RESET ...@@ -164,6 +164,7 @@ config EFI_HAVE_RUNTIME_RESET
config EFI_GRUB_ARM32_WORKAROUND config EFI_GRUB_ARM32_WORKAROUND
bool "Workaround for GRUB on 32bit ARM" bool "Workaround for GRUB on 32bit ARM"
default n if ARCH_QEMU
default y default y
depends on ARM && !ARM64 depends on ARM && !ARM64
help help
......
...@@ -47,9 +47,9 @@ static const struct efi_initrd_dp dp = { ...@@ -47,9 +47,9 @@ static const struct efi_initrd_dp dp = {
/** /**
* get_file_size() - retrieve the size of initramfs, set efi status on error * get_file_size() - retrieve the size of initramfs, set efi status on error
* *
* @dev: device to read from. i.e "mmc" * @dev: device to read from, e.g. "mmc"
* @part: device partition. i.e "0:1" * @part: device partition, e.g. "0:1"
* @file: name fo file * @file: name of file
* @status: EFI exit code in case of failure * @status: EFI exit code in case of failure
* *
* Return: size of file * Return: size of file
...@@ -78,15 +78,16 @@ out: ...@@ -78,15 +78,16 @@ out:
} }
/** /**
* load_file2() - get information about random number generation * efi_load_file2initrd() - load initial RAM disk
*
* This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
* in order to load an initial RAM disk requested by the Linux kernel stub.
* *
* This function implement the LoadFile2() service in order to load an initram
* disk requested by the Linux kernel stub.
* See the UEFI spec for details. * See the UEFI spec for details.
* *
* @this: loadfile2 protocol instance * @this: EFI_LOAD_FILE2_PROTOCOL instance
* @file_path: relative path of the file. "" in this case * @file_path: media device path of the file, "" in this case
* @boot_policy: must be false for Loadfile2 * @boot_policy: must be false
* @buffer_size: size of allocated buffer * @buffer_size: size of allocated buffer
* @buffer: buffer to load the file * @buffer: buffer to load the file
* *
...@@ -97,19 +98,20 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, ...@@ -97,19 +98,20 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
struct efi_device_path *file_path, bool boot_policy, struct efi_device_path *file_path, bool boot_policy,
efi_uintn_t *buffer_size, void *buffer) efi_uintn_t *buffer_size, void *buffer)
{ {
const char *filespec = CONFIG_EFI_INITRD_FILESPEC; char *filespec;
efi_status_t status = EFI_NOT_FOUND; efi_status_t status = EFI_NOT_FOUND;
loff_t file_sz = 0, read_sz = 0; loff_t file_sz = 0, read_sz = 0;
char *dev, *part, *file; char *dev, *part, *file;
char *s; char *pos;
int ret; int ret;
EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy, EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy,
buffer_size, buffer); buffer_size, buffer);
s = strdup(filespec); filespec = strdup(CONFIG_EFI_INITRD_FILESPEC);
if (!s) if (!filespec)
goto out; goto out;
pos = filespec;
if (!this || this != &efi_lf2_protocol || if (!this || this != &efi_lf2_protocol ||
!buffer_size) { !buffer_size) {
...@@ -128,14 +130,20 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, ...@@ -128,14 +130,20 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
goto out; goto out;
} }
/* expect something like 'mmc 0:1 initrd.cpio.gz' */ /*
dev = strsep(&s, " "); * expect a string with three space separated parts:
*
* * a block device type, e.g. "mmc"
* * a device and partition identifier, e.g. "0:1"
* * a file path on the block device, e.g. "/boot/initrd.cpio.gz"
*/
dev = strsep(&pos, " ");
if (!dev) if (!dev)
goto out; goto out;
part = strsep(&s, " "); part = strsep(&pos, " ");
if (!part) if (!part)
goto out; goto out;
file = strsep(&s, " "); file = strsep(&pos, " ");
if (!file) if (!file)
goto out; goto out;
...@@ -163,28 +171,25 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, ...@@ -163,28 +171,25 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
} }
out: out:
free(s); free(filespec);
return EFI_EXIT(status); return EFI_EXIT(status);
} }
/** /**
* efi_initrd_register() - Register a handle and loadfile2 protocol * efi_initrd_register() - create handle for loading initial RAM disk
* *
* This function creates a new handle and installs a linux specific GUID * This function creates a new handle and installs a Linux specific vendor
* to handle initram disk loading during boot. * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path
* See the UEFI spec for details. * to identify the handle and then calls the LoadFile service of the
* EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk.
* *
* Return: status code * Return: status code
*/ */
efi_status_t efi_initrd_register(void) efi_status_t efi_initrd_register(void)
{ {
efi_handle_t efi_initrd_handle = NULL; efi_handle_t efi_initrd_handle = NULL;
efi_status_t ret; efi_status_t ret;
/*
* Set up the handle with the EFI_LOAD_FILE2_PROTOCOL which Linux may
* use to load the initial ramdisk.
*/
ret = EFI_CALL(efi_install_multiple_protocol_interfaces ret = EFI_CALL(efi_install_multiple_protocol_interfaces
(&efi_initrd_handle, (&efi_initrd_handle,
/* initramfs */ /* initramfs */
......
...@@ -142,6 +142,27 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures) ...@@ -142,6 +142,27 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures)
return ret; return ret;
} }
/*
* Check that a test requiring reset exists.
*
* @testname: name of the test
* @return: test, or NULL if not found
*/
static bool need_reset(const u16 *testname)
{
struct efi_unit_test *test;
for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
if (testname && efi_st_strcmp_16_8(testname, test->name))
continue;
if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT ||
test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT)
return true;
}
return false;
}
/* /*
* Check that a test exists. * Check that a test exists.
* *
...@@ -290,6 +311,16 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle, ...@@ -290,6 +311,16 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
&failures); &failures);
if (!need_reset(testname)) {
if (failures)
ret = EFI_PROTOCOL_ERROR;
/* Give feedback */
efi_st_printc(EFI_WHITE, "\nSummary: %u failures\n\n",
failures);
return ret;
}
/* Execute mixed tests */ /* Execute mixed tests */
efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT, efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT,
EFI_ST_SETUP, &failures); EFI_ST_SETUP, &failures);
......
...@@ -44,25 +44,28 @@ static void mac(void *pointer, u16 **buf) ...@@ -44,25 +44,28 @@ static void mac(void *pointer, u16 **buf)
} }
/* /*
* Print a pointer to an u16 string * printx() - print hexadecimal number to an u16 string
* *
* @pointer: pointer * @pointer: pointer
* @buf: pointer to buffer address * @prec: minimum number of digits to print
* on return position of terminating zero word * @buf: pointer to buffer address,
* on return position of terminating zero word
* @size: size of value to be printed in bytes
*/ */
static void pointer(void *pointer, u16 **buf) static void printx(u64 p, int prec, u16 **buf)
{ {
int i; int i;
u16 c; u16 c;
uintptr_t p = (uintptr_t)pointer;
u16 *pos = *buf; u16 *pos = *buf;
for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) { for (i = 2 * sizeof(p) - 1; i >= 0; --i) {
c = (p >> i) & 0x0f; c = (p >> (4 * i)) & 0x0f;
c += '0'; if (c || pos != *buf || !i || i < prec) {
if (c > '9') c += '0';
c += 'a' - '9' - 1; if (c > '9')
*pos++ = c; c += 'a' - '9' - 1;
*pos++ = c;
}
} }
*pos = 0; *pos = 0;
*buf = pos; *buf = pos;
...@@ -212,7 +215,9 @@ void efi_st_printc(int color, const char *fmt, ...) ...@@ -212,7 +215,9 @@ void efi_st_printc(int color, const char *fmt, ...)
break; break;
default: default:
--c; --c;
pointer(va_arg(args, void*), &pos); printx((uintptr_t)va_arg(args, void *),
2 * sizeof(void *), &pos);
break;
} }
break; break;
case 's': case 's':
...@@ -223,6 +228,10 @@ void efi_st_printc(int color, const char *fmt, ...) ...@@ -223,6 +228,10 @@ void efi_st_printc(int color, const char *fmt, ...)
case 'u': case 'u':
uint2dec(va_arg(args, u32), prec, &pos); uint2dec(va_arg(args, u32), prec, &pos);
break; break;
case 'x':
printx((u64)va_arg(args, unsigned int),
prec, &pos);
break;
default: default:
break; break;
} }
......
...@@ -200,7 +200,7 @@ static int execute(void) ...@@ -200,7 +200,7 @@ static int execute(void)
efi_st_error("Could not determine CRC32\n"); efi_st_error("Could not determine CRC32\n");
return EFI_ST_FAILURE; return EFI_ST_FAILURE;
} }
efi_st_printf("CRC32 %u\n", (unsigned int)crc32); efi_st_printf("CRC32 %.8x\n", (unsigned int)crc32);
status = boottime->free_pool(buf); status = boottime->free_pool(buf);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
......
...@@ -23,7 +23,7 @@ static u32 notify_call_count; ...@@ -23,7 +23,7 @@ static u32 notify_call_count;
static bool convert_pointer_failed; static bool convert_pointer_failed;
/** /**
* notify () - notification function * notify() - notification function
* *
* This function is called when the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event * This function is called when the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event
* occurs. The correct output of ConvertPointer() is checked. * occurs. The correct output of ConvertPointer() is checked.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册