summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/Kconfig2
-rw-r--r--lib/efi_loader/Makefile20
-rw-r--r--lib/efi_loader/capsule_esl.dtsi.in11
-rw-r--r--lib/efi_loader/efi_acpi.c42
-rw-r--r--lib/efi_loader/efi_bootbin.c18
-rw-r--r--lib/efi_loader/efi_bootmgr.c4
-rw-r--r--lib/efi_loader/efi_boottime.c7
-rw-r--r--lib/efi_loader/efi_capsule.c37
-rw-r--r--lib/efi_loader/efi_capsule_key.S17
-rw-r--r--lib/efi_loader/efi_dt_fixup.c2
-rw-r--r--lib/efi_loader/efi_firmware.c56
-rw-r--r--lib/efi_loader/efi_gop.c7
-rw-r--r--lib/efi_loader/efi_helper.c31
-rw-r--r--lib/efi_loader/efi_hii.c3
-rw-r--r--lib/efi_loader/efi_hii_config.c4
-rw-r--r--lib/efi_loader/efi_load_initrd.c71
-rw-r--r--lib/efi_loader/efi_root_node.c3
17 files changed, 246 insertions, 89 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 6130af14337..7f02a83e2a2 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -305,7 +305,6 @@ config EFI_CAPSULE_FIRMWARE_FIT
depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT
select UPDATE_FIT
select DFU
- select SET_DFU_ALT_INFO
select EFI_CAPSULE_FIRMWARE
help
Select this option if you want to enable firmware management protocol
@@ -317,7 +316,6 @@ config EFI_CAPSULE_FIRMWARE_RAW
depends on SANDBOX || (!SANDBOX && !EFI_CAPSULE_FIRMWARE_FIT)
select DFU_WRITE_ALT
select DFU
- select SET_DFU_ALT_INFO
select EFI_CAPSULE_FIRMWARE
help
Select this option if you want to enable firmware management protocol
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 2a0b4172bd7..cf050e5385d 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -29,6 +29,7 @@ obj-y += efi_boottime.o
obj-y += efi_helper.o
obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o
obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o
+obj-$(CONFIG_EFI_CAPSULE_AUTHENTICATE) += efi_capsule_key.o
obj-y += efi_console.o
obj-y += efi_device_path.o
obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o
@@ -36,7 +37,7 @@ obj-$(CONFIG_EFI_DEVICE_PATH_UTIL) += efi_device_path_utilities.o
obj-y += efi_dt_fixup.o
obj-y += efi_fdt.o
obj-y += efi_file.o
-obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o
+obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o efi_hii_config.o
obj-y += efi_image_loader.o
obj-y += efi_load_options.o
obj-y += efi_memory.o
@@ -73,6 +74,23 @@ obj-$(CONFIG_EFI_ECPT) += efi_conformance.o
EFI_VAR_SEED_FILE := $(subst $\",,$(CONFIG_EFI_VAR_SEED_FILE))
$(obj)/efi_var_seed.o: $(srctree)/$(EFI_VAR_SEED_FILE)
+ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y)
+capsule_crt_path=($(subst $(quote),,$(CONFIG_EFI_CAPSULE_CRT_FILE)))
+capsule_crt_full=$(srctree)/$(subst $(quote),,$(CONFIG_EFI_CAPSULE_CRT_FILE))
+quiet_cmd_capsule_esl_gen = CAPSULE_ESL_GEN $@
+cmd_capsule_esl_gen = cert-to-efi-sig-list $(capsule_crt_full) $@
+$(objtree)/capsule_esl_file: FORCE
+ @if [ ! -e "$(capsule_crt_full)" ]; then \
+ echo "ERROR: path $(capsule_crt_full) is invalid." >&2; \
+ echo "EFI CONFIG_EFI_CAPSULE_CRT_FILE must be specified when CONFIG_EFI_CAPSULE_AUTHENTICATE is enabled." >&2; \
+ exit 1; \
+ fi
+ $(call cmd,capsule_esl_gen)
+
+$(obj)/efi_capsule.o: $(objtree)/capsule_esl_file FORCE
+asflags-y += -DCAPSULE_ESL_PATH=\"$(objtree)/capsule_esl_file\"
+endif
+
# Set the C flags to add and remove for each app
$(foreach f,$(apps-y),\
$(eval CFLAGS_$(f).o := $(CFLAGS_EFI) -Os -ffreestanding)\
diff --git a/lib/efi_loader/capsule_esl.dtsi.in b/lib/efi_loader/capsule_esl.dtsi.in
deleted file mode 100644
index bc7db836faa..00000000000
--- a/lib/efi_loader/capsule_esl.dtsi.in
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Devicetree file with the public key EFI Signature List(ESL)
- * node. This file is used to generate the dtsi file to be
- * included into the DTB.
- */
-/ {
- signature {
- capsule-key = /incbin/("ESL_BIN_FILE");
- };
-};
diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c
index 4422b31ac6a..046986a7518 100644
--- a/lib/efi_loader/efi_acpi.c
+++ b/lib/efi_loader/efi_acpi.c
@@ -7,6 +7,7 @@
#define LOG_CATEGORY LOGC_EFI
+#include <bloblist.h>
#include <efi_loader.h>
#include <log.h>
#include <mapmem.h>
@@ -34,25 +35,38 @@ efi_status_t efi_acpi_register(void)
* add_u_boot_and_runtime(). At some point that function could create a
* more detailed map.
*/
- if (IS_ENABLED(CONFIG_BLOBLIST_TABLES))
- return EFI_SUCCESS;
-
- /* Mark space used for tables */
- start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK);
- end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK);
- ret = efi_add_memory_map(start, end - start, EFI_ACPI_RECLAIM_MEMORY);
- if (ret != EFI_SUCCESS)
- return ret;
- if (gd->arch.table_start_high) {
- start = ALIGN_DOWN(gd->arch.table_start_high, EFI_PAGE_MASK);
- end = ALIGN(gd->arch.table_end_high, EFI_PAGE_MASK);
+ if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
+ int size;
+ void *tab = bloblist_get_blob(BLOBLISTT_ACPI_TABLES, &size);
+
+ if (!tab)
+ return EFI_NOT_FOUND;
+ addr = map_to_sysmem(tab);
+
+ ret = efi_add_memory_map(addr, size,
+ EFI_ACPI_RECLAIM_MEMORY);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ } else {
+ /* Mark space used for tables */
+ start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK);
+ end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK);
ret = efi_add_memory_map(start, end - start,
EFI_ACPI_RECLAIM_MEMORY);
if (ret != EFI_SUCCESS)
return ret;
- }
+ if (gd->arch.table_start_high) {
+ start = ALIGN_DOWN(gd->arch.table_start_high,
+ EFI_PAGE_MASK);
+ end = ALIGN(gd->arch.table_end_high, EFI_PAGE_MASK);
+ ret = efi_add_memory_map(start, end - start,
+ EFI_ACPI_RECLAIM_MEMORY);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
- addr = gd_acpi_start();
+ addr = gd_acpi_start();
+ }
log_debug("EFI using ACPI tables at %lx\n", addr);
/* And expose them to our EFI payload */
diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c
index deafb2ce1c2..94ba7c5589b 100644
--- a/lib/efi_loader/efi_bootbin.c
+++ b/lib/efi_loader/efi_bootbin.c
@@ -204,6 +204,8 @@ out:
* @image: memory address of the UEFI image
* @size: size of the UEFI image
* @fdt: device-tree
+ * @initrd: initrd
+ * @initrd_sz: initrd size
* @dp_dev: EFI device-path
* @dp_img: EFI image-path
*
@@ -213,6 +215,7 @@ out:
* Return: status code
*/
static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
+ void *initrd, size_t initrd_sz,
struct efi_device_path *dp_dev,
struct efi_device_path *dp_img)
{
@@ -230,6 +233,10 @@ static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
if (ret != EFI_SUCCESS)
return ret;
+ ret = efi_install_initrd(initrd, initrd_sz);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
return efi_run_image(image, size, dp_dev, dp_img);
}
@@ -239,13 +246,15 @@ static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
* @image: memory address of the UEFI image
* @size: size of the UEFI image
* @fdt: device-tree
+ * @initrd: initrd
+ * @initrd_sz: initrd size
*
* Execute an EFI binary image loaded at @image.
* @size may be zero if the binary is loaded with U-Boot load command.
*
* Return: status code
*/
-efi_status_t efi_binary_run(void *image, size_t size, void *fdt)
+efi_status_t efi_binary_run(void *image, size_t size, void *fdt, void *initrd, size_t initrd_sz)
{
efi_handle_t mem_handle = NULL;
struct efi_device_path *file_path = NULL;
@@ -269,11 +278,14 @@ efi_status_t efi_binary_run(void *image, size_t size, void *fdt)
file_path, NULL);
if (ret != EFI_SUCCESS)
goto out;
+
+ bootefi_device_path = file_path;
+ bootefi_image_path = NULL;
} else {
log_debug("Loaded from disk\n");
}
- ret = efi_binary_run_dp(image, size, fdt, bootefi_device_path,
+ ret = efi_binary_run_dp(image, size, fdt, initrd, initrd_sz, bootefi_device_path,
bootefi_image_path);
out:
if (mem_handle) {
@@ -355,7 +367,7 @@ efi_status_t efi_bootflow_run(struct bootflow *bflow)
log_debug("Booting with external fdt\n");
fdt = map_sysmem(bflow->fdt_addr, 0);
}
- ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, device, image);
+ ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, NULL, 0, device, image);
return ret;
}
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index f9534ef85ed..c0df5cb9acd 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -685,12 +685,12 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
/* try to register load file2 for initrd's */
if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
- ret = efi_initrd_register();
+ ret = efi_initrd_register(NULL);
if (ret != EFI_SUCCESS)
goto error;
}
- log_info("Booting: %ls\n", lo.label);
+ log_info("Booting: Label: %ls Device path: %pD\n", lo.label, lo.file_path);
/* Ignore the optional data in auto-generated boot options */
if (size >= sizeof(efi_guid_t) &&
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index f220daa048f..dbebb37dc04 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3195,7 +3195,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
struct efi_loaded_image_obj *image_obj =
(struct efi_loaded_image_obj *)image_handle;
efi_status_t ret;
- void *info;
+ struct efi_loaded_image *info;
efi_handle_t parent_image = current_image;
efi_status_t exit_status;
jmp_buf exit_jmp;
@@ -3213,7 +3213,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
return EFI_EXIT(EFI_SECURITY_VIOLATION);
ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
- &info, NULL, NULL,
+ (void **)&info, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
if (ret != EFI_SUCCESS)
return EFI_EXIT(EFI_INVALID_PARAMETER);
@@ -3266,7 +3266,8 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
current_image = image_handle;
image_obj->header.type = EFI_OBJECT_TYPE_STARTED_IMAGE;
- EFI_PRINT("Jumping into 0x%p\n", image_obj->entry);
+ EFI_PRINT("Starting image loaded at 0x%p, entry point 0x%p\n",
+ info->image_base, image_obj->entry);
ret = EFI_CALL(image_obj->entry(image_handle, &systab));
/*
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index f8a4a7c6ef4..1aa52ac7bb6 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -22,6 +22,7 @@
#include <asm/global_data.h>
#include <u-boot/uuid.h>
+#include <asm/sections.h>
#include <crypto/pkcs7.h>
#include <crypto/pkcs7_parser.h>
#include <linux/err.h>
@@ -284,33 +285,12 @@ out:
}
#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
-int efi_get_public_key_data(void **pkey, efi_uintn_t *pkey_len)
+static int efi_get_public_key_data(const void **pkey, efi_uintn_t *pkey_len)
{
- const void *fdt_blob = gd->fdt_blob;
- const void *blob;
- const char *cnode_name = "capsule-key";
- const char *snode_name = "signature";
- int sig_node;
- int len;
-
- sig_node = fdt_subnode_offset(fdt_blob, 0, snode_name);
- if (sig_node < 0) {
- log_err("Unable to get signature node offset\n");
-
- return -FDT_ERR_NOTFOUND;
- }
-
- blob = fdt_getprop(fdt_blob, sig_node, cnode_name, &len);
-
- if (!blob || len < 0) {
- log_err("Unable to get capsule-key value\n");
- *pkey = NULL;
- *pkey_len = 0;
-
- return -FDT_ERR_NOTFOUND;
- }
+ const void *blob = __efi_capsule_sig_begin;
+ const int len = __efi_capsule_sig_end - __efi_capsule_sig_begin;
- *pkey = (void *)blob;
+ *pkey = blob;
*pkey_len = len;
return 0;
@@ -321,7 +301,8 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s
{
u8 *buf;
int ret;
- void *fdt_pkey, *pkey;
+ void *pkey;
+ const void *stored_pkey;
efi_uintn_t pkey_len;
uint64_t monotonic_count;
struct efi_signature_store *truststore;
@@ -373,7 +354,7 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s
goto out;
}
- ret = efi_get_public_key_data(&fdt_pkey, &pkey_len);
+ ret = efi_get_public_key_data(&stored_pkey, &pkey_len);
if (ret < 0)
goto out;
@@ -381,7 +362,7 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s
if (!pkey)
goto out;
- memcpy(pkey, fdt_pkey, pkey_len);
+ memcpy(pkey, stored_pkey, pkey_len);
truststore = efi_build_signature_store(pkey, pkey_len);
if (!truststore)
goto out;
diff --git a/lib/efi_loader/efi_capsule_key.S b/lib/efi_loader/efi_capsule_key.S
new file mode 100644
index 00000000000..80cefbe16ae
--- /dev/null
+++ b/lib/efi_loader/efi_capsule_key.S
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * .esl cert for capsule authentication
+ *
+ * Copyright (c) 2021, Ilias Apalodimas <ilias.apalodimas@linaro.org>
+ */
+
+#include <config.h>
+
+.section .rodata.capsule_key.init,"a"
+.balign 16
+.global __efi_capsule_sig_begin
+__efi_capsule_sig_begin:
+.incbin CAPSULE_ESL_PATH
+__efi_capsule_sig_end:
+.global __efi_capsule_sig_end
+.balign 16
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index 26928cfc454..544e1aa9808 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -168,7 +168,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
/* Check size */
required_size = fdt_off_dt_strings(dtb) +
fdt_size_dt_strings(dtb) +
- 0x3000;
+ CONFIG_SYS_FDT_PAD;
total_size = fdt_totalsize(dtb);
if (required_size < total_size)
required_size = total_size;
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index 5a754c9cd03..d44dc09813e 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -56,11 +56,6 @@ struct fmp_state {
u32 last_attempt_status; /* not used */
};
-__weak void set_dfu_alt_info(char *interface, char *devstr)
-{
- env_set("dfu_alt_info", update_info.dfu_string);
-}
-
/**
* efi_firmware_get_image_type_id - get image_type_id
* @image_index: image index
@@ -649,8 +644,10 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
efi_status_t (*progress)(efi_uintn_t completion),
u16 **abort_reason)
{
+ int ret;
efi_status_t status;
struct fmp_state state = { 0 };
+ char *orig_dfu_env;
EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
image_size, vendor_code, progress, abort_reason);
@@ -663,7 +660,28 @@ efi_status_t EFIAPI efi_firmware_fit_set_image(
if (status != EFI_SUCCESS)
return EFI_EXIT(status);
- if (fit_update(image))
+ orig_dfu_env = env_get("dfu_alt_info");
+ if (orig_dfu_env) {
+ orig_dfu_env = strdup(orig_dfu_env);
+ if (!orig_dfu_env) {
+ log_err("strdup() failed!\n");
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+ }
+ }
+ if (env_set("dfu_alt_info", update_info.dfu_string)) {
+ log_err("Unable to set env variable \"dfu_alt_info\"!\n");
+ free(orig_dfu_env);
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+ }
+
+ ret = fit_update(image);
+
+ if (env_set("dfu_alt_info", orig_dfu_env))
+ log_warning("Unable to restore env variable \"dfu_alt_info\". Further DFU operations may fail!\n");
+
+ free(orig_dfu_env);
+
+ if (ret)
return EFI_EXIT(EFI_DEVICE_ERROR);
efi_firmware_set_fmp_state_var(&state, image_index);
@@ -717,6 +735,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
u8 dfu_alt_num;
efi_status_t status;
struct fmp_state state = { 0 };
+ char *orig_dfu_env;
EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
image_size, vendor_code, progress, abort_reason);
@@ -747,8 +766,29 @@ efi_status_t EFIAPI efi_firmware_raw_set_image(
}
}
- if (dfu_write_by_alt(dfu_alt_num, (void *)image, image_size,
- NULL, NULL))
+ orig_dfu_env = env_get("dfu_alt_info");
+ if (orig_dfu_env) {
+ orig_dfu_env = strdup(orig_dfu_env);
+ if (!orig_dfu_env) {
+ log_err("strdup() failed!\n");
+ return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+ }
+ }
+ if (env_set("dfu_alt_info", update_info.dfu_string)) {
+ log_err("Unable to set env variable \"dfu_alt_info\"!\n");
+ free(orig_dfu_env);
+ return EFI_EXIT(EFI_DEVICE_ERROR);
+ }
+
+ ret = dfu_write_by_alt(dfu_alt_num, (void *)image, image_size,
+ NULL, NULL);
+
+ if (env_set("dfu_alt_info", orig_dfu_env))
+ log_warning("Unable to restore env variable \"dfu_alt_info\". Further DFU operations may fail!\n");
+
+ free(orig_dfu_env);
+
+ if (ret)
return EFI_EXIT(EFI_DEVICE_ERROR);
efi_firmware_set_fmp_state_var(&state, image_index);
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 4593975be5a..3abb47d610e 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -26,6 +26,7 @@ static const efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
* @ops: graphical output protocol interface
* @info: graphical output mode information
* @mode: graphical output mode
+ * @vdev: backing video device
* @bpix: bits per pixel
* @fb: frame buffer
*/
@@ -34,6 +35,7 @@ struct efi_gop_obj {
struct efi_gop ops;
struct efi_gop_mode_info info;
struct efi_gop_mode mode;
+ struct udevice *vdev;
/* Fields we only have access to during init */
u32 bpix;
void *fb;
@@ -122,6 +124,7 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
u32 *fb32 = gopobj->fb;
u16 *fb16 = gopobj->fb;
struct efi_gop_pixel *buffer = __builtin_assume_aligned(bufferp, 4);
+ bool blt_to_video = (operation != EFI_BLT_VIDEO_TO_BLT_BUFFER);
if (delta) {
/* Check for 4 byte alignment */
@@ -245,6 +248,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
dlineoff += dwidth;
}
+ if (blt_to_video)
+ video_damage(gopobj->vdev, dx, dy, width, height);
+
return EFI_SUCCESS;
}
@@ -551,6 +557,7 @@ efi_status_t efi_gop_register(void)
gopobj->info.pixels_per_scanline = col;
gopobj->bpix = bpix;
gopobj->fb = map_sysmem(fb_base, fb_size);
+ gopobj->vdev = vdev;
return EFI_SUCCESS;
}
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
index 8c32059edda..19fb5d03fec 100644
--- a/lib/efi_loader/efi_helper.c
+++ b/lib/efi_loader/efi_helper.c
@@ -485,7 +485,7 @@ static efi_status_t copy_fdt(void **fdtp)
* needs to be expanded later.
*/
fdt = *fdtp;
- fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
+ fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + CONFIG_SYS_FDT_PAD);
fdt_size = fdt_pages << EFI_PAGE_SHIFT;
ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
@@ -623,6 +623,35 @@ efi_status_t efi_install_fdt(void *fdt)
}
/**
+ * efi_install_initrd() - install initrd
+ *
+ * Install the initrd located at @initrd using the EFI_LOAD_FILE2
+ * protocol.
+ *
+ * @initrd: address of initrd or NULL if none is provided
+ * @initrd_sz: size of initrd
+ * Return: status code
+ */
+efi_status_t efi_install_initrd(void *initrd, size_t initd_sz)
+{
+ efi_status_t ret;
+ struct efi_device_path *dp_initrd;
+
+ if (!initrd)
+ return EFI_SUCCESS;
+
+ dp_initrd = efi_dp_from_mem(EFI_LOADER_DATA, (uintptr_t)initrd, initd_sz);
+ if (!dp_initrd)
+ return EFI_OUT_OF_RESOURCES;
+
+ ret = efi_initrd_register(dp_initrd);
+ if (ret != EFI_SUCCESS)
+ efi_free_pool(dp_initrd);
+
+ return ret;
+}
+
+/**
* do_bootefi_exec() - execute EFI binary
*
* The image indicated by @handle is started. When it returns the allocated
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 44235970a7c..330d7c5830b 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -343,6 +343,9 @@ static struct efi_hii_packagelist *new_packagelist(void)
struct efi_hii_packagelist *hii;
hii = malloc(sizeof(*hii));
+ if (!hii)
+ return NULL;
+
list_add_tail(&hii->link, &efi_package_lists);
hii->max_string_id = 0;
INIT_LIST_HEAD(&hii->string_tables);
diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c
index 37d8c6629e2..521481a86d8 100644
--- a/lib/efi_loader/efi_hii_config.c
+++ b/lib/efi_loader/efi_hii_config.c
@@ -4,10 +4,6 @@
*
* Copyright (c) 2017 Leif Lindholm
* Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
- *
- * As this is still a non-working stub and the protocol is neither required
- * by the EFI shell nor by the UEFI SCT this module has been removed from
- * the Makefile.
*/
#define LOG_CATEGORY LOGC_EFI
diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
index fb8cc7bcbe3..b5d58943a80 100644
--- a/lib/efi_loader/efi_load_initrd.c
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -42,6 +42,7 @@ static const struct efi_lo_dp_prefix dp_lf2_handle = {
};
static efi_handle_t efi_initrd_handle;
+static struct efi_device_path *efi_initrd_dp;
/**
* get_initrd_fp() - Get initrd device path from a FilePathList device path
@@ -73,6 +74,41 @@ static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
}
/**
+ * efi_initrd_from_mem() - load initial RAM disk from memory
+ *
+ * This function copies the initrd from the memory mapped device
+ * path pointed to by efi_initrd_dp
+ *
+ * @buffer_size: size of allocated buffer
+ * @buffer: buffer to load the file
+ *
+ * Return: status code
+ */
+static efi_status_t efi_initrd_from_mem(efi_uintn_t *buffer_size, void *buffer)
+{
+ efi_status_t ret = EFI_NOT_FOUND;
+ efi_uintn_t bs;
+ struct efi_device_path_memory *mdp;
+
+ mdp = (struct efi_device_path_memory *)efi_initrd_dp;
+ if (!mdp)
+ return ret;
+
+ bs = mdp->end_address - mdp->start_address;
+
+ if (!buffer || *buffer_size < bs) {
+ ret = EFI_BUFFER_TOO_SMALL;
+ *buffer_size = bs;
+ } else {
+ memcpy(buffer, (void *)(uintptr_t)mdp->start_address, bs);
+ *buffer_size = bs;
+ ret = EFI_SUCCESS;
+ }
+
+ return ret;
+}
+
+/**
* efi_load_file2_initrd() - load initial RAM disk
*
* This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL
@@ -118,6 +154,9 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
goto out;
}
+ if (efi_initrd_dp)
+ return EFI_EXIT(efi_initrd_from_mem(buffer_size, buffer));
+
ret = get_initrd_fp(&initrd_fp);
if (ret != EFI_SUCCESS)
goto out;
@@ -209,6 +248,9 @@ efi_status_t efi_initrd_deregister(void)
NULL);
efi_initrd_handle = NULL;
+ efi_free_pool(efi_initrd_dp);
+ efi_initrd_dp = NULL;
+
return ret;
}
@@ -234,24 +276,31 @@ static void EFIAPI efi_initrd_return_notify(struct efi_event *event,
* This function creates a new handle and installs a Linux specific vendor
* device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
* to identify the handle and then calls the LoadFile service of the
- * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
+ * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk. If dp_initrd is
+ * not provided, the initrd will be taken from the BootCurrent variable
+ *
+ * @dp_initrd: optional device path containing an initrd
*
* Return: status code
*/
-efi_status_t efi_initrd_register(void)
+efi_status_t efi_initrd_register(struct efi_device_path *dp_initrd)
{
efi_status_t ret;
struct efi_event *event;
- /*
- * Allow the user to continue if Boot#### file path is not set for
- * an initrd
- */
- ret = check_initrd();
- if (ret == EFI_INVALID_PARAMETER)
- return EFI_SUCCESS;
- if (ret != EFI_SUCCESS)
- return ret;
+ if (dp_initrd) {
+ efi_initrd_dp = dp_initrd;
+ } else {
+ /*
+ * Allow the user to continue if Boot#### file path is not set for
+ * an initrd
+ */
+ ret = check_initrd();
+ if (ret == EFI_INVALID_PARAMETER)
+ return EFI_SUCCESS;
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle,
/* initramfs */
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index 74225edad29..e5246f65df2 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -80,6 +80,9 @@ efi_status_t efi_root_node_register(void)
/* HII database protocol */
&efi_guid_hii_database_protocol,
&efi_hii_database,
+ /* EFI HII Configuration Routing Protocol */
+ &efi_guid_hii_config_routing_protocol,
+ &efi_hii_config_routing,
#endif
NULL);
efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE;