summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/Kconfig1
-rw-r--r--lib/efi_loader/Makefile5
-rw-r--r--lib/efi_loader/efi_acpi.c2
-rw-r--r--lib/efi_loader/efi_memory.c5
-rw-r--r--lib/efi_loader/efi_runtime.c6
-rw-r--r--lib/efi_loader/efi_var_common.c76
-rw-r--r--lib/efi_loader/efi_var_file.c64
-rw-r--r--lib/efi_loader/efi_variable.c46
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 -