summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/Kconfig8
-rw-r--r--lib/efi_loader/Makefile7
-rw-r--r--lib/efi_loader/efi_bootbin.c7
-rw-r--r--lib/efi_loader/efi_bootmgr.c7
-rw-r--r--lib/efi_loader/efi_boottime.c2
-rw-r--r--lib/efi_loader/efi_console.c7
-rw-r--r--lib/efi_loader/efi_device_path.c4
-rw-r--r--lib/efi_loader/efi_disk.c1
-rw-r--r--lib/efi_loader/efi_dt_fixup.c3
-rw-r--r--lib/efi_loader/efi_hii.c3
-rw-r--r--lib/efi_loader/efi_image_loader.c86
-rw-r--r--lib/efi_loader/efi_memory.c53
-rw-r--r--lib/efi_loader/efi_setup.c2
-rw-r--r--lib/efi_loader/efi_signature.c3
-rw-r--r--lib/efi_loader/efi_tcg2.c12
-rw-r--r--lib/efi_loader/efi_var_common.c4
-rw-r--r--lib/efi_loader/efi_var_seed.S4
17 files changed, 131 insertions, 82 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index bae98e07d23..4cb13ae7c8a 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -102,8 +102,7 @@ config EFI_SET_TIME
can be used by an EFI application to adjust the real time clock.
config EFI_HAVE_RUNTIME_RESET
- # bool "Reset runtime service is available"
- bool
+ bool "Reset runtime service"
default y
depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || \
SANDBOX || SYSRESET_SBI || SYSRESET_X86
@@ -517,7 +516,7 @@ config EFI_RISCV_BOOT_PROTOCOL
config EFI_IP4_CONFIG2_PROTOCOL
bool "EFI_IP4_CONFIG2_PROTOCOL support"
default y if ARCH_QEMU || SANDBOX
- depends on NET || NET_LWIP
+ depends on NET
help
Provides an implementation of the EFI_IP4_CONFIG2_PROTOCOL, this
protocol can be used to set and get the current ip address and
@@ -610,7 +609,8 @@ config EFI_BOOTMGR
config EFI_HTTP_BOOT
bool "EFI HTTP Boot support"
- depends on NET || NET_LWIP
+ depends on NET
+ depends on CMDLINE
select CMD_NET
select CMD_DHCP
select CMD_DNS
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index d73ad43951b..567db518a8f 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -74,8 +74,11 @@ obj-$(CONFIG_EFI_SIGNATURE_SUPPORT) += efi_signature.o
obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
obj-$(CONFIG_EFI_DEBUG_SUPPORT) += efi_debug_support.o
-EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
-$(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
+TMP_VAR_SEED := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
+EFI_VAR_SEED_FILE := $(if $(filter /% ,$(TMP_VAR_SEED)) \
+ ,$(TMP_VAR_SEED),$(srctree)/$(TMP_VAR_SEED))
+AFLAGS_efi_var_seed.o := -DEFI_VAR_SEED_FILE=\"$(EFI_VAR_SEED_FILE)\"
+$(obj)/efi_var_seed.o: $(EFI_VAR_SEED_FILE)
ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y)
capsule_crt_path=($(subst $(quote),,$(CONFIG_EFI_CAPSULE_CRT_FILE)))
diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c
index b394f0d60ce..12db8f517c7 100644
--- a/lib/efi_loader/efi_bootbin.c
+++ b/lib/efi_loader/efi_bootbin.c
@@ -224,11 +224,8 @@ static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
/* Initialize EFI drivers */
ret = efi_init_obj_list();
- if (ret != EFI_SUCCESS) {
- log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
- ret & ~EFI_ERROR_MASK);
- return -1;
- }
+ if (ret != EFI_SUCCESS)
+ return ret;
ret = efi_install_fdt(fdt);
if (ret != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index a687f4d8e85..8c9a9b5eb56 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -1310,11 +1310,8 @@ efi_status_t efi_bootmgr_run(void *fdt)
/* Initialize EFI drivers */
ret = efi_init_obj_list();
- if (ret != EFI_SUCCESS) {
- log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
- ret & ~EFI_ERROR_MASK);
- return CMD_RET_FAILURE;
- }
+ if (ret != EFI_SUCCESS)
+ return ret;
ret = efi_bootmgr_load(&handle, &load_options);
if (ret != EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index de57823bd44..bcb01c92cf4 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3895,7 +3895,7 @@ efi_status_t EFIAPI efi_disconnect_controller(
&number_of_children,
&child_handle_buffer);
if (r != EFI_SUCCESS)
- return r;
+ goto out;
sole_child = (number_of_children == 1);
if (child_handle) {
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index a798d5604a3..8d076058280 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -9,6 +9,7 @@
#include <ansi.h>
#include <charset.h>
+#include <console.h>
#include <efi_device_path.h>
#include <malloc.h>
#include <time.h>
@@ -299,8 +300,7 @@ static int query_console_serial(int *rows, int *cols)
int n[2];
/* Empty input buffer */
- while (tstc())
- getchar();
+ console_flush_stdin();
/*
* Not all terminals understand CSI [18t for querying the console size.
@@ -960,8 +960,7 @@ static void efi_cin_check(void)
*/
static void efi_cin_empty_buffer(void)
{
- while (tstc())
- getchar();
+ console_flush_stdin();
key_available = false;
}
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index b3fb20b2501..9efb158f5dd 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -955,8 +955,8 @@ struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev
efi_uintn_t uridp_len;
char *pos;
char tmp[128];
- struct efi_ipv4_address ip;
- struct efi_ipv4_address mask;
+ struct efi_ipv4_address ip = { .ip_addr = { 0, 0, 0, 0 } };
+ struct efi_ipv4_address mask = { .ip_addr = { 0, 0, 0, 0 } };
if ((server && strlen("http://") + strlen(server) + 1 > sizeof(tmp)) ||
(!server && IS_ENABLED(CONFIG_NET_LWIP)))
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index f8a57539ec6..4a3ace3a304 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -305,6 +305,7 @@ static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
}
static const struct efi_block_io block_io_disk_template = {
+ .revision = EFI_BLOCK_IO_PROTOCOL_REVISION3,
.reset = &efi_disk_reset,
.read_blocks = &efi_disk_read_blocks,
.write_blocks = &efi_disk_write_blocks,
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index 544e1aa9808..333711b9957 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -123,8 +123,7 @@ void efi_carve_out_dt_rsv(void *fdt)
fdtdec_get_is_enabled(fdt, subnode)) {
bool nomap;
- nomap = !!fdt_getprop(fdt, subnode, "no-map",
- NULL);
+ nomap = fdtdec_get_bool(fdt, subnode, "no-map");
efi_reserve_memory(fdt_addr, fdt_size, nomap);
}
subnode = fdt_next_subnode(fdt, subnode);
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 330d7c5830b..7bf51ad43d1 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -324,7 +324,8 @@ add_keyboard_package(struct efi_hii_packagelist *hii,
list_add_tail(&layout_data->link_sys,
&efi_keyboard_layout_list);
- layout += layout_length;
+ layout = (struct efi_hii_keyboard_layout *)
+ ((uintptr_t)layout + layout_length);
}
list_add_tail(&package_data->link, &hii->keyboard_packages);
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index d002eb0c744..f9a2d2df405 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -108,11 +108,13 @@ void efi_print_image_infos(void *pc)
* @rel_size: size of the relocation table in bytes
* @efi_reloc: actual load address of the image
* @pref_address: preferred load address of the image
+ * @virt_size: virtual image size as provided in the PE-COFF header
* Return: status code
*/
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
- unsigned long rel_size, void *efi_reloc,
- unsigned long pref_address)
+ unsigned long rel_size, void *efi_reloc,
+ unsigned long pref_address,
+ unsigned long virt_size)
{
unsigned long delta = (unsigned long)efi_reloc - pref_address;
const IMAGE_BASE_RELOCATION *end;
@@ -122,34 +124,95 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
return EFI_SUCCESS;
end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
- while (rel + 1 < end && rel->SizeOfBlock) {
+ while (rel + 1 < end) {
const uint16_t *relocs = (const uint16_t *)(rel + 1);
+
+ /* Each block must start on a 32-bit boundary */
+ if (!IS_ALIGNED((uintptr_t)rel, sizeof(uint32_t))) {
+ log_debug("Relocation block not 32-bit aligned\n");
+ return EFI_LOAD_ERROR;
+ }
+ /* Relocation block cannot be shorter than its header */
+ if (rel->SizeOfBlock < sizeof(*rel)) {
+ log_debug("Relocation block too small: %u\n",
+ rel->SizeOfBlock);
+ return EFI_LOAD_ERROR;
+ }
+ /* All relocation entries must be inside the .reloc section */
+ if ((const char *)rel + rel->SizeOfBlock > (const char *)end) {
+ log_debug("Relocation block exceeds relocation data\n");
+ return EFI_LOAD_ERROR;
+ }
+ /*
+ * Relocations must be within the virtual address range.
+ * This also ensures that there is no overflow in the
+ * entry_offset check below.
+ */
+ if (rel->VirtualAddress > virt_size) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
+
i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t);
while (i--) {
- uint32_t offset = (uint32_t)(*relocs & 0xfff) +
- rel->VirtualAddress;
+ uint32_t entry_offset = *relocs & 0xfff;
+ unsigned long offset;
int type = *relocs >> EFI_PAGE_SHIFT;
- uint64_t *x64 = efi_reloc + offset;
- uint32_t *x32 = efi_reloc + offset;
- uint16_t *x16 = efi_reloc + offset;
+ uint64_t *x64;
+ uint32_t *x32;
+ uint16_t *x16;
+
+ /*
+ * Relocation address must be within virtual address
+ * range.
+ */
+ if (entry_offset > virt_size - rel->VirtualAddress) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ offset = rel->VirtualAddress + entry_offset;
+ x64 = efi_reloc + offset;
+ x32 = efi_reloc + offset;
+ x16 = efi_reloc + offset;
switch (type) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
+ if (sizeof(uint16_t) > virt_size - offset) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
*x16 += ((uint32_t)delta) >> 16;
break;
case IMAGE_REL_BASED_LOW:
+ if (sizeof(uint16_t) > virt_size - offset) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
*x16 += (uint16_t)delta;
break;
case IMAGE_REL_BASED_HIGHLOW:
+ if (sizeof(uint32_t) > virt_size - offset) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
*x32 += (uint32_t)delta;
break;
case IMAGE_REL_BASED_DIR64:
+ if (sizeof(uint64_t) > virt_size - offset) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
*x64 += (uint64_t)delta;
break;
#ifdef __riscv
case IMAGE_REL_BASED_RISCV_HI20:
+ if (sizeof(uint32_t) > virt_size - offset) {
+ log_debug("relocation address out of bounds\n");
+ return EFI_LOAD_ERROR;
+ }
*x32 = ((*x32 & 0xfffff000) + (uint32_t)delta) |
(*x32 & 0x00000fff);
break;
@@ -163,7 +226,7 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
break;
#endif
default:
- log_err("Unknown Relocation off %x type %x\n",
+ log_err("Unknown Relocation off %lx type %x\n",
offset, type);
return EFI_LOAD_ERROR;
}
@@ -970,8 +1033,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
/* Run through relocations */
if (efi_loader_relocate(rel, rel_size, efi_reloc,
- (unsigned long)image_base) != EFI_SUCCESS) {
- efi_free_pages((uintptr_t) efi_reloc,
+ (unsigned long)image_base,
+ virt_size) != EFI_SUCCESS) {
+ efi_free_pages((uintptr_t)efi_reloc,
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
ret = EFI_LOAD_ERROR;
goto err;
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index b77c2f980cc..c3da7c20cb2 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -128,44 +128,29 @@ static uint64_t desc_get_end(struct efi_mem_desc *desc)
*/
static void efi_mem_sort(void)
{
- struct efi_mem_list *lmem;
- struct efi_mem_list *prevmem = NULL;
- bool merge_again = true;
+ struct efi_mem_list *curmem, *nextmem = NULL;
list_sort(NULL, &efi_mem, efi_mem_cmp);
/* Now merge entries that can be merged */
- while (merge_again) {
- merge_again = false;
- list_for_each_entry(lmem, &efi_mem, link) {
- struct efi_mem_desc *prev;
- struct efi_mem_desc *cur;
- uint64_t pages;
-
- if (!prevmem) {
- prevmem = lmem;
- continue;
- }
-
- cur = &lmem->desc;
- prev = &prevmem->desc;
+ list_for_each_entry_safe(curmem, nextmem, &efi_mem, link) {
+ struct efi_mem_desc *cur;
+ struct efi_mem_desc *next;
- if ((desc_get_end(cur) == prev->physical_start) &&
- (prev->type == cur->type) &&
- (prev->attribute == cur->attribute)) {
- /* There is an existing map before, reuse it */
- pages = cur->num_pages;
- prev->num_pages += pages;
- prev->physical_start -= pages << EFI_PAGE_SHIFT;
- prev->virtual_start -= pages << EFI_PAGE_SHIFT;
- list_del(&lmem->link);
- free(lmem);
+ /* Exit when we've got nothing to compare with */
+ if (&nextmem->link == &efi_mem)
+ break;
- merge_again = true;
- break;
- }
+ cur = &curmem->desc;
+ next = &nextmem->desc;
- prevmem = lmem;
+ if ((cur->physical_start == desc_get_end(next)) &&
+ (cur->type == next->type) &&
+ (cur->attribute == next->attribute)) {
+ /* There is another similar map coming up, reuse it */
+ next->num_pages += cur->num_pages;
+ list_del(&curmem->link);
+ free(curmem);
}
}
}
@@ -510,7 +495,9 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
/* Map would overlap, bail out */
lmb_free(addr, (u64)pages << EFI_PAGE_SHIFT, flags);
unmap_sysmem((void *)(uintptr_t)efi_addr);
- return EFI_OUT_OF_RESOURCES;
+ if (type == EFI_ALLOCATE_ADDRESS)
+ return EFI_NOT_FOUND;
+ return EFI_OUT_OF_RESOURCES;
}
*memory = efi_addr;
@@ -884,7 +871,7 @@ static void add_u_boot_and_runtime(void)
/* Add U-Boot */
uboot_start = ((uintptr_t)map_sysmem(gd->start_addr_sp, 0) -
uboot_stack_size) & ~EFI_PAGE_MASK;
- uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) -
+ uboot_pages = ((uintptr_t)map_sysmem(gd->initial_relocaddr - 1, 0) -
uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
efi_update_memory_map(uboot_start, uboot_pages, EFI_BOOT_SERVICES_CODE,
false, false);
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index f06cf49e443..f302bb62ab9 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -392,5 +392,7 @@ efi_status_t efi_init_obj_list(void)
ret = efi_start_obj_list();
out:
efi_obj_list_initialized = ret;
+ if (ret != EFI_SUCCESS)
+ log_err("Cannot initialize UEFI sub-system\n");
return ret;
}
diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index 93a4f257016..f99a0c29d2b 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -703,8 +703,7 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl)
goto err;
}
- sig_data = calloc(esl->signature_size
- - sizeof(esd->signature_owner), 1);
+ sig_data = calloc(1, sizeof(*sig_data));
if (!sig_data) {
EFI_PRINT("Out of memory\n");
goto err;
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 1860dc50238..5f9bbe97455 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -352,8 +352,8 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this,
}
if (tcg2_platform_get_tpm2(&dev)) {
- event_log_location = NULL;
- event_log_last_entry = NULL;
+ *event_log_location = 0;
+ *event_log_last_entry = 0;
*event_log_truncated = false;
ret = EFI_SUCCESS;
goto out;
@@ -1343,8 +1343,8 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
header = dtb;
sha256_starts(&hash_ctx);
sha256_update(&hash_ctx, (u8 *)header, sizeof(struct fdt_header));
- sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_struct(dtb), fdt_size_dt_strings(dtb));
- sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_strings(dtb), fdt_size_dt_struct(dtb));
+ sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_struct(dtb), fdt_size_dt_struct(dtb));
+ sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_dt_strings(dtb), fdt_size_dt_strings(dtb));
sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size);
sha256_finish(&hash_ctx, blob->data + blob->blob_description_size);
@@ -1535,9 +1535,9 @@ static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
if (!data && !secure_variables[i].accept_empty)
continue;
- if (u16_strcmp(u"DeployedMode", secure_variables[i].name))
+ if (!u16_strcmp(u"DeployedMode", secure_variables[i].name))
secure_variables[i].pcr_index = deployed_audit_pcr_index;
- if (u16_strcmp(u"AuditMode", secure_variables[i].name))
+ if (!u16_strcmp(u"AuditMode", secure_variables[i].name))
secure_variables[i].pcr_index = deployed_audit_pcr_index;
ret = tcg2_measure_variable(dev, secure_variables[i].pcr_index,
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index d63c2d1b1cd..e51b21fe0b0 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -446,8 +446,10 @@ efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *
efi_status_t ret;
if ((uintptr_t)buf + len <=
- (uintptr_t)var->name + old_var_name_length)
+ (uintptr_t)var->name + old_var_name_length) {
+ free(buf);
return EFI_BUFFER_TOO_SMALL;
+ }
var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name;
memcpy(var->name, old_var->name, old_var_name_length);
diff --git a/lib/efi_loader/efi_var_seed.S b/lib/efi_loader/efi_var_seed.S
index e0a40cf46c8..008a505d19e 100644
--- a/lib/efi_loader/efi_var_seed.S
+++ b/lib/efi_loader/efi_var_seed.S
@@ -5,13 +5,11 @@
* Copyright (c) 2020, Heinrich Schuchardt <[email protected]>
*/
-#include <config.h>
-
.section .rodata.efi_seed.init,"a"
.balign 16
.global __efi_var_file_begin
__efi_var_file_begin:
-.incbin CONFIG_EFI_VAR_SEED_FILE
+.incbin EFI_VAR_SEED_FILE
.global __efi_var_file_end
__efi_var_file_end:
.balign 16