diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 1 | ||||
-rw-r--r-- | lib/efi_loader/Makefile | 5 | ||||
-rw-r--r-- | lib/efi_loader/efi_acpi.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 5 | ||||
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_common.c | 76 | ||||
-rw-r--r-- | lib/efi_loader/efi_var_file.c | 64 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 46 |
8 files changed, 117 insertions, 88 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index a7c3e05c13a..e13a6f9f4c3 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -44,7 +44,6 @@ config EFI_BINARY_EXEC config EFI_BOOTMGR bool "UEFI Boot Manager" default y - select BOOTMETH_GLOBAL if BOOTSTD help Select this option if you want to select the UEFI binary to be booted via UEFI variables Boot####, BootOrder, and BootNext. You should also diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index fcb0af7e7d6..034e366967f 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -6,8 +6,7 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it -asflags-y += -DHOST_ARCH="$(HOST_ARCH)" -I. -ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" +asflags-y += -I. CFLAGS_efi_boottime.o += \ -DFW_VERSION="0x$(VERSION)" \ @@ -72,11 +71,11 @@ obj-y += efi_string.o obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o obj-y += efi_var_common.o obj-y += efi_var_mem.o -obj-y += efi_var_file.o ifeq ($(CONFIG_EFI_MM_COMM_TEE),y) obj-y += efi_variable_tee.o else obj-y += efi_variable.o +obj-y += efi_var_file.o obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o endif obj-y += efi_watchdog.o diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 67bbd2a01c0..67bd7f8ca24 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -41,7 +41,7 @@ efi_status_t efi_acpi_register(void) } addr = gd_acpi_start(); - printf("EFI using ACPI tables at %lx\n", addr); + log_debug("EFI using ACPI tables at %lx\n", addr); /* And expose them to our EFI payload */ return efi_install_configuration_table(&acpi_guid, diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index edfad2d95a1..12cf23fa3fa 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -15,6 +15,7 @@ #include <watchdog.h> #include <asm/cache.h> #include <asm/global_data.h> +#include <asm/sections.h> #include <linux/list_sort.h> #include <linux/sizes.h> @@ -933,8 +934,8 @@ static void add_u_boot_and_runtime(void) * Add Runtime Services. We mark surrounding boottime code as runtime as * well to fulfill the runtime alignment constraints but avoid padding. */ - runtime_start = (ulong)&__efi_runtime_start & ~runtime_mask; - runtime_end = (ulong)&__efi_runtime_stop; + runtime_start = (uintptr_t)__efi_runtime_start & ~runtime_mask; + runtime_end = (uintptr_t)__efi_runtime_stop; runtime_end = (runtime_end + runtime_mask) & ~runtime_mask; runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; efi_add_memory_map_pg(runtime_start, runtime_pages, diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 9185f1894c4..a61c9a77b13 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -669,14 +669,14 @@ static __efi_runtime void efi_relocate_runtime_table(ulong offset) void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) { #ifdef IS_RELA - struct elf_rela *rel = (void*)&__efi_runtime_rel_start; + struct elf_rela *rel = (void *)__efi_runtime_rel_start; #else - struct elf_rel *rel = (void*)&__efi_runtime_rel_start; + struct elf_rel *rel = (void *)__efi_runtime_rel_start; static ulong lastoff = CONFIG_TEXT_BASE; #endif debug("%s: Relocating to offset=%lx\n", __func__, offset); - for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) { + for (; (uintptr_t)rel < (uintptr_t)__efi_runtime_rel_stop; rel++) { ulong base = CONFIG_TEXT_BASE; ulong *p; ulong newaddr; diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index d528747f3fb..aa8feffd3ec 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -9,6 +9,7 @@ #include <efi_loader.h> #include <efi_variable.h> #include <stdlib.h> +#include <u-boot/crc.h> enum efi_secure_mode { EFI_MODE_SETUP, @@ -99,7 +100,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, data_size, data); /* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */ - if (attributes & ~(u32)EFI_VARIABLE_MASK) + if (attributes & ~EFI_VARIABLE_MASK) ret = EFI_INVALID_PARAMETER; else ret = efi_set_variable_int(variable_name, vendor, attributes, @@ -416,3 +417,76 @@ void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size) return buf; } + +/** + * efi_var_collect() - Copy EFI variables mstching attributes mask + * + * @bufp: buffer containing variable collection + * @lenp: buffer length + * @attr_mask: mask of matched attributes + * + * Return: Status code + */ +efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp, + u32 check_attr_mask) +{ + size_t len = EFI_VAR_BUF_SIZE; + struct efi_var_file *buf; + struct efi_var_entry *var, *old_var; + size_t old_var_name_length = 2; + + *bufp = NULL; /* Avoid double free() */ + buf = calloc(1, len); + if (!buf) + return EFI_OUT_OF_RESOURCES; + var = buf->var; + old_var = var; + for (;;) { + efi_uintn_t data_length, var_name_length; + u8 *data; + efi_status_t ret; + + if ((uintptr_t)buf + len <= + (uintptr_t)var->name + old_var_name_length) + 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); + guidcpy(&var->guid, &old_var->guid); + ret = efi_get_next_variable_name_int( + &var_name_length, var->name, &var->guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret != EFI_SUCCESS) { + free(buf); + return ret; + } + old_var_name_length = var_name_length; + old_var = var; + + data = (u8 *)var->name + old_var_name_length; + data_length = (uintptr_t)buf + len - (uintptr_t)data; + ret = efi_get_variable_int(var->name, &var->guid, + &var->attr, &data_length, data, + &var->time); + if (ret != EFI_SUCCESS) { + free(buf); + return ret; + } + if ((var->attr & check_attr_mask) == check_attr_mask) { + var->length = data_length; + var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8); + } + } + + buf->reserved = 0; + buf->magic = EFI_VAR_FILE_MAGIC; + len = (uintptr_t)var - (uintptr_t)buf; + buf->crc32 = crc32(0, (u8 *)buf->var, + len - sizeof(struct efi_var_file)); + buf->length = len; + *bufp = buf; + *lenp = len; + + return EFI_SUCCESS; +} diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index 532b6b40eef..413e1794e88 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -52,70 +52,6 @@ static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void) return EFI_SUCCESS; } -efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp, - u32 check_attr_mask) -{ - size_t len = EFI_VAR_BUF_SIZE; - struct efi_var_file *buf; - struct efi_var_entry *var, *old_var; - size_t old_var_name_length = 2; - - *bufp = NULL; /* Avoid double free() */ - buf = calloc(1, len); - if (!buf) - return EFI_OUT_OF_RESOURCES; - var = buf->var; - old_var = var; - for (;;) { - efi_uintn_t data_length, var_name_length; - u8 *data; - efi_status_t ret; - - if ((uintptr_t)buf + len <= - (uintptr_t)var->name + old_var_name_length) - 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); - guidcpy(&var->guid, &old_var->guid); - ret = efi_get_next_variable_name_int( - &var_name_length, var->name, &var->guid); - if (ret == EFI_NOT_FOUND) - break; - if (ret != EFI_SUCCESS) { - free(buf); - return ret; - } - old_var_name_length = var_name_length; - old_var = var; - - data = (u8 *)var->name + old_var_name_length; - data_length = (uintptr_t)buf + len - (uintptr_t)data; - ret = efi_get_variable_int(var->name, &var->guid, - &var->attr, &data_length, data, - &var->time); - if (ret != EFI_SUCCESS) { - free(buf); - return ret; - } - if ((var->attr & check_attr_mask) == check_attr_mask) { - var->length = data_length; - var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8); - } - } - - buf->reserved = 0; - buf->magic = EFI_VAR_FILE_MAGIC; - len = (uintptr_t)var - (uintptr_t)buf; - buf->crc32 = crc32(0, (u8 *)buf->var, - len - sizeof(struct efi_var_file)); - buf->length = len; - *bufp = buf; - *lenp = len; - - return EFI_SUCCESS; -} - /** * efi_var_to_file() - save non-volatile variables as file * diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 40f7a0fb10d..e6c1219a11c 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -163,6 +163,7 @@ static efi_status_t efi_variable_authenticate(const u16 *variable, break; default: /* TODO: support private authenticated variables */ + ret = EFI_UNSUPPORTED; goto err; } @@ -235,8 +236,12 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, if (data_size && !data) return EFI_INVALID_PARAMETER; - /* EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated */ - if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + /* + * EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated. + * We don't support EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS. + */ + if (attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS)) return EFI_UNSUPPORTED; /* Make sure if runtime bit is set, boot service bit is set also */ @@ -259,7 +264,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, /* check if a variable exists */ var = efi_var_mem_find(vendor, variable_name, NULL); append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); - attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE; + attributes &= ~EFI_VARIABLE_APPEND_WRITE; delete = !append && (!data_size || !attributes); /* check attributes */ @@ -276,17 +281,27 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, /* attributes won't be changed */ if (!delete && ((ro_check && var->attr != attributes) || - (!ro_check && ((var->attr & ~(u32)EFI_VARIABLE_READ_ONLY) - != (attributes & ~(u32)EFI_VARIABLE_READ_ONLY))))) { + (!ro_check && ((var->attr & ~EFI_VARIABLE_READ_ONLY) + != (attributes & ~EFI_VARIABLE_READ_ONLY))))) { return EFI_INVALID_PARAMETER; } time = var->time; } else { - if (delete || append) - /* - * Trying to delete or to update a non-existent - * variable. - */ + /* + * UEFI specification does not clearly describe the expected + * behavior of append write with data size 0, we follow + * the EDK II reference implementation. + */ + if (append && !data_size) + return EFI_SUCCESS; + + /* + * EFI_VARIABLE_APPEND_WRITE to non-existent variable is accepted + * and new variable is created in EDK II reference implementation. + * We follow it and only check the deletion here. + */ + if (delete) + /* Trying to delete a non-existent variable. */ return EFI_NOT_FOUND; } @@ -329,7 +344,11 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, /* EFI_NOT_FOUND has been handled before */ attributes = var->attr; ret = EFI_SUCCESS; - } else if (append) { + } else if (append && var) { + /* + * data is appended if EFI_VARIABLE_APPEND_WRITE is set and + * variable exists. + */ u16 *old_data = var->name; for (; *old_data; ++old_data) @@ -342,11 +361,12 @@ efi_status_t efi_set_variable_int(const u16 *variable_name, ret = efi_var_mem_ins(variable_name, vendor, attributes, data_size, data, 0, NULL, time); } - efi_var_mem_del(var); if (ret != EFI_SUCCESS) return ret; + efi_var_mem_del(var); + if (var_type == EFI_AUTH_VAR_PK) ret = efi_init_secure_state(); else @@ -384,7 +404,7 @@ efi_status_t efi_query_variable_info_int(u32 attributes, EFI_VARIABLE_RUNTIME_ACCESS) return EFI_INVALID_PARAMETER; - if (attributes & ~(u32)EFI_VARIABLE_MASK) + if (attributes & ~EFI_VARIABLE_MASK) return EFI_INVALID_PARAMETER; *maximum_variable_storage_size = EFI_VAR_BUF_SIZE - |