aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-01-14 08:50:23 -0500
committerTom Rini <trini@konsulko.com>2021-01-14 08:50:23 -0500
commit35772ff4f63a302e0b873096372c70292fb0af79 (patch)
treeffa00f958cf61d12a9348b27699e3980f9d9f15d
parentab1a425524a79eeca61e7b67fdf382c7a499346f (diff)
parent8e70f1cb3f2c18d574b087d4fc1d79e68ce98fa9 (diff)
downloadu-boot-WIP/14Jan2021.zip
u-boot-WIP/14Jan2021.tar.gz
u-boot-WIP/14Jan2021.tar.bz2
Merge tag 'efi-2021-04-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot-efiWIP/14Jan2021
Pull request for UEFI sub-system for efi-2021-04-rc1 In the UEFI sub-system: * implement non-blocking file services * print boot device and file path in helloworld.efi * improve detection of boot device * correct argument handling in efivar.py * implement EFI_DT_FIXUP_PROTOCOL Bug fixes: * adjust conitrace command for low baud rates * check that FIT images are valid FDTs
-rw-r--r--cmd/bootefi.c234
-rw-r--r--cmd/conitrace.c4
-rw-r--r--cmd/efidebug.c5
-rw-r--r--common/image-fit.c6
-rw-r--r--doc/uefi/uefi.rst11
-rw-r--r--fs/fs.c3
-rw-r--r--include/efi.h5
-rw-r--r--include/efi_api.h34
-rw-r--r--include/efi_dt_fixup.h39
-rw-r--r--include/efi_loader.h10
-rw-r--r--lib/efi_loader/Makefile3
-rw-r--r--lib/efi_loader/efi_console.c6
-rw-r--r--lib/efi_loader/efi_dt_fixup.c160
-rw-r--r--lib/efi_loader/efi_file.c317
-rw-r--r--lib/efi_loader/efi_image_loader.c80
-rw-r--r--lib/efi_loader/efi_memory.c2
-rw-r--r--lib/efi_loader/efi_root_node.c6
-rw-r--r--lib/efi_loader/helloworld.c167
-rw-r--r--lib/efi_selftest/dtbdump.c310
-rw-r--r--net/tftp.c9
-rwxr-xr-xtools/efivar.py39
21 files changed, 1096 insertions, 354 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index fdf909f..fe70eec 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -29,6 +29,82 @@ DECLARE_GLOBAL_DATA_PTR;
static struct efi_device_path *bootefi_image_path;
static struct efi_device_path *bootefi_device_path;
+static void *image_addr;
+static size_t image_size;
+
+/**
+ * efi_clear_bootdev() - clear boot device
+ */
+static void efi_clear_bootdev(void)
+{
+ efi_free_pool(bootefi_device_path);
+ efi_free_pool(bootefi_image_path);
+ bootefi_device_path = NULL;
+ bootefi_image_path = NULL;
+ image_addr = NULL;
+ image_size = 0;
+}
+
+/**
+ * efi_set_bootdev() - set boot device
+ *
+ * This function is called when a file is loaded, e.g. via the 'load' command.
+ * We use the path to this file to inform the UEFI binary about the boot device.
+ *
+ * @dev: device, e.g. "MMC"
+ * @devnr: number of the device, e.g. "1:2"
+ * @path: path to file loaded
+ * @buffer: buffer with file loaded
+ * @buffer_size: size of file loaded
+ */
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
+ void *buffer, size_t buffer_size)
+{
+ struct efi_device_path *device, *image;
+ efi_status_t ret;
+
+ /* Forget overwritten image */
+ if (buffer + buffer_size >= image_addr &&
+ image_addr + image_size >= buffer)
+ efi_clear_bootdev();
+
+ /* Remember only PE-COFF and FIT images */
+ if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
+#ifdef CONFIG_FIT
+ if (!fit_check_format(buffer))
+ return;
+ /*
+ * FIT images of type EFI_OS are started via command bootm.
+ * We should not use their boot device with the bootefi command.
+ */
+ buffer = 0;
+ buffer_size = 0;
+#else
+ return;
+#endif
+ }
+
+ /* efi_set_bootdev() is typically called repeatedly, recover memory */
+ efi_clear_bootdev();
+
+ image_addr = buffer;
+ image_size = buffer_size;
+
+ ret = efi_dp_from_name(dev, devnr, path, &device, &image);
+ if (ret == EFI_SUCCESS) {
+ bootefi_device_path = device;
+ if (image) {
+ /* FIXME: image should not contain device */
+ struct efi_device_path *image_tmp = image;
+
+ efi_dp_split_file_path(image, &device, &image);
+ efi_free_pool(image_tmp);
+ }
+ bootefi_image_path = image;
+ } else {
+ efi_clear_bootdev();
+ }
+}
/**
* efi_env_set_load_options() - set load options from environment variable
@@ -136,86 +212,6 @@ done:
}
/**
- * 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. */
- addr = (uintptr_t)map_sysmem(addr, 0);
-
- 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",
- addr, size);
-}
-
-/**
- * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
- *
- * The mem_rsv entries of the FDT are added to the memory map. Any failures are
- * ignored because this is not critical and we would rather continue to try to
- * boot.
- *
- * @fdt: Pointer to device tree
- */
-static void efi_carve_out_dt_rsv(void *fdt)
-{
- int nr_rsv, i;
- u64 addr, size;
- int nodeoffset, subnode;
-
- nr_rsv = fdt_num_mem_rsv(fdt);
-
- /* Look for an existing entry and add it to the efi mem map. */
- for (i = 0; i < nr_rsv; i++) {
- if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
- continue;
- efi_reserve_memory(addr, size, false);
- }
-
- /* process reserved-memory */
- nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory");
- if (nodeoffset >= 0) {
- subnode = fdt_first_subnode(fdt, nodeoffset);
- while (subnode >= 0) {
- fdt_addr_t fdt_addr;
- fdt_size_t fdt_size;
-
- /* check if this subnode has a reg property */
- fdt_addr = fdtdec_get_addr_size_auto_parent(
- fdt, nodeoffset, subnode,
- "reg", 0, &fdt_size, false);
- /*
- * The /reserved-memory node may have children with
- * a size instead of a reg property.
- */
- if (fdt_addr != FDT_ADDR_T_NONE &&
- fdtdec_get_is_enabled(fdt, subnode)) {
- bool nomap;
-
- nomap = !!fdt_getprop(fdt, subnode, "no-map",
- NULL);
- efi_reserve_memory(fdt_addr, fdt_size, nomap);
- }
- subnode = fdt_next_subnode(fdt, subnode);
- }
- }
-}
-
-/**
* get_config_table() - get configuration table
*
* @guid: GUID of the configuration table
@@ -398,43 +394,28 @@ static int do_bootefi_image(const char *image_opt)
{
void *image_buf;
unsigned long addr, size;
- const char *size_str;
efi_status_t ret;
#ifdef CONFIG_CMD_BOOTEFI_HELLO
if (!strcmp(image_opt, "hello")) {
- char *saddr;
-
- saddr = env_get("loadaddr");
+ image_buf = __efi_helloworld_begin;
size = __efi_helloworld_end - __efi_helloworld_begin;
-
- if (saddr)
- addr = simple_strtoul(saddr, NULL, 16);
- else
- addr = CONFIG_SYS_LOAD_ADDR;
-
- image_buf = map_sysmem(addr, size);
- memcpy(image_buf, __efi_helloworld_begin, size);
-
- efi_free_pool(bootefi_device_path);
- efi_free_pool(bootefi_image_path);
- bootefi_device_path = NULL;
- bootefi_image_path = NULL;
+ efi_clear_bootdev();
} else
#endif
{
- size_str = env_get("filesize");
- if (size_str)
- size = simple_strtoul(size_str, NULL, 16);
- else
- size = 0;
-
- addr = simple_strtoul(image_opt, NULL, 16);
+ addr = strtoul(image_opt, NULL, 16);
/* Check that a numeric value was passed */
- if (!addr && *image_opt != '0')
+ if (!addr)
return CMD_RET_USAGE;
- image_buf = map_sysmem(addr, size);
+ image_buf = map_sysmem(addr, 0);
+
+ if (image_buf != image_addr) {
+ log_err("No UEFI binary known at %s\n", image_opt);
+ return CMD_RET_FAILURE;
+ }
+ size = image_size;
}
ret = efi_run_image(image_buf, size);
@@ -567,11 +548,8 @@ static efi_status_t bootefi_test_prepare
if (ret == EFI_SUCCESS)
return ret;
- efi_free_pool(bootefi_image_path);
- bootefi_image_path = NULL;
failure:
- efi_free_pool(bootefi_device_path);
- bootefi_device_path = NULL;
+ efi_clear_bootdev();
return ret;
}
@@ -691,39 +669,3 @@ U_BOOT_CMD(
"Boots an EFI payload from memory",
bootefi_help_text
);
-
-/**
- * efi_set_bootdev() - set boot device
- *
- * This function is called when a file is loaded, e.g. via the 'load' command.
- * We use the path to this file to inform the UEFI binary about the boot device.
- *
- * @dev: device, e.g. "MMC"
- * @devnr: number of the device, e.g. "1:2"
- * @path: path to file loaded
- */
-void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
-{
- struct efi_device_path *device, *image;
- efi_status_t ret;
-
- /* efi_set_bootdev is typically called repeatedly, recover memory */
- efi_free_pool(bootefi_device_path);
- efi_free_pool(bootefi_image_path);
-
- ret = efi_dp_from_name(dev, devnr, path, &device, &image);
- if (ret == EFI_SUCCESS) {
- bootefi_device_path = device;
- if (image) {
- /* FIXME: image should not contain device */
- struct efi_device_path *image_tmp = image;
-
- efi_dp_split_file_path(image, &device, &image);
- efi_free_pool(image_tmp);
- }
- bootefi_image_path = image;
- } else {
- bootefi_device_path = NULL;
- bootefi_image_path = NULL;
- }
-}
diff --git a/cmd/conitrace.c b/cmd/conitrace.c
index 811f5c6..d50f3bf 100644
--- a/cmd/conitrace.c
+++ b/cmd/conitrace.c
@@ -30,8 +30,8 @@ static int do_conitrace(struct cmd_tbl *cmdtp, int flag, int argc,
printf("%02x ", c);
first = false;
- /* 1 ms delay - serves to detect separate keystrokes */
- udelay(1000);
+ /* 10 ms delay - serves to detect separate keystrokes */
+ udelay(10000);
if (!tstc()) {
printf("\n");
first = true;
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 5fb7b1e..6de81ca 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -8,6 +8,7 @@
#include <charset.h>
#include <common.h>
#include <command.h>
+#include <efi_dt_fixup.h>
#include <efi_loader.h>
#include <efi_rng.h>
#include <exports.h>
@@ -495,6 +496,10 @@ static const struct {
"PXE Base Code",
EFI_PXE_BASE_CODE_PROTOCOL_GUID,
},
+ {
+ "Device-Tree Fixup",
+ EFI_DT_FIXUP_PROTOCOL_GUID,
+ },
/* Configuration table GUIDs */
{
"ACPI table",
diff --git a/common/image-fit.c b/common/image-fit.c
index 6a8787c..21c44bd 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1553,6 +1553,12 @@ int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
*/
int fit_check_format(const void *fit)
{
+ /* A FIT image must be a valid FDT */
+ if (fdt_check_header(fit)) {
+ debug("Wrong FIT format: not a flattened device tree\n");
+ return 0;
+ }
+
/* mandatory / node 'description' property */
if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
debug("Wrong FIT format: no description\n");
diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst
index dc930d9..5a67737 100644
--- a/doc/uefi/uefi.rst
+++ b/doc/uefi/uefi.rst
@@ -59,13 +59,10 @@ Below you find the output of an example session starting GRUB::
120832 bytes read in 7 ms (16.5 MiB/s)
=> bootefi ${kernel_addr_r} ${fdt_addr_r}
-The bootefi command uses the device, the file name, and the file size
-(environment variable 'filesize') of the most recently loaded file when setting
-up the binary for execution. So the UEFI binary should be loaded last.
-
-The environment variable 'bootargs' is passed as load options in the UEFI system
-table. The Linux kernel EFI stub uses the load options as command line
-arguments.
+When booting from a memory location it is unknown from which file it was loaded.
+Therefore the bootefi command uses the device path of the block device partition
+or the network adapter and the file name of the most recently loaded PE-COFF
+file when setting up the loaded image protocol.
Launching a UEFI binary from a FIT image
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/fs/fs.c b/fs/fs.c
index 5e80648..68a1555 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -752,7 +752,8 @@ int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "",
- (argc > 4) ? argv[4] : "");
+ (argc > 4) ? argv[4] : "", map_sysmem(addr, 0),
+ len_read);
printf("%llu bytes read in %lu ms", len_read, time);
if (time > 0) {
diff --git a/include/efi.h b/include/efi.h
index 5695273..503fbf0 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -20,6 +20,11 @@
#include <linux/string.h>
#include <linux/types.h>
+/* Type INTN in UEFI specification */
+#define efi_intn_t ssize_t
+/* Type UINTN in UEFI specification*/
+#define efi_uintn_t size_t
+
/*
* EFI on x86_64 uses the Microsoft ABI which is not the default for GCC.
*
diff --git a/include/efi_api.h b/include/efi_api.h
index ecb43a0..df9bee2 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -34,8 +34,6 @@ enum efi_timer_delay {
EFI_TIMER_RELATIVE = 2
};
-#define efi_intn_t ssize_t
-#define efi_uintn_t size_t
typedef void *efi_hii_handle_t;
typedef u16 *efi_string_t;
typedef u16 efi_string_id_t;
@@ -703,10 +701,10 @@ struct efi_simple_text_output_protocol {
char extended_verification);
efi_status_t (EFIAPI *output_string)(
struct efi_simple_text_output_protocol *this,
- const efi_string_t str);
+ const u16 *str);
efi_status_t (EFIAPI *test_string)(
struct efi_simple_text_output_protocol *this,
- const efi_string_t str);
+ const u16 *str);
efi_status_t(EFIAPI *query_mode)(
struct efi_simple_text_output_protocol *this,
unsigned long mode_number, unsigned long *columns,
@@ -1589,35 +1587,35 @@ struct efi_file_io_token {
struct efi_file_handle {
u64 rev;
- efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *open)(struct efi_file_handle *this,
struct efi_file_handle **new_handle,
u16 *file_name, u64 open_mode, u64 attributes);
- efi_status_t (EFIAPI *close)(struct efi_file_handle *file);
- efi_status_t (EFIAPI *delete)(struct efi_file_handle *file);
- efi_status_t (EFIAPI *read)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *close)(struct efi_file_handle *this);
+ efi_status_t (EFIAPI *delete)(struct efi_file_handle *this);
+ efi_status_t (EFIAPI *read)(struct efi_file_handle *this,
efi_uintn_t *buffer_size, void *buffer);
- efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *write)(struct efi_file_handle *this,
efi_uintn_t *buffer_size, void *buffer);
- efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *getpos)(struct efi_file_handle *this,
u64 *pos);
- efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *setpos)(struct efi_file_handle *this,
u64 pos);
- efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *this,
const efi_guid_t *info_type, efi_uintn_t *buffer_size,
void *buffer);
- efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *this,
const efi_guid_t *info_type, efi_uintn_t buffer_size,
void *buffer);
- efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
- efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *flush)(struct efi_file_handle *this);
+ efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *this,
struct efi_file_handle **new_handle,
u16 *file_name, u64 open_mode, u64 attributes,
struct efi_file_io_token *token);
- efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *this,
struct efi_file_io_token *token);
- efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *this,
struct efi_file_io_token *token);
- efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file,
+ efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *this,
struct efi_file_io_token *token);
};
diff --git a/include/efi_dt_fixup.h b/include/efi_dt_fixup.h
new file mode 100644
index 0000000..9066e8d
--- /dev/null
+++ b/include/efi_dt_fixup.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * EFI_DT_FIXUP_PROTOCOL
+ *
+ * Copyright (c) 2020 Heinrich Schuchardt
+ */
+
+#include <efi_api.h>
+
+#define EFI_DT_FIXUP_PROTOCOL_GUID \
+ EFI_GUID(0xe617d64c, 0xfe08, 0x46da, 0xf4, 0xdc, \
+ 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00)
+
+#define EFI_DT_FIXUP_PROTOCOL_REVISION 0x00010000
+
+/* Add nodes and update properties */
+#define EFI_DT_APPLY_FIXUPS 0x00000001
+/*
+ * Reserve memory according to the /reserved-memory node
+ * and the memory reservation block
+ */
+#define EFI_DT_RESERVE_MEMORY 0x00000002
+/* Install the device-tree as configuration table */
+#define EFI_DT_INSTALL_TABLE 0x00000004
+
+#define EFI_DT_ALL (EFI_DT_APPLY_FIXUPS | \
+ EFI_DT_RESERVE_MEMORY | \
+ EFI_DT_INSTALL_TABLE)
+
+struct efi_dt_fixup_protocol {
+ u64 revision;
+ efi_status_t (EFIAPI *fixup) (struct efi_dt_fixup_protocol *this,
+ void *dtb,
+ efi_uintn_t *buffer_size,
+ u32 flags);
+};
+
+extern struct efi_dt_fixup_protocol efi_dt_fixup_prot;
+extern const efi_guid_t efi_guid_dt_fixup_protocol;
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 4719fa9..e53d286 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -411,6 +411,8 @@ void efi_runtime_detach(void);
/* efi_convert_pointer() - convert pointer to virtual address */
efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t debug_disposition,
void **address);
+/* Carve out DT reserved memory ranges */
+void efi_carve_out_dt_rsv(void *fdt);
/* Called by bootefi to make console interface available */
efi_status_t efi_console_register(void);
/* Called by bootefi to make all disk storage accessible as EFI objects */
@@ -460,6 +462,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout);
/* Called from places to check whether a timer expired */
void efi_timer_check(void);
+/* Check if a buffer contains a PE-COFF image */
+efi_status_t efi_check_pe(void *buffer, size_t size, void **nt_header);
/* PE loader implementation */
efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
void *efi, size_t efi_size,
@@ -472,7 +476,8 @@ void efi_restore_gd(void);
/* Call this to relocate the runtime section to an address space */
void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
/* Call this to set the current device name */
-void efi_set_bootdev(const char *dev, const char *devnr, const char *path);
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
+ void *buffer, size_t buffer_size);
/* Add a new object to the object list. */
void efi_add_handle(efi_handle_t obj);
/* Create handle */
@@ -871,7 +876,8 @@ static inline efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
/* No loader configured, stub out EFI_ENTRY */
static inline void efi_restore_gd(void) { }
static inline void efi_set_bootdev(const char *dev, const char *devnr,
- const char *path) { }
+ const char *path, void *buffer,
+ size_t buffer_size) { }
static inline void efi_net_set_dhcp_ack(void *pkt, int len) { }
static inline void efi_print_image_infos(void *pc) { }
static inline efi_status_t efi_launch_capsules(void)
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 462d4d9..412fa88 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -29,6 +29,9 @@ obj-y += efi_console.o
obj-y += efi_device_path.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
obj-y += efi_device_path_utilities.o
+ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
+obj-y += efi_dt_fixup.o
+endif
obj-y += efi_file.o
obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o
obj-y += efi_image_loader.o
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 7051095..edcfce7 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -141,12 +141,12 @@ static int term_read_reply(int *n, int num, char end_char)
*/
static efi_status_t EFIAPI efi_cout_output_string(
struct efi_simple_text_output_protocol *this,
- const efi_string_t string)
+ const u16 *string)
{
struct simple_text_output_mode *con = &efi_con_mode;
struct cout_mode *mode = &efi_cout_modes[con->mode];
char *buf, *pos;
- u16 *p;
+ const u16 *p;
efi_status_t ret = EFI_SUCCESS;
EFI_ENTRY("%p, %p", this, string);
@@ -230,7 +230,7 @@ out:
*/
static efi_status_t EFIAPI efi_cout_test_string(
struct efi_simple_text_output_protocol *this,
- const efi_string_t string)
+ const u16 *string)
{
EFI_ENTRY("%p, %p", this, string);
return EFI_EXIT(EFI_SUCCESS);
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
new file mode 100644
index 0000000..5f0ae5c
--- /dev/null
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI_DT_FIXUP_PROTOCOL
+ *
+ * Copyright (c) 2020 Heinrich Schuchardt
+ */
+
+#include <common.h>
+#include <efi_dt_fixup.h>
+#include <efi_loader.h>
+#include <mapmem.h>
+
+static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
+ void *dtb,
+ efi_uintn_t *buffer_size,
+ u32 flags);
+
+struct efi_dt_fixup_protocol efi_dt_fixup_prot = {
+ .revision = EFI_DT_FIXUP_PROTOCOL_REVISION,
+ .fixup = efi_dt_fixup
+};
+
+const efi_guid_t efi_guid_dt_fixup_protocol = EFI_DT_FIXUP_PROTOCOL_GUID;
+
+/**
+ * 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. */
+ addr = (uintptr_t)map_sysmem(addr, 0);
+
+ 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",
+ addr, size);
+}
+
+/**
+ * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges
+ *
+ * The mem_rsv entries of the FDT are added to the memory map. Any failures are
+ * ignored because this is not critical and we would rather continue to try to
+ * boot.
+ *
+ * @fdt: Pointer to device tree
+ */
+void efi_carve_out_dt_rsv(void *fdt)
+{
+ int nr_rsv, i;
+ u64 addr, size;
+ int nodeoffset, subnode;
+
+ nr_rsv = fdt_num_mem_rsv(fdt);
+
+ /* Look for an existing entry and add it to the efi mem map. */
+ for (i = 0; i < nr_rsv; i++) {
+ if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
+ continue;
+ efi_reserve_memory(addr, size, false);
+ }
+
+ /* process reserved-memory */
+ nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory");
+ if (nodeoffset >= 0) {
+ subnode = fdt_first_subnode(fdt, nodeoffset);
+ while (subnode >= 0) {
+ fdt_addr_t fdt_addr;
+ fdt_size_t fdt_size;
+
+ /* check if this subnode has a reg property */
+ fdt_addr = fdtdec_get_addr_size_auto_parent(
+ fdt, nodeoffset, subnode,
+ "reg", 0, &fdt_size, false);
+ /*
+ * The /reserved-memory node may have children with
+ * a size instead of a reg property.
+ */
+ if (fdt_addr != FDT_ADDR_T_NONE &&
+ fdtdec_get_is_enabled(fdt, subnode)) {
+ bool nomap;
+
+ nomap = !!fdt_getprop(fdt, subnode, "no-map",
+ NULL);
+ efi_reserve_memory(fdt_addr, fdt_size, nomap);
+ }
+ subnode = fdt_next_subnode(fdt, subnode);
+ }
+ }
+}
+
+static efi_status_t EFIAPI efi_dt_fixup(struct efi_dt_fixup_protocol *this,
+ void *dtb,
+ efi_uintn_t *buffer_size,
+ u32 flags)
+{
+ efi_status_t ret;
+ size_t required_size;
+ bootm_headers_t img = { 0 };
+
+ EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags);
+
+ if (this != &efi_dt_fixup_prot || !dtb || !buffer_size ||
+ !flags || (flags & ~EFI_DT_ALL)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (fdt_check_header(dtb)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (flags & EFI_DT_APPLY_FIXUPS) {
+ required_size = fdt_off_dt_strings(dtb) +
+ fdt_size_dt_strings(dtb) +
+ 0x3000;
+ } else {
+ required_size = fdt_totalsize(dtb);
+ }
+ if (required_size > *buffer_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
+ fdt_set_totalsize(dtb, *buffer_size);
+
+ if (flags & EFI_DT_APPLY_FIXUPS) {
+ if (image_setup_libfdt(&img, dtb, 0, NULL)) {
+ log_err("failed to process device tree\n");
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ }
+ if (flags & EFI_DT_RESERVE_MEMORY)
+ efi_carve_out_dt_rsv(dtb);
+
+ if (EFI_DT_INSTALL_TABLE) {
+ ret = efi_install_configuration_table(&efi_guid_fdt, dtb);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: failed to install device tree\n");
+ goto out;
+ }
+ }
+
+ ret = EFI_SUCCESS;
+out:
+ return EFI_EXIT(ret);
+}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 72b7ec1..8ece8e7 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -246,18 +246,16 @@ error:
return NULL;
}
-static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
- struct efi_file_handle **new_handle,
- u16 *file_name, u64 open_mode, u64 attributes)
+static efi_status_t efi_file_open_int(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes)
{
- struct file_handle *fh = to_fh(file);
+ struct file_handle *fh = to_fh(this);
efi_status_t ret;
- EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle,
- file_name, open_mode, attributes);
-
/* Check parameters */
- if (!file || !new_handle || !file_name) {
+ if (!this || !new_handle || !file_name) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -292,6 +290,75 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
ret = EFI_NOT_FOUND;
}
out:
+ return ret;
+}
+
+/**
+ * efi_file_open_()
+ *
+ * This function implements the Open service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: EFI_FILE_PROTOCOL instance
+ * @new_handle: on return pointer to file handle
+ * @file_name: file name
+ * @open_mode: mode to open the file (read, read/write, create/read/write)
+ * @attributes: attributes for newly created file
+ */
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", this, new_handle,
+ file_name, open_mode, attributes);
+
+ ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+ attributes);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_open_ex() - open file asynchronously
+ *
+ * This function implements the OpenEx service of the File Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this: EFI_FILE_PROTOCOL instance
+ * @new_handle: on return pointer to file handle
+ * @file_name: file name
+ * @open_mode: mode to open the file (read, read/write, create/read/write)
+ * @attributes: attributes for newly created file
+ * @token: transaction token
+ */
+static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *this,
+ struct efi_file_handle **new_handle,
+ u16 *file_name, u64 open_mode,
+ u64 attributes,
+ struct efi_file_io_token *token)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu, %p", this, new_handle,
+ file_name, open_mode, attributes, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_open_int(this, new_handle, file_name, open_mode,
+ attributes);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
return EFI_EXIT(ret);
}
@@ -441,19 +508,15 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
return EFI_SUCCESS;
}
-static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
- efi_uintn_t *buffer_size, void *buffer)
+static efi_status_t efi_file_read_int(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
{
- struct file_handle *fh = to_fh(file);
+ struct file_handle *fh = to_fh(this);
efi_status_t ret = EFI_SUCCESS;
u64 bs;
- EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
- if (!buffer_size) {
- ret = EFI_INVALID_PARAMETER;
- goto error;
- }
+ if (!this || !buffer_size || !buffer)
+ return EFI_INVALID_PARAMETER;
bs = *buffer_size;
if (fh->isdir)
@@ -465,34 +528,77 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
else
*buffer_size = SIZE_MAX;
-error:
+ return ret;
+}
+
+/**
+ * efi_file_read() - read file
+ *
+ * This function implements the Read() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @buffer_size: number of bytes to read
+ * @buffer: read buffer
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+ ret = efi_file_read_int(this, buffer_size, buffer);
+
return EFI_EXIT(ret);
}
/**
- * efi_file_write() - write to file
+ * efi_file_read_ex() - read file asynchonously
*
- * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ * This function implements the ReadEx() service of the EFI_FILE_PROTOCOL.
*
* See the Unified Extensible Firmware Interface (UEFI) specification for
* details.
*
- * @file: file handle
- * @buffer_size: number of bytes to write
- * @buffer: buffer with the bytes to write
+ * @this: file protocol instance
+ * @token: transaction token
* Return: status code
*/
-static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
- efi_uintn_t *buffer_size,
- void *buffer)
+static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
{
- struct file_handle *fh = to_fh(file);
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_read_int(this, &token->buffer_size, token->buffer);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
+ return EFI_EXIT(ret);
+}
+
+static efi_status_t efi_file_write_int(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size, void *buffer)
+{
+ struct file_handle *fh = to_fh(this);
efi_status_t ret = EFI_SUCCESS;
loff_t actwrite;
- EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
-
- if (!file || !buffer_size || !buffer) {
+ if (!this || !buffer_size || !buffer) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@@ -521,6 +627,67 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
fh->offset += actwrite;
out:
+ return ret;
+}
+
+/**
+ * efi_file_write() - write to file
+ *
+ * This function implements the Write() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @buffer_size: number of bytes to write
+ * @buffer: buffer with the bytes to write
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *this,
+ efi_uintn_t *buffer_size,
+ void *buffer)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p, %p", this, buffer_size, buffer);
+
+ ret = efi_file_write_int(this, buffer_size, buffer);
+
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_file_write_ex() - write to file
+ *
+ * This function implements the WriteEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @token: transaction token
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
+{
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_write_int(this, &token->buffer_size, token->buffer);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
return EFI_EXIT(ret);
}
@@ -761,36 +928,84 @@ out:
return EFI_EXIT(ret);
}
-static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+/**
+ * efi_file_flush_int() - flush file
+ *
+ * This is the internal implementation of the Flush() and FlushEx() services of
+ * the EFI_FILE_PROTOCOL.
+ *
+ * @this: file protocol instance
+ * Return: status code
+ */
+static efi_status_t efi_file_flush_int(struct efi_file_handle *this)
{
- EFI_ENTRY("%p", file);
- return EFI_EXIT(EFI_SUCCESS);
-}
+ struct file_handle *fh = to_fh(this);
-static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file,
- struct efi_file_handle **new_handle,
- u16 *file_name, u64 open_mode, u64 attributes,
- struct efi_file_io_token *token)
-{
- return EFI_UNSUPPORTED;
-}
+ if (!this)
+ return EFI_INVALID_PARAMETER;
-static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
-{
- return EFI_UNSUPPORTED;
+ if (!(fh->open_mode & EFI_FILE_MODE_WRITE))
+ return EFI_ACCESS_DENIED;
+
+ /* TODO: flush for file position after end of file */
+ return EFI_SUCCESS;
}
-static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
+/**
+ * efi_file_flush() - flush file
+ *
+ * This function implements the Flush() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *this)
{
- return EFI_UNSUPPORTED;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p", this);
+
+ ret = efi_file_flush_int(this);
+
+ return EFI_EXIT(ret);
}
-static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file,
- struct efi_file_io_token *token)
+/**
+ * efi_file_flush_ex() - flush file
+ *
+ * This function implements the FlushEx() service of the EFI_FILE_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: file protocol instance
+ * @token: transaction token
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *this,
+ struct efi_file_io_token *token)
{
- return EFI_UNSUPPORTED;
+ efi_status_t ret;
+
+ EFI_ENTRY("%p, %p", this, token);
+
+ if (!token) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = efi_file_flush_int(this);
+
+ if (ret == EFI_SUCCESS && token->event) {
+ token->status = EFI_SUCCESS;
+ efi_signal_event(token->event);
+ }
+
+out:
+ return EFI_EXIT(ret);
}
static const struct efi_file_handle efi_file_handle_protocol = {
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 94f76ef..d4dd9e94 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -675,6 +675,46 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
}
#endif /* CONFIG_EFI_SECURE_BOOT */
+
+/**
+ * efi_check_pe() - check if a memory buffer contains a PE-COFF image
+ *
+ * @buffer: buffer to check
+ * @size: size of buffer
+ * @nt_header: on return pointer to NT header of PE-COFF image
+ * Return: EFI_SUCCESS if the buffer contains a PE-COFF image
+ */
+efi_status_t efi_check_pe(void *buffer, size_t size, void **nt_header)
+{
+ IMAGE_DOS_HEADER *dos = buffer;
+ IMAGE_NT_HEADERS32 *nt;
+
+ if (size < sizeof(*dos))
+ return EFI_INVALID_PARAMETER;
+
+ /* Check for DOS magix */
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ /*
+ * Check if the image section header fits into the file. Knowing that at
+ * least one section header follows we only need to check for the length
+ * of the 64bit header which is longer than the 32bit header.
+ */
+ if (size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
+ return EFI_INVALID_PARAMETER;
+ nt = (IMAGE_NT_HEADERS32 *)((u8 *)buffer + dos->e_lfanew);
+
+ /* Check for PE-COFF magic */
+ if (nt->Signature != IMAGE_NT_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ if (nt_header)
+ *nt_header = nt;
+
+ return EFI_SUCCESS;
+}
+
/**
* efi_load_pe() - relocate EFI binary
*
@@ -705,36 +745,10 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
int supported = 0;
efi_status_t ret;
- /* Sanity check for a file header */
- if (efi_size < sizeof(*dos)) {
- log_err("Truncated DOS Header\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- dos = efi;
- if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
- log_err("Invalid DOS Signature\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- /*
- * Check if the image section header fits into the file. Knowing that at
- * least one section header follows we only need to check for the length
- * of the 64bit header which is longer than the 32bit header.
- */
- if (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS64)) {
- log_err("Invalid offset for Extended Header\n");
- ret = EFI_LOAD_ERROR;
- goto err;
- }
-
- nt = (void *) ((char *)efi + dos->e_lfanew);
- if (nt->Signature != IMAGE_NT_SIGNATURE) {
- log_err("Invalid NT Signature\n");
- ret = EFI_LOAD_ERROR;
- goto err;
+ ret = efi_check_pe(efi, efi_size, (void **)&nt);
+ if (ret != EFI_SUCCESS) {
+ log_err("Not a PE-COFF file\n");
+ return EFI_LOAD_ERROR;
}
for (i = 0; machines[i]; i++)
@@ -746,8 +760,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
if (!supported) {
log_err("Machine type 0x%04x is not supported\n",
nt->FileHeader.Machine);
- ret = EFI_LOAD_ERROR;
- goto err;
+ return EFI_LOAD_ERROR;
}
num_sections = nt->FileHeader.NumberOfSections;
@@ -757,8 +770,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle,
if (efi_size < ((void *)sections + sizeof(sections[0]) * num_sections
- efi)) {
log_err("Invalid number of sections: %d\n", num_sections);
- ret = EFI_LOAD_ERROR;
- goto err;
+ return EFI_LOAD_ERROR;
}
/* Authenticate an image */
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 11e7553..a3106ab 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -541,8 +541,6 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY,
false);
- /* Merging of adjacent free regions is missing */
-
if (ret != EFI_SUCCESS)
return EFI_NOT_FOUND;
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index b17db31..b411a12 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <malloc.h>
+#include <efi_dt_fixup.h>
#include <efi_loader.h>
const efi_guid_t efi_u_boot_guid = U_BOOT_GUID;
@@ -60,6 +61,11 @@ efi_status_t efi_root_node_register(void)
/* Device path utilities protocol */
&efi_guid_device_path_utilities_protocol,
(void *)&efi_device_path_utilities,
+#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+ /* Device-tree fix-up protocol */
+ &efi_guid_dt_fixup_protocol,
+ (void *)&efi_dt_fixup_prot,
+#endif
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL2)
#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL)
/* Deprecated Unicode collation protocol */
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index 9ae2ee3..5c8b7a9 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -1,43 +1,41 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * EFI hello world
+ * Hello world EFI application
*
- * Copyright (c) 2016 Google, Inc
- * Written by Simon Glass <sjg@chromium.org>
+ * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
*
- * This program demonstrates calling a boottime service.
- * It writes a greeting and the load options to the console.
+ * This test program is used to test the invocation of an EFI application.
+ * It writes
+ *
+ * * a greeting
+ * * the firmware's UEFI version
+ * * the installed configuration tables
+ * * the boot device's device path and the file path
+ *
+ * to the console.
*/
-#include <common.h>
#include <efi_api.h>
static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+static const efi_guid_t device_path_to_text_protocol_guid =
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+static const efi_guid_t device_path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
static const efi_guid_t fdt_guid = EFI_FDT_GUID;
static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
+static struct efi_system_table *systable;
+static struct efi_boot_services *boottime;
+static struct efi_simple_text_output_protocol *con_out;
+
/**
- * efi_main() - entry point of the EFI application.
- *
- * @handle: handle of the loaded image
- * @systable: system table
- * @return: status code
+ * print_uefi_revision() - print UEFI revision number
*/
-efi_status_t EFIAPI efi_main(efi_handle_t handle,
- struct efi_system_table *systable)
+static void print_uefi_revision(void)
{
- struct efi_simple_text_output_protocol *con_out = systable->con_out;
- struct efi_boot_services *boottime = systable->boottime;
- struct efi_loaded_image *loaded_image;
- efi_status_t ret;
- efi_uintn_t i;
u16 rev[] = L"0.0.0";
- /* UEFI requires CR LF */
- con_out->output_string(con_out, L"Hello, world!\r\n");
-
- /* Print the revision number */
rev[0] = (systable->hdr.revision >> 16) + '0';
rev[4] = systable->hdr.revision & 0xffff;
for (; rev[4] >= 10;) {
@@ -53,15 +51,15 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
con_out->output_string(con_out, L"Running on UEFI ");
con_out->output_string(con_out, rev);
con_out->output_string(con_out, L"\r\n");
+}
+
+/**
+ * print_config_tables() - print configuration tables
+ */
+static void print_config_tables(void)
+{
+ efi_uintn_t i;
- /* Get the loaded image protocol */
- ret = boottime->handle_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image);
- if (ret != EFI_SUCCESS) {
- con_out->output_string
- (con_out, L"Cannot open loaded image protocol\r\n");
- goto out;
- }
/* Find configuration tables */
for (i = 0; i < systable->nr_tables; ++i) {
if (!memcmp(&systable->tables[i].guid, &fdt_guid,
@@ -77,6 +75,16 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
con_out->output_string
(con_out, L"Have SMBIOS table\r\n");
}
+}
+
+/**
+ * print_load_options() - print load options
+ *
+ * @systable: system table
+ * @con_out: simple text output protocol
+ */
+void print_load_options(struct efi_loaded_image *loaded_image)
+{
/* Output the load options */
con_out->output_string(con_out, L"Load options: ");
if (loaded_image->load_options_size && loaded_image->load_options)
@@ -85,6 +93,105 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
else
con_out->output_string(con_out, L"<none>");
con_out->output_string(con_out, L"\r\n");
+}
+
+/**
+ * print_device_path() - print device path
+ *
+ * @device_path: device path to print
+ * @dp2txt: device path to text protocol
+ */
+efi_status_t print_device_path(struct efi_device_path *device_path,
+ struct efi_device_path_to_text_protocol *dp2txt)
+{
+ u16 *string;
+ efi_status_t ret;
+
+ if (!device_path) {
+ con_out->output_string(con_out, L"<none>\r\n");
+ return EFI_SUCCESS;
+ }
+
+ string = dp2txt->convert_device_path_to_text(device_path, true, false);
+ if (!string) {
+ con_out->output_string
+ (con_out, L"Cannot convert device path to text\r\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ con_out->output_string(con_out, string);
+ con_out->output_string(con_out, L"\r\n");
+ ret = boottime->free_pool(string);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string(con_out, L"Cannot free pool memory\r\n");
+ return ret;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systab: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+ struct efi_system_table *systab)
+{
+ struct efi_loaded_image *loaded_image;
+ struct efi_device_path_to_text_protocol *device_path_to_text;
+ struct efi_device_path *device_path;
+ efi_status_t ret;
+
+ systable = systab;
+ boottime = systable->boottime;
+ con_out = systable->con_out;
+
+ /* UEFI requires CR LF */
+ con_out->output_string(con_out, L"Hello, world!\r\n");
+
+ print_uefi_revision();
+ print_config_tables();
+
+ /* Get the loaded image protocol */
+ ret = boottime->handle_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Cannot open loaded image protocol\r\n");
+ goto out;
+ }
+ print_load_options(loaded_image);
+
+ /* Get the device path to text protocol */
+ ret = boottime->locate_protocol(&device_path_to_text_protocol_guid,
+ NULL, (void **)&device_path_to_text);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Cannot open device path to text protocol\r\n");
+ goto out;
+ }
+ if (!loaded_image->device_handle) {
+ con_out->output_string
+ (con_out, L"Missing device handle\r\n");
+ goto out;
+ }
+ ret = boottime->handle_protocol(loaded_image->device_handle,
+ &device_path_guid,
+ (void **)&device_path);
+ if (ret != EFI_SUCCESS) {
+ con_out->output_string
+ (con_out, L"Missing devide path for device handle\r\n");
+ goto out;
+ }
+ con_out->output_string(con_out, L"Boot device: ");
+ ret = print_device_path(device_path, device_path_to_text);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ con_out->output_string(con_out, L"File path: ");
+ ret = print_device_path(loaded_image->file_path, device_path_to_text);
+ if (ret != EFI_SUCCESS)
+ goto out;
out:
boottime->exit(handle, ret, 0, NULL);
diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_selftest/dtbdump.c
index d90e3eb..efef759 100644
--- a/lib/efi_selftest/dtbdump.c
+++ b/lib/efi_selftest/dtbdump.c
@@ -8,10 +8,12 @@
#include <common.h>
#include <efi_api.h>
+#include <efi_dt_fixup.h>
#define BUFFER_SIZE 64
#define ESC 0x17
-#define DEFAULT_FILENAME L"dtb.dtb"
+
+#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
static struct efi_simple_text_output_protocol *cerr;
static struct efi_simple_text_output_protocol *cout;
@@ -21,6 +23,22 @@ static const efi_guid_t fdt_guid = EFI_FDT_GUID;
static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
static const efi_guid_t guid_simple_file_system_protocol =
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static efi_handle_t handle;
+static struct efi_system_table *systable;
+static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
+static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+
+/**
+ * error() - print error string
+ *
+ * @string: error text
+ */
+static void error(u16 *string)
+{
+ cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
+ cout->output_string(cout, string);
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+}
/**
* input() - read string from console
@@ -39,6 +57,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
/* Drain the console input */
ret = cin->reset(cin, true);
+ *buffer = 0;
for (;;) {
ret = bs->wait_for_event(1, &cin->wait_for_key, &index);
if (ret != EFI_SUCCESS)
@@ -62,6 +81,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
break;
case 0x0a: /* Linefeed */
case 0x0d: /* Carriage return */
+ cout->output_string(cout, L"\n");
return EFI_SUCCESS;
default:
break;
@@ -73,6 +93,7 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size)
pos < buffer_size - 1) {
*outbuf = key.unicode_char;
buffer[pos++] = key.unicode_char;
+ buffer[pos] = 0;
cout->output_string(cout, outbuf);
}
}
@@ -117,60 +138,228 @@ void *get_dtb(struct efi_system_table *systable)
}
/**
- * efi_main() - entry point of the EFI application.
+ * skip_whitespace() - skip over leading whitespace
*
- * @handle: handle of the loaded image
- * @systable: system table
- * @return: status code
+ * @pos: UTF-16 string
+ * Return: pointer to first non-whitespace
*/
-efi_status_t EFIAPI efi_main(efi_handle_t handle,
- struct efi_system_table *systable)
+u16 *skip_whitespace(u16 *pos)
{
- efi_uintn_t ret;
- u16 filename[BUFFER_SIZE] = {0};
- efi_uintn_t dtb_size;
+ for (; *pos && *pos <= 0x20; ++pos)
+ ;
+ return pos;
+}
+
+/**
+ * starts_with() - check if @string starts with @keyword
+ *
+ * @string: string to search for keyword
+ * @keyword: keyword to be searched
+ * Return: true fi @string starts with the keyword
+ */
+bool starts_with(u16 *string, u16 *keyword)
+{
+ for (; *keyword; ++string, ++keyword) {
+ if (*string != *keyword)
+ return false;
+ }
+ return true;
+}
+
+/**
+ * do_help() - print help
+ */
+void do_help(void)
+{
+ error(L"load <dtb> - load device-tree from file\n");
+ error(L"save <dtb> - save device-tree to file\n");
+ error(L"exit - exit the shell\n");
+}
+
+/**
+ * do_load() - load and install device-tree
+ *
+ * @filename: file name
+ * Return: status code
+ */
+efi_status_t do_load(u16 *filename)
+{
+ struct efi_dt_fixup_protocol *dt_fixup_prot;
struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
- struct efi_file_handle *root, *file;
+ struct efi_file_handle *root = NULL, *file = NULL;
+ u64 addr = 0;
+ struct efi_file_info *info;
struct fdt_header *dtb;
+ efi_uintn_t buffer_size;
+ efi_uintn_t pages;
+ efi_status_t ret, ret2;
- cerr = systable->std_err;
- cout = systable->con_out;
- cin = systable->con_in;
- bs = systable->boottime;
+ ret = bs->locate_protocol(&efi_dt_fixup_protocol_guid, NULL,
+ (void **)&dt_fixup_prot);
+ if (ret != EFI_SUCCESS) {
+ error(L"Device-tree fix-up protocol not found\n");
+ return ret;
+ }
- cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
- cout->clear_screen(cout);
- cout->set_attribute(cout, EFI_YELLOW | EFI_BACKGROUND_BLACK);
- cout->output_string(cout, L"DTB Dump\n\n");
- cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+ filename = skip_whitespace(filename);
+
+ ret = bs->open_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Loaded image protocol not found\n");
+ return ret;
+ }
+ /* Open the simple file system protocol */
+ ret = bs->open_protocol(loaded_image->device_handle,
+ &guid_simple_file_system_protocol,
+ (void **)&file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Failed to open simple file system protocol\n");
+ goto out;
+ }
+
+ /* Open volume */
+ ret = file_system->open_volume(file_system, &root);
+ if (ret != EFI_SUCCESS) {
+ error(L"Failed to open volume\n");
+ goto out;
+ }
+
+ /* Open file */
+ ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0);
+ if (ret != EFI_SUCCESS) {
+ error(L"File not found\n");
+ goto out;
+ }
+ /* Get file size */
+ buffer_size = 0;
+ ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, NULL);
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ error(L"Can't get file info size\n");
+ goto out;
+ }
+ ret = bs->allocate_pool(EFI_LOADER_DATA, buffer_size, (void **)&info);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ ret = file->getinfo(file, &efi_file_info_guid, &buffer_size, info);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't get file info\n");
+ goto out;
+ }
+ buffer_size = info->file_size;
+ pages = efi_size_in_pages(buffer_size);
+ ret = bs->free_pool(info);
+ if (ret != EFI_SUCCESS)
+ error(L"Can't free memory pool\n");
+ /* Read file */
+ ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY,
+ pages, &addr);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ dtb = (struct fdt_header *)(uintptr_t)addr;
+ ret = file->read(file, &buffer_size, dtb);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't read file\n");
+ goto out;
+ }
+ /* Fixup file, expecting EFI_BUFFER_TOO_SMALL */
+ ret = dt_fixup_prot->fixup(dt_fixup_prot, dtb, &buffer_size,
+ EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
+ EFI_DT_INSTALL_TABLE);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ /* Read file into larger buffer */
+ ret = bs->free_pages(addr, pages);
+ if (ret != EFI_SUCCESS)
+ error(L"Can't free memory pages\n");
+ pages = efi_size_in_pages(buffer_size);
+ ret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY,
+ pages, &addr);
+ if (ret != EFI_SUCCESS) {
+ error(L"Out of memory\n");
+ goto out;
+ }
+ dtb = (struct fdt_header *)(uintptr_t)addr;
+ ret = file->setpos(file, 0);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't position file\n");
+ goto out;
+ }
+ ret = file->read(file, &buffer_size, dtb);
+ if (ret != EFI_SUCCESS) {
+ error(L"Can't read file\n");
+ goto out;
+ }
+ buffer_size = pages << EFI_PAGE_SHIFT;
+ ret = dt_fixup_prot->fixup(
+ dt_fixup_prot, dtb, &buffer_size,
+ EFI_DT_APPLY_FIXUPS | EFI_DT_RESERVE_MEMORY |
+ EFI_DT_INSTALL_TABLE);
+ }
+ if (ret == EFI_SUCCESS)
+ cout->output_string(cout, L"device-tree installed\n");
+ else
+ error(L"Device-tree fix-up failed\n");
+out:
+ if (addr) {
+ ret2 = bs->free_pages(addr, pages);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't free memory pages\n");
+ }
+ if (file) {
+ ret2 = file->close(file);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't close file\n");
+ }
+ if (root) {
+ ret2 = root->close(root);
+ if (ret2 != EFI_SUCCESS)
+ error(L"Can't close volume\n");
+ }
+ return ret;
+}
+
+/**
+ * do_save() - save current device-tree
+ *
+ * @filename: file name
+ * Return: status code
+ */
+efi_status_t do_save(u16 *filename)
+{
+ struct efi_loaded_image *loaded_image;
+ struct efi_simple_file_system_protocol *file_system;
+ efi_uintn_t dtb_size;
+ struct efi_file_handle *root, *file;
+ struct fdt_header *dtb;
+ efi_uintn_t ret;
dtb = get_dtb(systable);
if (!dtb) {
- cerr->output_string(cout, L"DTB not found\n");
+ error(L"DTB not found\n");
return EFI_NOT_FOUND;
}
if (f2h(dtb->magic) != FDT_MAGIC) {
- cerr->output_string(cout, L"Wrong device tree magic\n");
+ error(L"Wrong device tree magic\n");
return EFI_NOT_FOUND;
}
dtb_size = f2h(dtb->totalsize);
- cout->output_string(cout, L"Filename (" DEFAULT_FILENAME ")?\n");
- ret = efi_input(filename, sizeof(filename));
- if (ret != EFI_SUCCESS)
- return ret;
- if (!*filename)
- memcpy(filename, DEFAULT_FILENAME, sizeof(DEFAULT_FILENAME));
-
- cout->output_string(cout, L"\n");
+ filename = skip_whitespace(filename);
ret = bs->open_protocol(handle, &loaded_image_guid,
(void **)&loaded_image, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
- cerr->output_string(cout,
- L"Loaded image protocol not found\n");
+ error(L"Loaded image protocol not found\n");
return ret;
}
@@ -180,15 +369,14 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
(void **)&file_system, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
- cerr->output_string(
- cout, L"Failed to open simple file system protocol\n");
+ error(L"Failed to open simple file system protocol\n");
return ret;
}
/* Open volume */
ret = file_system->open_volume(file_system, &root);
if (ret != EFI_SUCCESS) {
- cerr->output_string(cerr, L"Failed to open volume\n");
+ error(L"Failed to open volume\n");
return ret;
}
/* Create file */
@@ -199,10 +387,10 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
/* Write file */
ret = file->write(file, &dtb_size, dtb);
if (ret != EFI_SUCCESS)
- cerr->output_string(cerr, L"Failed to write file\n");
+ error(L"Failed to write file\n");
file->close(file);
} else {
- cerr->output_string(cerr, L"Failed to open file\n");
+ error(L"Failed to open file\n");
}
root->close(root);
@@ -213,3 +401,51 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
return ret;
}
+
+/**
+ * efi_main() - entry point of the EFI application.
+ *
+ * @handle: handle of the loaded image
+ * @systab: system table
+ * @return: status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
+ struct efi_system_table *systab)
+{
+ handle = image_handle;
+ systable = systab;
+ cerr = systable->std_err;
+ cout = systable->con_out;
+ cin = systable->con_in;
+ bs = systable->boottime;
+
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+ cout->clear_screen(cout);
+ cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
+ cout->output_string(cout, L"DTB Dump\n========\n\n");
+ cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+
+ for (;;) {
+ u16 command[BUFFER_SIZE];
+ u16 *pos;
+ efi_uintn_t ret;
+
+ cout->output_string(cout, L"=> ");
+ ret = efi_input(command, sizeof(command));
+ if (ret == EFI_ABORTED)
+ break;
+ pos = skip_whitespace(command);
+ if (starts_with(pos, L"exit"))
+ break;
+ else if (starts_with(pos, L"load "))
+ do_load(pos + 5);
+ else if (starts_with(pos, L"save "))
+ do_save(pos + 5);
+ else
+ do_help();
+ }
+
+ cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+ cout->clear_screen(cout);
+ return EFI_SUCCESS;
+}
diff --git a/net/tftp.c b/net/tftp.c
index 6fdb1a8..2cfa0b1 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -329,6 +329,12 @@ static void tftp_complete(void)
time_start * 1000, "/s");
}
puts("\ndone\n");
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) {
+ if (!tftp_put_active)
+ efi_set_bootdev("Net", "", tftp_filename,
+ map_sysmem(tftp_load_addr, 0),
+ net_boot_file_size);
+ }
net_set_state(NETLOOP_SUCCESS);
}
@@ -841,9 +847,6 @@ void tftp_start(enum proto_t protocol)
printf("Load address: 0x%lx\n", tftp_load_addr);
puts("Loading: *\b");
tftp_state = STATE_SEND_RRQ;
-#ifdef CONFIG_CMD_BOOTEFI
- efi_set_bootdev("Net", "", tftp_filename);
-#endif
}
time_start = get_timer(0);
diff --git a/tools/efivar.py b/tools/efivar.py
index ebfcab2..67729fa 100755
--- a/tools/efivar.py
+++ b/tools/efivar.py
@@ -51,21 +51,21 @@ var_guids = {
}
class EfiStruct:
- # struct efi_var_file
- var_file_fmt = '<QQLL'
- var_file_size = struct.calcsize(var_file_fmt)
- # struct efi_var_entry
- var_entry_fmt = '<LLQ16s'
- var_entry_size = struct.calcsize(var_entry_fmt)
- # struct efi_time
- var_time_fmt = '<H6BLh2B'
- var_time_size = struct.calcsize(var_time_fmt)
- # WIN_CERTIFICATE
- var_win_cert_fmt = '<L2H'
- var_win_cert_size = struct.calcsize(var_win_cert_fmt)
- # WIN_CERTIFICATE_UEFI_GUID
- var_win_cert_uefi_guid_fmt = var_win_cert_fmt+'16s'
- var_win_cert_uefi_guid_size = struct.calcsize(var_win_cert_uefi_guid_fmt)
+ # struct efi_var_file
+ var_file_fmt = '<QQLL'
+ var_file_size = struct.calcsize(var_file_fmt)
+ # struct efi_var_entry
+ var_entry_fmt = '<LLQ16s'
+ var_entry_size = struct.calcsize(var_entry_fmt)
+ # struct efi_time
+ var_time_fmt = '<H6BLh2B'
+ var_time_size = struct.calcsize(var_time_fmt)
+ # WIN_CERTIFICATE
+ var_win_cert_fmt = '<L2H'
+ var_win_cert_size = struct.calcsize(var_win_cert_fmt)
+ # WIN_CERTIFICATE_UEFI_GUID
+ var_win_cert_uefi_guid_fmt = var_win_cert_fmt+'16s'
+ var_win_cert_uefi_guid_size = struct.calcsize(var_win_cert_uefi_guid_fmt)
class EfiVariable:
def __init__(self, size, attrs, time, guid, name, data):
@@ -149,7 +149,7 @@ class EfiVariableStore:
offs = 0
while offs < len(self.ents):
var, loffs = self._next_var(offs)
- if var.name == name and str(var.guid):
+ if var.name == name and str(var.guid) == guid:
if var.attrs != attrs:
print("err: attributes don't match")
exit(1)
@@ -292,7 +292,7 @@ def pkcs7_sign(cert, key, buf):
# UEFI 2.8 Errata B "8.2.2 Using the EFI_VARIABLE_AUTHENTICATION_2 descriptor"
def cmd_sign(args):
- guid, name, attrs, data, size = parse_args(args)
+ guid, name, attrs, data, _ = parse_args(args)
attrs |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
efi = EfiStruct()
@@ -357,7 +357,10 @@ def main():
signp.set_defaults(func=cmd_sign)
args = ap.parse_args()
- args.func(args)
+ if hasattr(args, "func"):
+ args.func(args)
+ else:
+ ap.print_help()
def group(a, *ns):
for n in ns: