diff options
Diffstat (limited to 'lib/efi_loader')
| -rw-r--r-- | lib/efi_loader/Kconfig | 8 | ||||
| -rw-r--r-- | lib/efi_loader/Makefile | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_bootbin.c | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_boottime.c | 2 | ||||
| -rw-r--r-- | lib/efi_loader/efi_console.c | 7 | ||||
| -rw-r--r-- | lib/efi_loader/efi_device_path.c | 4 | ||||
| -rw-r--r-- | lib/efi_loader/efi_disk.c | 1 | ||||
| -rw-r--r-- | lib/efi_loader/efi_dt_fixup.c | 3 | ||||
| -rw-r--r-- | lib/efi_loader/efi_hii.c | 3 | ||||
| -rw-r--r-- | lib/efi_loader/efi_image_loader.c | 86 | ||||
| -rw-r--r-- | lib/efi_loader/efi_memory.c | 53 | ||||
| -rw-r--r-- | lib/efi_loader/efi_setup.c | 2 | ||||
| -rw-r--r-- | lib/efi_loader/efi_signature.c | 3 | ||||
| -rw-r--r-- | lib/efi_loader/efi_tcg2.c | 12 | ||||
| -rw-r--r-- | lib/efi_loader/efi_var_common.c | 4 | ||||
| -rw-r--r-- | lib/efi_loader/efi_var_seed.S | 4 |
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 |
