Commit 4fc8e738 authored by Ard Biesheuvel's avatar Ard Biesheuvel

efi: libstub: remove DT dependency from generic stub

Refactor the generic EFI stub entry code so that all the dependencies on
device tree are abstracted and hidden behind a generic efi_boot_kernel()
routine that can also be implemented in other ways. This allows users of
the generic stub to avoid using FDT for passing information to the core
kernel.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent f4dc7fff
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
*/ */
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/libfdt.h>
#include <asm/efi.h> #include <asm/efi.h>
#include "efistub.h" #include "efistub.h"
...@@ -132,14 +131,11 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -132,14 +131,11 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
unsigned long image_addr; unsigned long image_addr;
unsigned long image_size = 0; unsigned long image_size = 0;
/* addr/point and size pairs for memory management*/ /* addr/point and size pairs for memory management*/
unsigned long fdt_addr = 0; /* Original DTB */
unsigned long fdt_size = 0;
char *cmdline_ptr = NULL; char *cmdline_ptr = NULL;
int cmdline_size = 0; int cmdline_size = 0;
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
unsigned long reserve_addr = 0; unsigned long reserve_addr = 0;
unsigned long reserve_size = 0; unsigned long reserve_size = 0;
enum efi_secureboot_mode secure_boot;
struct screen_info *si; struct screen_info *si;
efi_properties_table_t *prop_tbl; efi_properties_table_t *prop_tbl;
...@@ -215,38 +211,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -215,38 +211,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
/* Ask the firmware to clear memory on unclean shutdown */ /* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation(); 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 && status != EFI_NOT_READY) {
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, ULONG_MAX, efi_get_max_initrd_addr(image_addr), efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr),
NULL); NULL);
...@@ -290,23 +254,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -290,23 +254,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
install_memreserve_table(); install_memreserve_table();
status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr, cmdline_ptr, status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
fdt_addr, fdt_size);
if (status != EFI_SUCCESS)
goto fail_free_fdt;
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_fdt:
efi_err("Failed to update FDT and exit boot services\n");
efi_free(fdt_size, fdt_addr);
fail_free_image:
efi_free(image_size, image_addr); efi_free(image_size, image_addr);
efi_free(reserve_size, reserve_addr); efi_free(reserve_size, reserve_addr);
fail_free_screeninfo: fail_free_screeninfo:
......
...@@ -844,11 +844,8 @@ typedef efi_status_t (*efi_exit_boot_map_processing)( ...@@ -844,11 +844,8 @@ typedef efi_status_t (*efi_exit_boot_map_processing)(
efi_status_t efi_exit_boot_services(void *handle, void *priv, efi_status_t efi_exit_boot_services(void *handle, void *priv,
efi_exit_boot_map_processing priv_func); efi_exit_boot_map_processing priv_func);
efi_status_t allocate_new_fdt_and_exit_boot(void *handle, efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
unsigned long *new_fdt_addr, unsigned long kernel_addr, char *cmdline_ptr);
char *cmdline_ptr,
unsigned long fdt_addr,
unsigned long fdt_size);
void *get_fdt(unsigned long *fdt_size); void *get_fdt(unsigned long *fdt_size);
......
...@@ -219,17 +219,18 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) ...@@ -219,17 +219,18 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
* exit_boot_services() call, so the exiting of boot services is very tightly * 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. * 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_status_t allocate_new_fdt_and_exit_boot(void *handle,
efi_loaded_image_t *image,
unsigned long *new_fdt_addr, unsigned long *new_fdt_addr,
char *cmdline_ptr, char *cmdline_ptr)
unsigned long fdt_addr,
unsigned long fdt_size)
{ {
unsigned long desc_size; unsigned long desc_size;
u32 desc_ver; u32 desc_ver;
efi_status_t status; efi_status_t status;
struct exit_boot_struct priv; struct exit_boot_struct priv;
unsigned long fdt_addr = 0;
unsigned long fdt_size = 0;
if (!efi_novamap) { if (!efi_novamap) {
status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, status = efi_alloc_virtmap(&priv.runtime_map, &desc_size,
...@@ -240,6 +241,36 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, ...@@ -240,6 +241,36 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
} }
} }
/*
* 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) ||
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"); efi_info("Exiting boot services...\n");
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX); status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
...@@ -303,11 +334,33 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, ...@@ -303,11 +334,33 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
efi_free(MAX_FDT_SIZE, *new_fdt_addr); efi_free(MAX_FDT_SIZE, *new_fdt_addr);
fail: fail:
efi_free(fdt_size, fdt_addr);
efi_bs_call(free_pool, priv.runtime_map); efi_bs_call(free_pool, priv.runtime_map);
return EFI_LOAD_ERROR; 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 *get_fdt(unsigned long *fdt_size)
{ {
void *fdt; void *fdt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment