summaryrefslogtreecommitdiff
path: root/drivers/firmware/efi/libstub
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi/libstub')
-rw-r--r--drivers/firmware/efi/libstub/Makefile13
-rw-r--r--drivers/firmware/efi/libstub/Makefile.zboot6
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c1
-rw-r--r--drivers/firmware/efi/libstub/efistub.h3
-rw-r--r--drivers/firmware/efi/libstub/intrinsics.c26
-rw-r--r--drivers/firmware/efi/libstub/x86-5lvl.c2
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c52
-rw-r--r--drivers/firmware/efi/libstub/zboot-decompress-gzip.c68
-rw-r--r--drivers/firmware/efi/libstub/zboot-decompress-zstd.c49
-rw-r--r--drivers/firmware/efi/libstub/zboot-header.S32
-rw-r--r--drivers/firmware/efi/libstub/zboot.c65
-rw-r--r--drivers/firmware/efi/libstub/zboot.lds14
12 files changed, 238 insertions, 93 deletions
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 1141cd06011f..939a4955e00b 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -31,7 +31,7 @@ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
$(DISABLE_STACKLEAK_PLUGIN)
cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax \
$(DISABLE_STACKLEAK_PLUGIN)
-cflags-$(CONFIG_LOONGARCH) += -fpie
+cflags-$(CONFIG_LOONGARCH) += -fpie $(DISABLE_STACKLEAK_PLUGIN)
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
@@ -62,6 +62,8 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS))
# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL
KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL))
+KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
+
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
file.o mem.o random.o randomalloc.o pci.o \
skip_spaces.o lib-cmdline.o lib-ctype.o \
@@ -89,12 +91,17 @@ lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
-zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o
+zboot-obj-y := zboot-decompress-gzip.o
+CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
+zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
+CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
+
+zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
-extra-y := $(lib-y)
+targets := $(lib-y)
lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
# Even when -mbranch-protection=none is set, Clang will generate a
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index 48842b5c106b..832deee36e48 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -36,7 +36,7 @@ aflags-zboot-header-$(EFI_ZBOOT_FORWARD_CFI) := \
-DPE_DLL_CHAR_EX=IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
- -DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
+ -DZBOOT_EFI_PATH="\"$(abspath $(obj)/vmlinuz.efi.elf)\"" \
-DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
-DCOMP_TYPE="\"$(comp-type-y)\"" \
$(aflags-zboot-header-y)
@@ -44,6 +44,10 @@ AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
$(call if_changed_rule,as_o_S)
+ifneq ($(CONFIG_EFI_SBAT_FILE),)
+$(obj)/zboot-header.o: $(CONFIG_EFI_SBAT_FILE)
+endif
+
ZBOOT_DEPS := $(obj)/zboot-header.o $(objtree)/drivers/firmware/efi/libstub/lib.a
LDFLAGS_vmlinuz.efi.elf := -T $(srctree)/drivers/firmware/efi/libstub/zboot.lds
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index fd6dc790c5a8..7aa2f9ad2935 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -601,6 +601,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
* @image: EFI loaded image protocol
* @soft_limit: preferred address for loading the initrd
* @hard_limit: upper limit address for loading the initrd
+ * @out: pointer to store the address of the initrd table
*
* Return: status code
*/
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index d96d4494070d..f5ba032863a9 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1234,4 +1234,7 @@ void process_unaccepted_memory(u64 start, u64 end);
void accept_memory(phys_addr_t start, unsigned long size);
void arch_accept_memory(phys_addr_t start, phys_addr_t end);
+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
+
#endif
diff --git a/drivers/firmware/efi/libstub/intrinsics.c b/drivers/firmware/efi/libstub/intrinsics.c
index 965e734f6f98..418cd2e6dccc 100644
--- a/drivers/firmware/efi/libstub/intrinsics.c
+++ b/drivers/firmware/efi/libstub/intrinsics.c
@@ -15,8 +15,31 @@ void *__memmove(void *__dest, const void *__src, size_t count) __alias(memmove);
void *__memset(void *s, int c, size_t count) __alias(memset);
#endif
+static void *efistub_memmove(u8 *dst, const u8 *src, size_t len)
+{
+ if (src > dst || dst >= (src + len))
+ for (size_t i = 0; i < len; i++)
+ dst[i] = src[i];
+ else
+ for (ssize_t i = len - 1; i >= 0; i--)
+ dst[i] = src[i];
+
+ return dst;
+}
+
+static void *efistub_memset(void *dst, int c, size_t len)
+{
+ for (u8 *d = dst; len--; d++)
+ *d = c;
+
+ return dst;
+}
+
void *memcpy(void *dst, const void *src, size_t len)
{
+ if (efi_table_attr(efi_system_table, boottime) == NULL)
+ return efistub_memmove(dst, src, len);
+
efi_bs_call(copy_mem, dst, src, len);
return dst;
}
@@ -25,6 +48,9 @@ extern void *memmove(void *dst, const void *src, size_t len) __alias(memcpy);
void *memset(void *dst, int c, size_t len)
{
+ if (efi_table_attr(efi_system_table, boottime) == NULL)
+ return efistub_memset(dst, c, len);
+
efi_bs_call(set_mem, dst, len, c & U8_MAX);
return dst;
}
diff --git a/drivers/firmware/efi/libstub/x86-5lvl.c b/drivers/firmware/efi/libstub/x86-5lvl.c
index 77359e802181..f1c5fb45d5f7 100644
--- a/drivers/firmware/efi/libstub/x86-5lvl.c
+++ b/drivers/firmware/efi/libstub/x86-5lvl.c
@@ -62,7 +62,7 @@ efi_status_t efi_setup_5level_paging(void)
void efi_5level_switch(void)
{
- bool want_la57 = IS_ENABLED(CONFIG_X86_5LEVEL) && !efi_no5lvl;
+ bool want_la57 = !efi_no5lvl;
bool have_la57 = native_read_cr4() & X86_CR4_LA57;
bool need_toggle = want_la57 ^ have_la57;
u64 *pgt = (void *)la57_toggle + PAGE_SIZE;
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 863910e9eefc..cafc90d4caaf 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -397,17 +397,13 @@ static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
asm("hlt");
}
-void __noreturn efi_stub_entry(efi_handle_t handle,
- efi_system_table_t *sys_table_arg,
- struct boot_params *boot_params);
-
/*
* Because the x86 boot code expects to be passed a boot_params we
* need to create one ourselves (usually the bootloader would create
* one for us).
*/
-efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
- efi_system_table_t *sys_table_arg)
+static efi_status_t efi_allocate_bootparams(efi_handle_t handle,
+ struct boot_params **bp)
{
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
struct boot_params *boot_params;
@@ -416,21 +412,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
unsigned long alloc;
char *cmdline_ptr;
- 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)
- efi_exit(handle, EFI_INVALID_PARAMETER);
-
status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
if (status != EFI_SUCCESS) {
efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
- efi_exit(handle, status);
+ return status;
}
status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);
if (status != EFI_SUCCESS)
- efi_exit(handle, status);
+ return status;
boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);
hdr = &boot_params->hdr;
@@ -446,14 +436,14 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
cmdline_ptr = efi_convert_cmdline(image);
if (!cmdline_ptr) {
efi_free(PARAM_SIZE, alloc);
- efi_exit(handle, EFI_OUT_OF_RESOURCES);
+ return EFI_OUT_OF_RESOURCES;
}
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
&boot_params->ext_cmd_line_ptr);
- efi_stub_entry(handle, sys_table_arg, boot_params);
- /* not reached */
+ *bp = boot_params;
+ return EFI_SUCCESS;
}
static void add_e820ext(struct boot_params *params,
@@ -740,13 +730,16 @@ static efi_status_t parse_options(const char *cmdline)
return efi_parse_options(cmdline);
}
-static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
+static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
+ struct boot_params *boot_params)
{
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
unsigned long addr, alloc_size, entry;
efi_status_t status;
u32 seed[2] = {};
+ boot_params_ptr = boot_params;
+
/* determine the required size of the allocation */
alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),
MIN_KERNEL_ALIGN);
@@ -777,7 +770,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
seed[0] = 0;
}
- boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
+ boot_params->hdr.loadflags |= KASLR_FLAG;
}
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
@@ -815,20 +808,27 @@ static void __noreturn enter_kernel(unsigned long kernel_addr,
void __noreturn efi_stub_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg,
struct boot_params *boot_params)
+
{
efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
- struct setup_header *hdr = &boot_params->hdr;
const struct linux_efi_initrd *initrd = NULL;
unsigned long kernel_entry;
+ struct setup_header *hdr;
efi_status_t status;
- boot_params_ptr = boot_params;
-
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)
efi_exit(handle, EFI_INVALID_PARAMETER);
+ if (!IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL) || !boot_params) {
+ status = efi_allocate_bootparams(handle, &boot_params);
+ if (status != EFI_SUCCESS)
+ efi_exit(handle, status);
+ }
+
+ hdr = &boot_params->hdr;
+
if (have_unsupported_snp_features())
efi_exit(handle, EFI_UNSUPPORTED);
@@ -870,7 +870,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
if (efi_mem_encrypt > 0)
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
- status = efi_decompress_kernel(&kernel_entry);
+ status = efi_decompress_kernel(&kernel_entry, boot_params);
if (status != EFI_SUCCESS) {
efi_err("Failed to decompress kernel\n");
goto fail;
@@ -940,6 +940,12 @@ fail:
efi_exit(handle, status);
}
+efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ efi_system_table_t *sys_table_arg)
+{
+ efi_stub_entry(handle, sys_table_arg, NULL);
+}
+
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
struct boot_params *boot_params)
diff --git a/drivers/firmware/efi/libstub/zboot-decompress-gzip.c b/drivers/firmware/efi/libstub/zboot-decompress-gzip.c
new file mode 100644
index 000000000000..e97a7e9d3c98
--- /dev/null
+++ b/drivers/firmware/efi/libstub/zboot-decompress-gzip.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/efi.h>
+#include <linux/zlib.h>
+
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+#include "inftrees.c"
+#include "inffast.c"
+#include "inflate.c"
+
+extern unsigned char _gzdata_start[], _gzdata_end[];
+extern u32 __aligned(1) payload_size;
+
+static struct z_stream_s stream;
+
+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
+{
+ efi_status_t status;
+ int rc;
+
+ /* skip the 10 byte header, assume no recorded filename */
+ stream.next_in = _gzdata_start + 10;
+ stream.avail_in = _gzdata_end - stream.next_in;
+
+ status = efi_allocate_pages(zlib_inflate_workspacesize(),
+ (unsigned long *)&stream.workspace,
+ ULONG_MAX);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ rc = zlib_inflateInit2(&stream, -MAX_WBITS);
+ if (rc != Z_OK) {
+ efi_err("failed to initialize GZIP decompressor: %d\n", rc);
+ status = EFI_LOAD_ERROR;
+ goto out;
+ }
+
+ *alloc_size = payload_size;
+ return EFI_SUCCESS;
+out:
+ efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
+ return status;
+}
+
+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
+{
+ int rc;
+
+ stream.next_out = out;
+ stream.avail_out = outlen;
+
+ rc = zlib_inflate(&stream, 0);
+ zlib_inflateEnd(&stream);
+
+ efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
+
+ if (rc != Z_STREAM_END) {
+ efi_err("GZIP decompression failed with status %d\n", rc);
+ return EFI_LOAD_ERROR;
+ }
+
+ efi_cache_sync_image((unsigned long)out, outlen);
+
+ return EFI_SUCCESS;
+}
diff --git a/drivers/firmware/efi/libstub/zboot-decompress-zstd.c b/drivers/firmware/efi/libstub/zboot-decompress-zstd.c
new file mode 100644
index 000000000000..bde9d94dd2e3
--- /dev/null
+++ b/drivers/firmware/efi/libstub/zboot-decompress-zstd.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/efi.h>
+#include <linux/zstd.h>
+
+#include <asm/efi.h>
+
+#include "decompress_sources.h"
+#include "efistub.h"
+
+extern unsigned char _gzdata_start[], _gzdata_end[];
+extern u32 __aligned(1) payload_size;
+
+static size_t wksp_size;
+static void *wksp;
+
+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
+{
+ efi_status_t status;
+
+ wksp_size = zstd_dctx_workspace_bound();
+ status = efi_allocate_pages(wksp_size, (unsigned long *)&wksp, ULONG_MAX);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ *alloc_size = payload_size;
+ return EFI_SUCCESS;
+}
+
+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
+{
+ zstd_dctx *dctx = zstd_init_dctx(wksp, wksp_size);
+ size_t ret;
+ int retval;
+
+ ret = zstd_decompress_dctx(dctx, out, outlen, _gzdata_start,
+ _gzdata_end - _gzdata_start - 4);
+ efi_free(wksp_size, (unsigned long)wksp);
+
+ retval = zstd_get_error_code(ret);
+ if (retval) {
+ efi_err("ZSTD-decompression failed with status %d\n", retval);
+ return EFI_LOAD_ERROR;
+ }
+
+ efi_cache_sync_image((unsigned long)out, outlen);
+
+ return EFI_SUCCESS;
+}
diff --git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S
index fb676ded47fa..b6431edd0fc9 100644
--- a/drivers/firmware/efi/libstub/zboot-header.S
+++ b/drivers/firmware/efi/libstub/zboot-header.S
@@ -4,17 +4,17 @@
#ifdef CONFIG_64BIT
.set .Lextra_characteristics, 0x0
- .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32PLUS
+ .set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC
#else
.set .Lextra_characteristics, IMAGE_FILE_32BIT_MACHINE
- .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32
+ .set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC
#endif
.section ".head", "a"
.globl __efistub_efi_zboot_header
__efistub_efi_zboot_header:
.Ldoshdr:
- .long MZ_MAGIC
+ .long IMAGE_DOS_SIGNATURE
.ascii "zimg" // image type
.long __efistub__gzdata_start - .Ldoshdr // payload offset
.long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size
@@ -25,7 +25,7 @@ __efistub_efi_zboot_header:
.long .Lpehdr - .Ldoshdr // PE header offset
.Lpehdr:
- .long PE_MAGIC
+ .long IMAGE_NT_SIGNATURE
.short MACHINE_TYPE
.short .Lsection_count
.long 0
@@ -63,7 +63,7 @@ __efistub_efi_zboot_header:
.long .Lefi_header_end - .Ldoshdr
.long 0
.short IMAGE_SUBSYSTEM_EFI_APPLICATION
- .short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
+ .short IMAGE_DLLCHARACTERISTICS_NX_COMPAT
#ifdef CONFIG_64BIT
.quad 0, 0, 0, 0
#else
@@ -123,11 +123,29 @@ __efistub_efi_zboot_header:
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_EXECUTE
+#ifdef CONFIG_EFI_SBAT
+ .ascii ".sbat\0\0\0"
+ .long __sbat_size
+ .long _sbat - .Ldoshdr
+ .long __sbat_size
+ .long _sbat - .Ldoshdr
+
+ .long 0, 0
+ .short 0, 0
+ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
+ IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_DISCARDABLE
+
+ .pushsection ".sbat", "a", @progbits
+ .incbin CONFIG_EFI_SBAT_FILE
+ .popsection
+#endif
+
.ascii ".data\0\0\0"
.long __data_size
- .long _etext - .Ldoshdr
+ .long _data - .Ldoshdr
.long __data_rawsize
- .long _etext - .Ldoshdr
+ .long _data - .Ldoshdr
.long 0, 0
.short 0, 0
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index af23b3c50228..c47ace06f010 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -7,36 +7,6 @@
#include "efistub.h"
-static unsigned char zboot_heap[SZ_256K] __aligned(64);
-static unsigned long free_mem_ptr, free_mem_end_ptr;
-
-#define STATIC static
-#if defined(CONFIG_KERNEL_GZIP)
-#include "../../../../lib/decompress_inflate.c"
-#elif defined(CONFIG_KERNEL_LZ4)
-#include "../../../../lib/decompress_unlz4.c"
-#elif defined(CONFIG_KERNEL_LZMA)
-#include "../../../../lib/decompress_unlzma.c"
-#elif defined(CONFIG_KERNEL_LZO)
-#include "../../../../lib/decompress_unlzo.c"
-#elif defined(CONFIG_KERNEL_XZ)
-#undef memcpy
-#define memcpy memcpy
-#undef memmove
-#define memmove memmove
-#include "../../../../lib/decompress_unxz.c"
-#elif defined(CONFIG_KERNEL_ZSTD)
-#include "../../../../lib/decompress_unzstd.c"
-#endif
-
-extern char efi_zboot_header[];
-extern char _gzdata_start[], _gzdata_end[];
-
-static void error(char *x)
-{
- efi_err("EFI decompressor: %s\n", x);
-}
-
static unsigned long alloc_preferred_address(unsigned long alloc_size)
{
#ifdef EFI_KIMG_PREFERRED_ADDRESS
@@ -64,22 +34,17 @@ struct screen_info *alloc_screen_info(void)
asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
{
- unsigned long compressed_size = _gzdata_end - _gzdata_start;
+ char *cmdline_ptr __free(efi_pool) = NULL;
unsigned long image_base, alloc_size;
efi_loaded_image_t *image;
efi_status_t status;
- char *cmdline_ptr;
- int ret;
WRITE_ONCE(efi_system_table, systab);
- free_mem_ptr = (unsigned long)&zboot_heap;
- free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
-
status = efi_bs_call(handle_protocol, handle,
&LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
if (status != EFI_SUCCESS) {
- error("Failed to locate parent's loaded image protocol");
+ efi_err("Failed to locate parent's loaded image protocol\n");
return status;
}
@@ -89,9 +54,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
efi_info("Decompressing Linux Kernel...\n");
- // SizeOfImage from the compressee's PE/COFF header
- alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
- EFI_ALLOC_ALIGN);
+ status = efi_zboot_decompress_init(&alloc_size);
+ if (status != EFI_SUCCESS)
+ return status;
// If the architecture has a preferred address for the image,
// try that first.
@@ -122,26 +87,14 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
if (status != EFI_SUCCESS) {
efi_err("Failed to allocate memory\n");
- goto free_cmdline;
+ return status;
}
}
- // Decompress the payload into the newly allocated buffer.
- ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
- (void *)image_base, alloc_size, NULL, error);
- if (ret < 0) {
- error("Decompression failed");
- status = EFI_DEVICE_ERROR;
- goto free_image;
- }
-
- efi_cache_sync_image(image_base, alloc_size);
-
- status = efi_stub_common(handle, image, image_base, cmdline_ptr);
+ // Decompress the payload into the newly allocated buffer
+ status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
+ efi_stub_common(handle, image, image_base, cmdline_ptr);
-free_image:
efi_free(alloc_size, image_base);
-free_cmdline:
- efi_bs_call(free_pool, cmdline_ptr);
return status;
}
diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds
index af2c82f7bd90..367907eb7d86 100644
--- a/drivers/firmware/efi/libstub/zboot.lds
+++ b/drivers/firmware/efi/libstub/zboot.lds
@@ -17,6 +17,7 @@ SECTIONS
.rodata : ALIGN(8) {
__efistub__gzdata_start = .;
*(.gzdata)
+ __efistub_payload_size = . - 4;
__efistub__gzdata_end = .;
*(.rodata* .init.rodata* .srodata*)
@@ -28,7 +29,15 @@ SECTIONS
. = _etext;
}
+ .sbat : ALIGN(4096) {
+ _sbat = .;
+ *(.sbat)
+ _esbat = ALIGN(4096);
+ . = _esbat;
+ }
+
.data : ALIGN(4096) {
+ _data = .;
*(.data* .init.data*)
_edata = ALIGN(512);
. = _edata;
@@ -49,5 +58,6 @@ SECTIONS
PROVIDE(__efistub__gzdata_size =
ABSOLUTE(__efistub__gzdata_end - __efistub__gzdata_start));
-PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext));
-PROVIDE(__data_size = ABSOLUTE(_end - _etext));
+PROVIDE(__data_rawsize = ABSOLUTE(_edata - _data));
+PROVIDE(__data_size = ABSOLUTE(_end - _data));
+PROVIDE(__sbat_size = ABSOLUTE(_esbat - _sbat));