aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r--drivers/firmware/efi/efi.c15
-rw-r--r--drivers/firmware/efi/libstub/Makefile14
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c19
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c145
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c92
-rw-r--r--drivers/firmware/efi/libstub/efistub.h31
-rw-r--r--drivers/firmware/efi/libstub/fdt.c175
-rw-r--r--drivers/firmware/efi/libstub/file.c3
-rw-r--r--drivers/firmware/efi/libstub/loongarch-stub.c56
-rw-r--r--drivers/firmware/efi/libstub/mem.c93
-rw-r--r--drivers/firmware/efi/libstub/randomalloc.c25
-rw-r--r--drivers/firmware/efi/libstub/relocate.c21
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c33
13 files changed, 358 insertions, 364 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index e4080ad96089..11857af72859 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -21,6 +21,7 @@
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/of.h>
+#include <linux/initrd.h>
#include <linux/io.h>
#include <linux/kexec.h>
#include <linux/platform_device.h>
@@ -55,6 +56,7 @@ EXPORT_SYMBOL(efi);
unsigned long __ro_after_init efi_rng_seed = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;
+static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;
struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
@@ -532,6 +534,7 @@ static const efi_config_table_type_t common_tables[] __initconst = {
{LINUX_EFI_TPM_EVENT_LOG_GUID, &efi.tpm_log, "TPMEventLog" },
{LINUX_EFI_TPM_FINAL_LOG_GUID, &efi.tpm_final_log, "TPMFinalLog" },
{LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" },
+ {LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" },
{EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" },
#ifdef CONFIG_EFI_RCI2_TABLE
{DELLEMC_EFI_RCI2_TABLE_GUID, &rci2_table_phys },
@@ -674,6 +677,18 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
}
}
+ if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) &&
+ initrd != EFI_INVALID_TABLE_ADDR && phys_initrd_size == 0) {
+ struct linux_efi_initrd *tbl;
+
+ tbl = early_memremap(initrd, sizeof(*tbl));
+ if (tbl) {
+ phys_initrd_start = tbl->base;
+ phys_initrd_size = tbl->size;
+ early_memunmap(tbl, sizeof(*tbl));
+ }
+ }
+
return 0;
}
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 4c59f39dbd40..a7cadf7b1471 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
-fpie
-cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
+cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
-include $(srctree)/include/linux/hidden.h \
@@ -59,15 +59,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
skip_spaces.o lib-cmdline.o lib-ctype.o \
alignedmem.o relocate.o vsprintf.o
-# include the stub's generic dependencies from lib/ when building for ARM/arm64
-efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
+# include the stub's libfdt dependencies from lib/ when needed
+libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \
+ fdt_empty_tree.c fdt_sw.c
+
+lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \
+ $(patsubst %.c,lib-%.o,$(libfdt-deps))
$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
-lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o intrinsics.o \
- $(patsubst %.c,lib-%.o,$(efi-deps-y)) \
- systable.o
+lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o
lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += arm64-stub.o
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index 577173ee1f83..cd3bea25c762 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -42,26 +42,17 @@ efi_status_t check_platform_features(void)
*/
static bool check_image_region(u64 base, u64 size)
{
- unsigned long map_size, desc_size, buff_size;
- efi_memory_desc_t *memory_map;
- struct efi_boot_memmap map;
+ struct efi_boot_memmap *map;
efi_status_t status;
bool ret = false;
int map_offset;
- map.map = &memory_map;
- map.map_size = &map_size;
- map.desc_size = &desc_size;
- map.desc_ver = NULL;
- map.key_ptr = NULL;
- map.buff_size = &buff_size;
-
- status = efi_get_memory_map(&map);
+ status = efi_get_memory_map(&map, false);
if (status != EFI_SUCCESS)
return false;
- for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
- efi_memory_desc_t *md = (void *)memory_map + map_offset;
+ for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+ efi_memory_desc_t *md = (void *)map->map + map_offset;
u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
/*
@@ -74,7 +65,7 @@ static bool check_image_region(u64 base, u64 size)
}
}
- efi_bs_call(free_pool, memory_map);
+ efi_bs_call(free_pool, map);
return ret;
}
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 829f732c5f37..aa6e73c0de2d 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -420,7 +420,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
/**
* efi_exit_boot_services() - Exit boot services
* @handle: handle of the exiting image
- * @map: pointer to receive the memory map
* @priv: argument to be passed to @priv_func
* @priv_func: function to process the memory map before exiting boot services
*
@@ -433,26 +432,26 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
*
* Return: status code
*/
-efi_status_t efi_exit_boot_services(void *handle,
- struct efi_boot_memmap *map,
- void *priv,
+efi_status_t efi_exit_boot_services(void *handle, void *priv,
efi_exit_boot_map_processing priv_func)
{
+ struct efi_boot_memmap *map;
efi_status_t status;
- status = efi_get_memory_map(map);
-
+ status = efi_get_memory_map(&map, true);
if (status != EFI_SUCCESS)
- goto fail;
+ return status;
status = priv_func(map, priv);
- if (status != EFI_SUCCESS)
- goto free_map;
+ if (status != EFI_SUCCESS) {
+ efi_bs_call(free_pool, map);
+ return status;
+ }
if (efi_disable_pci_dma)
efi_pci_disable_bridge_busmaster();
- status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+ status = efi_bs_call(exit_boot_services, handle, map->map_key);
if (status == EFI_INVALID_PARAMETER) {
/*
@@ -468,35 +467,26 @@ efi_status_t efi_exit_boot_services(void *handle,
* buffer should account for any changes in the map so the call
* to get_memory_map() is expected to succeed here.
*/
- *map->map_size = *map->buff_size;
+ map->map_size = map->buff_size;
status = efi_bs_call(get_memory_map,
- map->map_size,
- *map->map,
- map->key_ptr,
- map->desc_size,
- map->desc_ver);
+ &map->map_size,
+ &map->map,
+ &map->map_key,
+ &map->desc_size,
+ &map->desc_ver);
/* exit_boot_services() was called, thus cannot free */
if (status != EFI_SUCCESS)
- goto fail;
+ return status;
status = priv_func(map, priv);
/* exit_boot_services() was called, thus cannot free */
if (status != EFI_SUCCESS)
- goto fail;
+ return status;
- status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
+ status = efi_bs_call(exit_boot_services, handle, map->map_key);
}
- /* exit_boot_services() was called, thus cannot free */
- if (status != EFI_SUCCESS)
- goto fail;
-
- return EFI_SUCCESS;
-
-free_map:
- efi_bs_call(free_pool, *map->map);
-fail:
return status;
}
@@ -561,20 +551,16 @@ static const struct {
* * %EFI_SUCCESS if the initrd was loaded successfully, in which
* case @load_addr and @load_size are assigned accordingly
* * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path
- * * %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
* * %EFI_OUT_OF_RESOURCES if memory allocation failed
* * %EFI_LOAD_ERROR in all other cases
*/
static
-efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
- unsigned long *load_size,
+efi_status_t efi_load_initrd_dev_path(struct linux_efi_initrd *initrd,
unsigned long max)
{
efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
efi_device_path_protocol_t *dp;
efi_load_file2_protocol_t *lf2;
- unsigned long initrd_addr;
- unsigned long initrd_size;
efi_handle_t handle;
efi_status_t status;
@@ -588,42 +574,37 @@ efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
if (status != EFI_SUCCESS)
return status;
- status = efi_call_proto(lf2, load_file, dp, false, &initrd_size, NULL);
+ initrd->size = 0;
+ status = efi_call_proto(lf2, load_file, dp, false, &initrd->size, NULL);
if (status != EFI_BUFFER_TOO_SMALL)
return EFI_LOAD_ERROR;
- status = efi_allocate_pages(initrd_size, &initrd_addr, max);
+ status = efi_allocate_pages(initrd->size, &initrd->base, max);
if (status != EFI_SUCCESS)
return status;
- status = efi_call_proto(lf2, load_file, dp, false, &initrd_size,
- (void *)initrd_addr);
+ status = efi_call_proto(lf2, load_file, dp, false, &initrd->size,
+ (void *)initrd->base);
if (status != EFI_SUCCESS) {
- efi_free(initrd_size, initrd_addr);
+ efi_free(initrd->size, initrd->base);
return EFI_LOAD_ERROR;
}
-
- *load_addr = initrd_addr;
- *load_size = initrd_size;
return EFI_SUCCESS;
}
static
efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
- unsigned long *load_addr,
- unsigned long *load_size,
+ struct linux_efi_initrd *initrd,
unsigned long soft_limit,
unsigned long hard_limit)
{
if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) ||
- (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) {
- *load_addr = *load_size = 0;
- return EFI_SUCCESS;
- }
+ (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL)))
+ return EFI_UNSUPPORTED;
return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
soft_limit, hard_limit,
- load_addr, load_size);
+ &initrd->base, &initrd->size);
}
static const struct {
@@ -670,42 +651,60 @@ static void efi_measure_initrd(unsigned long load_addr, unsigned long load_size)
/**
* efi_load_initrd() - Load initial RAM disk
* @image: EFI loaded image protocol
- * @load_addr: pointer to loaded initrd
- * @load_size: size of loaded initrd
* @soft_limit: preferred address for loading the initrd
* @hard_limit: upper limit address for loading the initrd
*
* Return: status code
*/
efi_status_t efi_load_initrd(efi_loaded_image_t *image,
- unsigned long *load_addr,
- unsigned long *load_size,
unsigned long soft_limit,
- unsigned long hard_limit)
+ unsigned long hard_limit,
+ const struct linux_efi_initrd **out)
{
- efi_status_t status;
+ efi_guid_t tbl_guid = LINUX_EFI_INITRD_MEDIA_GUID;
+ efi_status_t status = EFI_SUCCESS;
+ struct linux_efi_initrd initrd, *tbl;
- if (efi_noinitrd) {
- *load_addr = *load_size = 0;
- status = EFI_SUCCESS;
- } else {
- status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit);
- if (status == EFI_SUCCESS) {
- efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
- if (*load_size > 0)
- efi_measure_initrd(*load_addr, *load_size);
- } else if (status == EFI_NOT_FOUND) {
- status = efi_load_initrd_cmdline(image, load_addr, load_size,
- soft_limit, hard_limit);
- if (status == EFI_SUCCESS && *load_size > 0)
- efi_info("Loaded initrd from command line option\n");
- }
- if (status != EFI_SUCCESS) {
- efi_err("Failed to load initrd: 0x%lx\n", status);
- *load_addr = *load_size = 0;
- }
+ if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD) || efi_noinitrd)
+ return EFI_SUCCESS;
+
+ status = efi_load_initrd_dev_path(&initrd, hard_limit);
+ if (status == EFI_SUCCESS) {
+ efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
+ if (initrd.size > 0)
+ efi_measure_initrd(initrd.base, initrd.size);
+ } else if (status == EFI_NOT_FOUND) {
+ status = efi_load_initrd_cmdline(image, &initrd, soft_limit,
+ hard_limit);
+ /* command line loader disabled or no initrd= passed? */
+ if (status == EFI_UNSUPPORTED || status == EFI_NOT_READY)
+ return EFI_SUCCESS;
+ if (status == EFI_SUCCESS)
+ efi_info("Loaded initrd from command line option\n");
}
+ if (status != EFI_SUCCESS)
+ goto failed;
+
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),
+ (void **)&tbl);
+ if (status != EFI_SUCCESS)
+ goto free_initrd;
+
+ *tbl = initrd;
+ status = efi_bs_call(install_configuration_table, &tbl_guid, tbl);
+ if (status != EFI_SUCCESS)
+ goto free_tbl;
+
+ if (out)
+ *out = tbl;
+ return EFI_SUCCESS;
+free_tbl:
+ efi_bs_call(free_pool, tbl);
+free_initrd:
+ efi_free(initrd.size, initrd.base);
+failed:
+ efi_err("Failed to load initrd: 0x%lx\n", status);
return status;
}
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 57ea04378087..269df915675e 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -10,7 +10,6 @@
*/
#include <linux/efi.h>
-#include <linux/libfdt.h>
#include <asm/efi.h>
#include "efistub.h"
@@ -130,16 +129,11 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
unsigned long image_addr;
unsigned long image_size = 0;
/* addr/point and size pairs for memory management*/
- unsigned long initrd_addr = 0;
- unsigned long initrd_size = 0;
- unsigned long fdt_addr = 0; /* Original DTB */
- unsigned long fdt_size = 0;
char *cmdline_ptr = NULL;
int cmdline_size = 0;
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
unsigned long reserve_addr = 0;
unsigned long reserve_size = 0;
- enum efi_secureboot_mode secure_boot;
struct screen_info *si;
efi_properties_table_t *prop_tbl;
@@ -215,40 +209,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation();
- secure_boot = efi_get_secureboot();
-
- /*
- * Unauthenticated device tree data is a security hazard, so ignore
- * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure
- * boot is enabled if we can't determine its state.
- */
- if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
- secure_boot != efi_secureboot_mode_disabled) {
- if (strstr(cmdline_ptr, "dtb="))
- efi_err("Ignoring DTB from command line.\n");
- } else {
- status = efi_load_dtb(image, &fdt_addr, &fdt_size);
-
- if (status != EFI_SUCCESS) {
- efi_err("Failed to load device tree!\n");
- goto fail_free_image;
- }
- }
-
- if (fdt_addr) {
- efi_info("Using DTB from command line\n");
- } else {
- /* Look for a device tree configuration table entry. */
- fdt_addr = (uintptr_t)get_fdt(&fdt_size);
- if (fdt_addr)
- efi_info("Using DTB from configuration table\n");
- }
-
- if (!fdt_addr)
- efi_info("Generating empty DTB\n");
-
- efi_load_initrd(image, &initrd_addr, &initrd_size, ULONG_MAX,
- efi_get_max_initrd_addr(image_addr));
+ efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr),
+ NULL);
efi_random_get_seed();
@@ -290,25 +252,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
install_memreserve_table();
- status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr,
- initrd_addr, initrd_size,
- cmdline_ptr, fdt_addr, fdt_size);
- if (status != EFI_SUCCESS)
- goto fail_free_initrd;
-
- if (IS_ENABLED(CONFIG_ARM))
- efi_handle_post_ebs_state();
-
- efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
- /* not reached */
-
-fail_free_initrd:
- efi_err("Failed to update FDT and exit boot services\n");
+ status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
- efi_free(initrd_size, initrd_addr);
- efi_free(fdt_size, fdt_addr);
-
-fail_free_image:
efi_free(image_size, image_addr);
efi_free(reserve_size, reserve_addr);
fail_free_screeninfo:
@@ -320,6 +265,35 @@ fail:
}
/*
+ * efi_allocate_virtmap() - create a pool allocation for the virtmap
+ *
+ * Create an allocation that is of sufficient size to hold all the memory
+ * descriptors that will be passed to SetVirtualAddressMap() to inform the
+ * firmware about the virtual mapping that will be used under the OS to call
+ * into the firmware.
+ */
+efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap,
+ unsigned long *desc_size, u32 *desc_ver)
+{
+ unsigned long size, mmap_key;
+ efi_status_t status;
+
+ /*
+ * Use the size of the current memory map as an upper bound for the
+ * size of the buffer we need to pass to SetVirtualAddressMap() to
+ * cover all EFI_MEMORY_RUNTIME regions.
+ */
+ size = 0;
+ status = efi_bs_call(get_memory_map, &size, NULL, &mmap_key, desc_size,
+ desc_ver);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return EFI_LOAD_ERROR;
+
+ return efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
+ (void **)virtmap);
+}
+
+/*
* efi_get_virtmap() - create a virtual mapping for the EFI memory map
*
* This function populates the virt_addr fields of all memory region descriptors
@@ -334,6 +308,8 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
efi_memory_desc_t *in, *out = runtime_map;
int l;
+ *count = 0;
+
for (l = 0; l < map_size; l += desc_size) {
u64 paddr, size;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 02fb5f7c8eff..9ed5889594ed 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -160,15 +160,6 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
*/
#define EFI_MMAP_NR_SLACK_SLOTS 8
-struct efi_boot_memmap {
- efi_memory_desc_t **map;
- unsigned long *map_size;
- unsigned long *desc_size;
- u32 *desc_ver;
- unsigned long *key_ptr;
- unsigned long *buff_size;
-};
-
typedef struct efi_generic_dev_path efi_device_path_protocol_t;
union efi_device_path_to_text_protocol {
@@ -871,20 +862,16 @@ typedef efi_status_t (*efi_exit_boot_map_processing)(
struct efi_boot_memmap *map,
void *priv);
-efi_status_t efi_exit_boot_services(void *handle,
- struct efi_boot_memmap *map,
- void *priv,
+efi_status_t efi_exit_boot_services(void *handle, void *priv,
efi_exit_boot_map_processing priv_func);
-efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
- unsigned long *new_fdt_addr,
- u64 initrd_addr, u64 initrd_size,
- char *cmdline_ptr,
- unsigned long fdt_addr,
- unsigned long fdt_size);
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+ unsigned long kernel_addr, char *cmdline_ptr);
void *get_fdt(unsigned long *fdt_size);
+efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap,
+ unsigned long *desc_size, u32 *desc_ver);
void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
unsigned long desc_size, efi_memory_desc_t *runtime_map,
int *count);
@@ -910,7 +897,8 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_si
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
-efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
+efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
+ bool install_cfg_tbl);
efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
unsigned long max);
@@ -953,10 +941,9 @@ static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image,
}
efi_status_t efi_load_initrd(efi_loaded_image_t *image,
- unsigned long *load_addr,
- unsigned long *load_size,
unsigned long soft_limit,
- unsigned long hard_limit);
+ unsigned long hard_limit,
+ const struct linux_efi_initrd **out);
/*
* This function handles the architcture specific differences between arm and
* arm64 regarding where the kernel image must be loaded and any memory that
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index fe567be0f118..4f4d98e51fbf 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -28,8 +28,7 @@ static void fdt_update_cell_size(void *fdt)
}
static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
- void *fdt, int new_fdt_size, char *cmdline_ptr,
- u64 initrd_addr, u64 initrd_size)
+ void *fdt, int new_fdt_size, char *cmdline_ptr)
{
int node, num_rsv;
int status;
@@ -93,21 +92,6 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
goto fdt_set_fail;
}
- /* Set initrd address/end in device tree, if present */
- if (initrd_size != 0) {
- u64 initrd_image_end;
- u64 initrd_image_start = cpu_to_fdt64(initrd_addr);
-
- status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start);
- if (status)
- goto fdt_set_fail;
-
- initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
- status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end);
- if (status)
- goto fdt_set_fail;
- }
-
/* Add FDT entries for EFI runtime services in chosen node. */
node = fdt_subnode_offset(fdt, 0, "chosen");
fdt_val64 = cpu_to_fdt64((u64)(unsigned long)efi_system_table);
@@ -170,25 +154,25 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
if (node < 0)
return EFI_LOAD_ERROR;
- fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
+ fdt_val64 = cpu_to_fdt64((unsigned long)map->map);
err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
if (err)
return EFI_LOAD_ERROR;
- fdt_val32 = cpu_to_fdt32(*map->map_size);
+ fdt_val32 = cpu_to_fdt32(map->map_size);
err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
if (err)
return EFI_LOAD_ERROR;
- fdt_val32 = cpu_to_fdt32(*map->desc_size);
+ fdt_val32 = cpu_to_fdt32(map->desc_size);
err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32);
if (err)
return EFI_LOAD_ERROR;
- fdt_val32 = cpu_to_fdt32(*map->desc_ver);
+ fdt_val32 = cpu_to_fdt32(map->desc_ver);
err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32);
if (err)
@@ -198,22 +182,25 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
}
struct exit_boot_struct {
+ struct efi_boot_memmap *boot_memmap;
efi_memory_desc_t *runtime_map;
- int *runtime_entry_count;
+ int runtime_entry_count;
void *new_fdt_addr;
};
-static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
- void *priv)
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
{
struct exit_boot_struct *p = priv;
+
+ p->boot_memmap = map;
+
/*
* Update the memory map with virtual addresses. The function will also
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
* entries so that we can pass it straight to SetVirtualAddressMap()
*/
- efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
- p->runtime_map, p->runtime_entry_count);
+ efi_get_virtmap(map->map, map->map_size, map->desc_size,
+ p->runtime_map, &p->runtime_entry_count);
return update_fdt_memmap(p->new_fdt_addr, map);
}
@@ -223,86 +210,86 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
#endif
/*
- * Allocate memory for a new FDT, then add EFI, commandline, and
- * initrd related fields to the FDT. This routine increases the
- * FDT allocation size until the allocated memory is large
- * enough. EFI allocations are in EFI_PAGE_SIZE granules,
- * which are fixed at 4K bytes, so in most cases the first
- * allocation should succeed.
- * EFI boot services are exited at the end of this function.
- * There must be no allocations between the get_memory_map()
- * call and the exit_boot_services() call, so the exiting of
- * boot services is very tightly tied to the creation of the FDT
- * with the final memory map in it.
+ * Allocate memory for a new FDT, then add EFI and commandline related fields
+ * to the FDT. This routine increases the FDT allocation size until the
+ * allocated memory is large enough. EFI allocations are in EFI_PAGE_SIZE
+ * granules, which are fixed at 4K bytes, so in most cases the first allocation
+ * should succeed. EFI boot services are exited at the end of this function.
+ * There must be no allocations between the get_memory_map() call and the
+ * exit_boot_services() call, so the exiting of boot services is very tightly
+ * tied to the creation of the FDT with the final memory map in it.
*/
-
+static
efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
+ efi_loaded_image_t *image,
unsigned long *new_fdt_addr,
- u64 initrd_addr, u64 initrd_size,
- char *cmdline_ptr,
- unsigned long fdt_addr,
- unsigned long fdt_size)
+ char *cmdline_ptr)
{
- unsigned long map_size, desc_size, buff_size;
+ unsigned long desc_size;
u32 desc_ver;
- unsigned long mmap_key;
- efi_memory_desc_t *memory_map, *runtime_map;
efi_status_t status;
- int runtime_entry_count;
- struct efi_boot_memmap map;
struct exit_boot_struct priv;
+ unsigned long fdt_addr = 0;
+ unsigned long fdt_size = 0;
- map.map = &runtime_map;
- map.map_size = &map_size;
- map.desc_size = &desc_size;
- map.desc_ver = &desc_ver;
- map.key_ptr = &mmap_key;
- map.buff_size = &buff_size;
+ if (!efi_novamap) {
+ status = efi_alloc_virtmap(&priv.runtime_map, &desc_size,
+ &desc_ver);
+ if (status != EFI_SUCCESS) {
+ efi_err("Unable to retrieve UEFI memory map.\n");
+ return status;
+ }
+ }
/*
- * Get a copy of the current memory map that we will use to prepare
- * the input for SetVirtualAddressMap(). We don't have to worry about
- * subsequent allocations adding entries, since they could not affect
- * the number of EFI_MEMORY_RUNTIME regions.
+ * Unauthenticated device tree data is a security hazard, so ignore
+ * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure
+ * boot is enabled if we can't determine its state.
*/
- status = efi_get_memory_map(&map);
- if (status != EFI_SUCCESS) {
- efi_err("Unable to retrieve UEFI memory map.\n");
- return status;
+ if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
+ efi_get_secureboot() != efi_secureboot_mode_disabled) {
+ if (strstr(cmdline_ptr, "dtb="))
+ efi_err("Ignoring DTB from command line.\n");
+ } else {
+ status = efi_load_dtb(image, &fdt_addr, &fdt_size);
+
+ if (status != EFI_SUCCESS && status != EFI_NOT_READY) {
+ efi_err("Failed to load device tree!\n");
+ goto fail;
+ }
}
+ if (fdt_addr) {
+ efi_info("Using DTB from command line\n");
+ } else {
+ /* Look for a device tree configuration table entry. */
+ fdt_addr = (uintptr_t)get_fdt(&fdt_size);
+ if (fdt_addr)
+ efi_info("Using DTB from configuration table\n");
+ }
+
+ if (!fdt_addr)
+ efi_info("Generating empty DTB\n");
+
efi_info("Exiting boot services...\n");
- map.map = &memory_map;
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
if (status != EFI_SUCCESS) {
efi_err("Unable to allocate memory for new device tree.\n");
goto fail;
}
- /*
- * Now that we have done our final memory allocation (and free)
- * we can get the memory map key needed for exit_boot_services().
- */
- status = efi_get_memory_map(&map);
- if (status != EFI_SUCCESS)
- goto fail_free_new_fdt;
-
status = update_fdt((void *)fdt_addr, fdt_size,
- (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
- initrd_addr, initrd_size);
+ (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr);
if (status != EFI_SUCCESS) {
efi_err("Unable to construct new device tree.\n");
goto fail_free_new_fdt;
}
- runtime_entry_count = 0;
- priv.runtime_map = runtime_map;
- priv.runtime_entry_count = &runtime_entry_count;
- priv.new_fdt_addr = (void *)*new_fdt_addr;
+ priv.new_fdt_addr = (void *)*new_fdt_addr;
- status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
+ status = efi_exit_boot_services(handle, &priv, exit_boot_func);
if (status == EFI_SUCCESS) {
efi_set_virtual_address_map_t *svam;
@@ -312,8 +299,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
/* Install the new virtual address map */
svam = efi_system_table->runtime->set_virtual_address_map;
- status = svam(runtime_entry_count * desc_size, desc_size,
- desc_ver, runtime_map);
+ status = svam(priv.runtime_entry_count * desc_size, desc_size,
+ desc_ver, priv.runtime_map);
/*
* We are beyond the point of no return here, so if the call to
@@ -321,6 +308,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
* incoming kernel but proceed normally otherwise.
*/
if (status != EFI_SUCCESS) {
+ efi_memory_desc_t *p;
int l;
/*
@@ -329,8 +317,9 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
* the incoming kernel that no virtual translation has
* been installed.
*/
- for (l = 0; l < map_size; l += desc_size) {
- efi_memory_desc_t *p = (void *)memory_map + l;
+ for (l = 0; l < priv.boot_memmap->map_size;
+ l += priv.boot_memmap->desc_size) {
+ p = (void *)priv.boot_memmap->map + l;
if (p->attribute & EFI_MEMORY_RUNTIME)
p->virt_addr = 0;
@@ -345,11 +334,33 @@ fail_free_new_fdt:
efi_free(MAX_FDT_SIZE, *new_fdt_addr);
fail:
- efi_system_table->boottime->free_pool(runtime_map);
+ efi_free(fdt_size, fdt_addr);
+
+ efi_bs_call(free_pool, priv.runtime_map);
return EFI_LOAD_ERROR;
}
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+ unsigned long kernel_addr, char *cmdline_ptr)
+{
+ unsigned long fdt_addr;
+ efi_status_t status;
+
+ status = allocate_new_fdt_and_exit_boot(handle, image, &fdt_addr,
+ cmdline_ptr);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to update FDT and exit boot services\n");
+ return status;
+ }
+
+ if (IS_ENABLED(CONFIG_ARM))
+ efi_handle_post_ebs_state();
+
+ efi_enter_kernel(kernel_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
+ /* not reached */
+}
+
void *get_fdt(unsigned long *fdt_size)
{
void *fdt;
diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
index bf133d39a543..f756c61396e9 100644
--- a/drivers/firmware/efi/libstub/file.c
+++ b/drivers/firmware/efi/libstub/file.c
@@ -256,6 +256,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
if (volume)
volume->close(volume);
+
+ if (*load_size == 0)
+ return EFI_NOT_READY;
return EFI_SUCCESS;
err_close_file:
diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c
index b7ef8d2df59e..32329f2a92f9 100644
--- a/drivers/firmware/efi/libstub/loongarch-stub.c
+++ b/drivers/firmware/efi/libstub/loongarch-stub.c
@@ -9,7 +9,8 @@
#include <asm/addrspace.h>
#include "efistub.h"
-typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long fdt);
+typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline,
+ unsigned long systab);
extern int kernel_asize;
extern int kernel_fsize;
@@ -42,19 +43,60 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
return status;
}
-void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, unsigned long fdt_size)
+struct exit_boot_struct {
+ efi_memory_desc_t *runtime_map;
+ int runtime_entry_count;
+};
+
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
+{
+ struct exit_boot_struct *p = priv;
+
+ /*
+ * Update the memory map with virtual addresses. The function will also
+ * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
+ * entries so that we can pass it straight to SetVirtualAddressMap()
+ */
+ efi_get_virtmap(map->map, map->map_size, map->desc_size,
+ p->runtime_map, &p->runtime_entry_count);
+
+ return EFI_SUCCESS;
+}
+
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+ unsigned long kernel_addr, char *cmdline_ptr)
{
kernel_entry_t real_kernel_entry;
+ struct exit_boot_struct priv;
+ unsigned long desc_size;
+ efi_status_t status;
+ u32 desc_ver;
+
+ status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver);
+ if (status != EFI_SUCCESS) {
+ efi_err("Unable to retrieve UEFI memory map.\n");
+ return status;
+ }
+
+ efi_info("Exiting boot services\n");
+
+ efi_novamap = false;
+ status = efi_exit_boot_services(handle, &priv, exit_boot_func);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ /* Install the new virtual address map */
+ efi_rt_call(set_virtual_address_map,
+ priv.runtime_entry_count * desc_size, desc_size,
+ desc_ver, priv.runtime_map);
/* Config Direct Mapping */
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
real_kernel_entry = (kernel_entry_t)
- ((unsigned long)&kernel_entry - entrypoint + VMLINUX_LOAD_ADDRESS);
+ ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS);
- if (!efi_novamap)
- real_kernel_entry(true, fdt);
- else
- real_kernel_entry(false, fdt);
+ real_kernel_entry(true, (unsigned long)cmdline_ptr,
+ (unsigned long)efi_system_table);
}
diff --git a/drivers/firmware/efi/libstub/mem.c b/drivers/firmware/efi/libstub/mem.c
index feef8d4be113..45841ef55a9f 100644
--- a/drivers/firmware/efi/libstub/mem.c
+++ b/drivers/firmware/efi/libstub/mem.c
@@ -5,71 +5,66 @@
#include "efistub.h"
-static inline bool mmap_has_headroom(unsigned long buff_size,
- unsigned long map_size,
- unsigned long desc_size)
-{
- unsigned long slack = buff_size - map_size;
-
- return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
-}
-
/**
* efi_get_memory_map() - get memory map
- * @map: on return pointer to memory map
+ * @map: pointer to memory map pointer to which to assign the
+ * newly allocated memory map
+ * @install_cfg_tbl: whether or not to install the boot memory map as a
+ * configuration table
*
* Retrieve the UEFI memory map. The allocated memory leaves room for
* up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries.
*
* Return: status code
*/
-efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
+efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
+ bool install_cfg_tbl)
{
- efi_memory_desc_t *m = NULL;
+ int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY
+ : EFI_LOADER_DATA;
+ efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;
+ struct efi_boot_memmap *m, tmp;
efi_status_t status;
- unsigned long key;
- u32 desc_version;
-
- *map->desc_size = sizeof(*m);
- *map->map_size = *map->desc_size * 32;
- *map->buff_size = *map->map_size;
-again:
- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
- *map->map_size, (void **)&m);
+ unsigned long size;
+
+ tmp.map_size = 0;
+ status = efi_bs_call(get_memory_map, &tmp.map_size, NULL, &tmp.map_key,
+ &tmp.desc_size, &tmp.desc_ver);
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return EFI_LOAD_ERROR;
+
+ size = tmp.map_size + tmp.desc_size * EFI_MMAP_NR_SLACK_SLOTS;
+ status = efi_bs_call(allocate_pool, memtype, sizeof(*m) + size,
+ (void **)&m);
if (status != EFI_SUCCESS)
- goto fail;
-
- *map->desc_size = 0;
- key = 0;
- status = efi_bs_call(get_memory_map, map->map_size, m,
- &key, map->desc_size, &desc_version);
- if (status == EFI_BUFFER_TOO_SMALL ||
- !mmap_has_headroom(*map->buff_size, *map->map_size,
- *map->desc_size)) {
- efi_bs_call(free_pool, m);
+ return status;
+
+ if (install_cfg_tbl) {
/*
- * Make sure there is some entries of headroom so that the
- * buffer can be reused for a new map after allocations are
- * no longer permitted. Its unlikely that the map will grow to
- * exceed this headroom once we are ready to trigger
- * ExitBootServices()
+ * Installing a configuration table might allocate memory, and
+ * this may modify the memory map. This means we should install
+ * the configuration table first, and re-install or delete it
+ * as needed.
*/
- *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
- *map->buff_size = *map->map_size;
- goto again;
+ status = efi_bs_call(install_configuration_table, &tbl_guid, m);
+ if (status != EFI_SUCCESS)
+ goto free_map;
}
- if (status == EFI_SUCCESS) {
- if (map->key_ptr)
- *map->key_ptr = key;
- if (map->desc_ver)
- *map->desc_ver = desc_version;
- } else {
- efi_bs_call(free_pool, m);
- }
+ m->buff_size = m->map_size = size;
+ status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key,
+ &m->desc_size, &m->desc_ver);
+ if (status != EFI_SUCCESS)
+ goto uninstall_table;
+
+ *map = m;
+ return EFI_SUCCESS;
-fail:
- *map->map = m;
+uninstall_table:
+ if (install_cfg_tbl)
+ efi_bs_call(install_configuration_table, &tbl_guid, NULL);
+free_map:
+ efi_bs_call(free_pool, m);
return status;
}
diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c
index 715f37479154..9fb5869896be 100644
--- a/drivers/firmware/efi/libstub/randomalloc.c
+++ b/drivers/firmware/efi/libstub/randomalloc.c
@@ -55,22 +55,13 @@ efi_status_t efi_random_alloc(unsigned long size,
unsigned long *addr,
unsigned long random_seed)
{
- unsigned long map_size, desc_size, total_slots = 0, target_slot;
+ unsigned long total_slots = 0, target_slot;
unsigned long total_mirrored_slots = 0;
- unsigned long buff_size;
+ struct efi_boot_memmap *map;
efi_status_t status;
- efi_memory_desc_t *memory_map;
int map_offset;
- struct efi_boot_memmap map;
- map.map = &memory_map;
- map.map_size = &map_size;
- map.desc_size = &desc_size;
- map.desc_ver = NULL;
- map.key_ptr = NULL;
- map.buff_size = &buff_size;
-
- status = efi_get_memory_map(&map);
+ status = efi_get_memory_map(&map, false);
if (status != EFI_SUCCESS)
return status;
@@ -80,8 +71,8 @@ efi_status_t efi_random_alloc(unsigned long size,
size = round_up(size, EFI_ALLOC_ALIGN);
/* count the suitable slots in each memory map entry */
- for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
- efi_memory_desc_t *md = (void *)memory_map + map_offset;
+ for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+ efi_memory_desc_t *md = (void *)map->map + map_offset;
unsigned long slots;
slots = get_entry_num_slots(md, size, ilog2(align));
@@ -109,8 +100,8 @@ efi_status_t efi_random_alloc(unsigned long size,
* to calculate the randomly chosen address, and allocate it directly
* using EFI_ALLOCATE_ADDRESS.
*/
- for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
- efi_memory_desc_t *md = (void *)memory_map + map_offset;
+ for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
+ efi_memory_desc_t *md = (void *)map->map + map_offset;
efi_physical_addr_t target;
unsigned long pages;
@@ -133,7 +124,7 @@ efi_status_t efi_random_alloc(unsigned long size,
break;
}
- efi_bs_call(free_pool, memory_map);
+ efi_bs_call(free_pool, map);
return status;
}
diff --git a/drivers/firmware/efi/libstub/relocate.c b/drivers/firmware/efi/libstub/relocate.c
index 8ee9eb2b9039..bf6fbd5d22a1 100644
--- a/drivers/firmware/efi/libstub/relocate.c
+++ b/drivers/firmware/efi/libstub/relocate.c
@@ -23,21 +23,12 @@
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
unsigned long *addr, unsigned long min)
{
- unsigned long map_size, desc_size, buff_size;
- efi_memory_desc_t *map;
+ struct efi_boot_memmap *map;
efi_status_t status;
unsigned long nr_pages;
int i;
- struct efi_boot_memmap boot_map;
- boot_map.map = &map;
- boot_map.map_size = &map_size;
- boot_map.desc_size = &desc_size;
- boot_map.desc_ver = NULL;
- boot_map.key_ptr = NULL;
- boot_map.buff_size = &buff_size;
-
- status = efi_get_memory_map(&boot_map);
+ status = efi_get_memory_map(&map, false);
if (status != EFI_SUCCESS)
goto fail;
@@ -52,12 +43,12 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
size = round_up(size, EFI_ALLOC_ALIGN);
nr_pages = size / EFI_PAGE_SIZE;
- for (i = 0; i < map_size / desc_size; i++) {
+ for (i = 0; i < map->map_size / map->desc_size; i++) {
efi_memory_desc_t *desc;
- unsigned long m = (unsigned long)map;
+ unsigned long m = (unsigned long)map->map;
u64 start, end;
- desc = efi_early_memdesc_ptr(m, desc_size, i);
+ desc = efi_early_memdesc_ptr(m, map->desc_size, i);
if (desc->type != EFI_CONVENTIONAL_MEMORY)
continue;
@@ -87,7 +78,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
}
}
- if (i == map_size / desc_size)
+ if (i == map->map_size / map->desc_size)
status = EFI_NOT_FOUND;
efi_bs_call(free_pool, map);
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 05ae8bcc9d67..8cb7ff5ecffc 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -716,32 +716,22 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
efi_set_u64_split((unsigned long)efi_system_table,
&p->efi->efi_systab, &p->efi->efi_systab_hi);
- p->efi->efi_memdesc_size = *map->desc_size;
- p->efi->efi_memdesc_version = *map->desc_ver;
- efi_set_u64_split((unsigned long)*map->map,
+ p->efi->efi_memdesc_size = map->desc_size;
+ p->efi->efi_memdesc_version = map->desc_ver;
+ efi_set_u64_split((unsigned long)map->map,
&p->efi->efi_memmap, &p->efi->efi_memmap_hi);
- p->efi->efi_memmap_size = *map->map_size;
+ p->efi->efi_memmap_size = map->map_size;
return EFI_SUCCESS;
}
static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
{
- unsigned long map_sz, key, desc_size, buff_size;
- efi_memory_desc_t *mem_map;
struct setup_data *e820ext = NULL;
__u32 e820ext_size = 0;
efi_status_t status;
- __u32 desc_version;
- struct efi_boot_memmap map;
struct exit_boot_struct priv;
- map.map = &mem_map;
- map.map_size = &map_sz;
- map.desc_size = &desc_size;
- map.desc_ver = &desc_version;
- map.key_ptr = &key;
- map.buff_size = &buff_size;
priv.boot_params = boot_params;
priv.efi = &boot_params->efi_info;
@@ -750,7 +740,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
return status;
/* Might as well exit boot services now */
- status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func);
+ status = efi_exit_boot_services(handle, &priv, exit_boot_func);
if (status != EFI_SUCCESS)
return status;
@@ -776,7 +766,7 @@ unsigned long efi_main(efi_handle_t handle,
unsigned long bzimage_addr = (unsigned long)startup_32;
unsigned long buffer_start, buffer_end;
struct setup_header *hdr = &boot_params->hdr;
- unsigned long addr, size;
+ const struct linux_efi_initrd *initrd = NULL;
efi_status_t status;
efi_system_table = sys_table_arg;
@@ -871,17 +861,18 @@ unsigned long efi_main(efi_handle_t handle,
* arguments will be processed only if image is not NULL, which will be
* the case only if we were loaded via the PE entry point.
*/
- status = efi_load_initrd(image, &addr, &size, hdr->initrd_addr_max,
- ULONG_MAX);
+ status = efi_load_initrd(image, hdr->initrd_addr_max, ULONG_MAX,
+ &initrd);
if (status != EFI_SUCCESS)
goto fail;
- if (size > 0) {
- efi_set_u64_split(addr, &hdr->ramdisk_image,
+ if (initrd && initrd->size > 0) {
+ efi_set_u64_split(initrd->base, &hdr->ramdisk_image,
&boot_params->ext_ramdisk_image);
- efi_set_u64_split(size, &hdr->ramdisk_size,
+ efi_set_u64_split(initrd->size, &hdr->ramdisk_size,
&boot_params->ext_ramdisk_size);
}
+
/*
* If the boot loader gave us a value for secure_boot then we use that,
* otherwise we ask the BIOS.