efi: libstub: Factor out EFI stub entrypoint into separate file
In preparation for allowing the EFI zboot decompressor to reuse most of the EFI stub machinery, factor out the actual EFI PE/COFF entrypoint into a separate file. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
da8dd0c75b
commit
42c8ea3dca
4 changed files with 100 additions and 64 deletions
|
@ -83,7 +83,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
|
||||||
$(call if_changed_rule,cc_o_c)
|
$(call if_changed_rule,cc_o_c)
|
||||||
|
|
||||||
lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
|
lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
|
||||||
screen_info.o
|
screen_info.o efi-stub-entry.o
|
||||||
|
|
||||||
lib-$(CONFIG_ARM) += arm32-stub.o
|
lib-$(CONFIG_ARM) += arm32-stub.o
|
||||||
lib-$(CONFIG_ARM64) += arm64-stub.o arm64-entry.o
|
lib-$(CONFIG_ARM64) += arm64-stub.o arm64-entry.o
|
||||||
|
|
65
drivers/firmware/efi/libstub/efi-stub-entry.c
Normal file
65
drivers/firmware/efi/libstub/efi-stub-entry.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <linux/efi.h>
|
||||||
|
#include <asm/efi.h>
|
||||||
|
|
||||||
|
#include "efistub.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
|
||||||
|
* LoongArch. This is the entrypoint that is described in the PE/COFF header
|
||||||
|
* of the core kernel.
|
||||||
|
*/
|
||||||
|
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||||
|
efi_system_table_t *systab)
|
||||||
|
{
|
||||||
|
efi_loaded_image_t *image;
|
||||||
|
efi_status_t status;
|
||||||
|
unsigned long image_addr;
|
||||||
|
unsigned long image_size = 0;
|
||||||
|
/* addr/point and size pairs for memory management*/
|
||||||
|
char *cmdline_ptr = NULL;
|
||||||
|
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
|
||||||
|
unsigned long reserve_addr = 0;
|
||||||
|
unsigned long reserve_size = 0;
|
||||||
|
|
||||||
|
WRITE_ONCE(efi_system_table, systab);
|
||||||
|
|
||||||
|
/* Check if we were booted by the EFI firmware */
|
||||||
|
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a handle to the loaded image protocol. This is used to get
|
||||||
|
* information about the running image, such as size and the command
|
||||||
|
* line.
|
||||||
|
*/
|
||||||
|
status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
|
||||||
|
(void *)&image);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
efi_err("Failed to get loaded image protocol\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = efi_handle_cmdline(image, &cmdline_ptr);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
efi_info("Booting Linux Kernel...\n");
|
||||||
|
|
||||||
|
status = handle_kernel_image(&image_addr, &image_size,
|
||||||
|
&reserve_addr,
|
||||||
|
&reserve_size,
|
||||||
|
image, handle);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
efi_err("Failed to relocate kernel\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
|
||||||
|
|
||||||
|
efi_free(image_size, image_addr);
|
||||||
|
efi_free(reserve_size, reserve_addr);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
|
@ -115,61 +115,21 @@ static u32 get_supported_rt_services(void)
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
||||||
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
|
|
||||||
* that is described in the PE/COFF header. Most of the code is the same
|
|
||||||
* for both archictectures, with the arch-specific code provided in the
|
|
||||||
* handle_kernel_image() function.
|
|
||||||
*/
|
|
||||||
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
|
||||||
efi_system_table_t *sys_table_arg)
|
|
||||||
{
|
{
|
||||||
efi_loaded_image_t *image;
|
|
||||||
efi_status_t status;
|
|
||||||
unsigned long image_addr;
|
|
||||||
unsigned long image_size = 0;
|
|
||||||
/* addr/point and size pairs for memory management*/
|
|
||||||
char *cmdline_ptr = NULL;
|
|
||||||
int cmdline_size = 0;
|
int cmdline_size = 0;
|
||||||
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
|
efi_status_t status;
|
||||||
unsigned long reserve_addr = 0;
|
char *cmdline;
|
||||||
unsigned long reserve_size = 0;
|
|
||||||
struct screen_info *si;
|
|
||||||
|
|
||||||
efi_system_table = sys_table_arg;
|
|
||||||
|
|
||||||
/* Check if we were booted by the EFI firmware */
|
|
||||||
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
|
|
||||||
status = EFI_INVALID_PARAMETER;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = check_platform_features();
|
|
||||||
if (status != EFI_SUCCESS)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get a handle to the loaded image protocol. This is used to get
|
|
||||||
* information about the running image, such as size and the command
|
|
||||||
* line.
|
|
||||||
*/
|
|
||||||
status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
|
|
||||||
(void *)&image);
|
|
||||||
if (status != EFI_SUCCESS) {
|
|
||||||
efi_err("Failed to get loaded image protocol\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the command line from EFI, using the LOADED_IMAGE
|
* Get the command line from EFI, using the LOADED_IMAGE
|
||||||
* protocol. We are going to copy the command line into the
|
* protocol. We are going to copy the command line into the
|
||||||
* device tree, so this can be allocated anywhere.
|
* device tree, so this can be allocated anywhere.
|
||||||
*/
|
*/
|
||||||
cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
|
cmdline = efi_convert_cmdline(image, &cmdline_size);
|
||||||
if (!cmdline_ptr) {
|
if (!cmdline) {
|
||||||
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
|
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
|
||||||
status = EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||||
|
@ -183,26 +143,35 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
|
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
|
||||||
status = efi_parse_options(cmdline_ptr);
|
status = efi_parse_options(cmdline);
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
efi_err("Failed to parse options\n");
|
efi_err("Failed to parse options\n");
|
||||||
goto fail_free_cmdline;
|
goto fail_free_cmdline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
efi_info("Booting Linux Kernel...\n");
|
*cmdline_ptr = cmdline;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
fail_free_cmdline:
|
||||||
|
efi_bs_call(free_pool, cmdline_ptr);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
efi_status_t efi_stub_common(efi_handle_t handle,
|
||||||
|
efi_loaded_image_t *image,
|
||||||
|
unsigned long image_addr,
|
||||||
|
char *cmdline_ptr)
|
||||||
|
{
|
||||||
|
struct screen_info *si;
|
||||||
|
efi_status_t status;
|
||||||
|
|
||||||
|
status = check_platform_features();
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
si = setup_graphics();
|
si = setup_graphics();
|
||||||
|
|
||||||
status = handle_kernel_image(&image_addr, &image_size,
|
|
||||||
&reserve_addr,
|
|
||||||
&reserve_size,
|
|
||||||
image, handle);
|
|
||||||
if (status != EFI_SUCCESS) {
|
|
||||||
efi_err("Failed to relocate kernel\n");
|
|
||||||
goto fail_free_screeninfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
efi_retrieve_tpm2_eventlog();
|
efi_retrieve_tpm2_eventlog();
|
||||||
|
|
||||||
/* Ask the firmware to clear memory on unclean shutdown */
|
/* Ask the firmware to clear memory on unclean shutdown */
|
||||||
|
@ -221,13 +190,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||||
|
|
||||||
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
|
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
|
||||||
|
|
||||||
efi_free(image_size, image_addr);
|
|
||||||
efi_free(reserve_size, reserve_addr);
|
|
||||||
fail_free_screeninfo:
|
|
||||||
free_screen_info(si);
|
free_screen_info(si);
|
||||||
fail_free_cmdline:
|
|
||||||
efi_bs_call(free_pool, cmdline_ptr);
|
|
||||||
fail:
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -958,6 +958,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
||||||
efi_loaded_image_t *image,
|
efi_loaded_image_t *image,
|
||||||
efi_handle_t image_handle);
|
efi_handle_t image_handle);
|
||||||
|
|
||||||
|
/* shared entrypoint between the normal stub and the zboot stub */
|
||||||
|
efi_status_t efi_stub_common(efi_handle_t handle,
|
||||||
|
efi_loaded_image_t *image,
|
||||||
|
unsigned long image_addr,
|
||||||
|
char *cmdline_ptr);
|
||||||
|
|
||||||
|
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr);
|
||||||
|
|
||||||
asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
|
asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
|
||||||
unsigned long fdt_addr,
|
unsigned long fdt_addr,
|
||||||
unsigned long fdt_size);
|
unsigned long fdt_size);
|
||||||
|
|
Loading…
Add table
Reference in a new issue