Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'efi-next-for-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel:
"A bit more going on than usual in the EFI subsystem. The main driver
for this has been the introduction of the LoonArch architecture last
cycle, which inspired some cleanup and refactoring of the EFI code.
Another driver for EFI changes this cycle and in the future is
confidential compute.

The LoongArch architecture does not use either struct bootparams or DT
natively [yet], and so passing information between the EFI stub and
the core kernel using either of those is undesirable. And in general,
overloading DT has been a source of issues on arm64, so using DT for
this on new architectures is a to avoid for the time being (even if we
might converge on something DT based for non-x86 architectures in the
future). For this reason, in addition to the patch that enables EFI
boot for LoongArch, there are a number of refactoring patches applied
on top of which separate the DT bits from the generic EFI stub bits.
These changes are on a separate topich branch that has been shared
with the LoongArch maintainers, who will include it in their pull
request as well. This is not ideal, but the best way to manage the
conflicts without stalling LoongArch for another cycle.

Another development inspired by LoongArch is the newly added support
for EFI based decompressors. Instead of adding yet another
arch-specific incarnation of this pattern for LoongArch, we are
introducing an EFI app based on the existing EFI libstub
infrastructure that encapulates the decompression code we use on other
architectures, but in a way that is fully generic. This has been
developed and tested in collaboration with distro and systemd folks,
who are eager to start using this for systemd-boot and also for arm64
secure boot on Fedora. Note that the EFI zimage files this introduces
can also be decompressed by non-EFI bootloaders if needed, as the
image header describes the location of the payload inside the image,
and the type of compression that was used. (Note that Fedora's arm64
GRUB is buggy [0] so you'll need a recent version or switch to
systemd-boot in order to use this.)

Finally, we are adding TPM measurement of the kernel command line
provided by EFI. There is an oversight in the TCG spec which results
in a blind spot for command line arguments passed to loaded images,
which means that either the loader or the stub needs to take the
measurement. Given the combinatorial explosion I am anticipating when
it comes to firmware/bootloader stacks and firmware based attestation
protocols (SEV-SNP, TDX, DICE, DRTM), it is good to set a baseline now
when it comes to EFI measured boot, which is that the kernel measures
the initrd and command line. Intermediate loaders can measure
additional assets if needed, but with the baseline in place, we can
deploy measured boot in a meaningful way even if you boot into Linux
straight from the EFI firmware.

Summary:

- implement EFI boot support for LoongArch

- implement generic EFI compressed boot support for arm64, RISC-V and
LoongArch, none of which implement a decompressor today

- measure the kernel command line into the TPM if measured boot is in
effect

- refactor the EFI stub code in order to isolate DT dependencies for
architectures other than x86

- avoid calling SetVirtualAddressMap() on arm64 if the configured
size of the VA space guarantees that doing so is unnecessary

- move some ARM specific code out of the generic EFI source files

- unmap kernel code from the x86 mixed mode 1:1 page tables"

* tag 'efi-next-for-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: (24 commits)
efi/arm64: libstub: avoid SetVirtualAddressMap() when possible
efi: zboot: create MemoryMapped() device path for the parent if needed
efi: libstub: fix up the last remaining open coded boot service call
efi/arm: libstub: move ARM specific code out of generic routines
efi/libstub: measure EFI LoadOptions
efi/libstub: refactor the initrd measuring functions
efi/loongarch: libstub: remove dependency on flattened DT
efi: libstub: install boot-time memory map as config table
efi: libstub: remove DT dependency from generic stub
efi: libstub: unify initrd loading between architectures
efi: libstub: remove pointless goto kludge
efi: libstub: simplify efi_get_memory_map() and struct efi_boot_memmap
efi: libstub: avoid efi_get_memory_map() for allocating the virt map
efi: libstub: drop pointless get_memory_map() call
efi: libstub: fix type confusion for load_options_size
arm64: efi: enable generic EFI compressed boot
loongarch: efi: enable generic EFI compressed boot
riscv: efi: enable generic EFI compressed boot
efi/libstub: implement generic EFI zboot
efi/libstub: move efi_system_table global var into separate object
...

+1636 -561
-4
Documentation/arm/uefi.rst
··· 65 65 66 66 linux,uefi-mmap-desc-ver 32-bit Version of the mmap descriptor format. 67 67 68 - linux,initrd-start 64-bit Physical start address of an initrd 69 - 70 - linux,initrd-end 64-bit Physical end address of an initrd 71 - 72 68 kaslr-seed 64-bit Entropy used to randomize the kernel image 73 69 base address location. 74 70 ========================== ====== ===========================================
+2 -1
arch/arm/include/asm/efi.h
··· 17 17 18 18 #ifdef CONFIG_EFI 19 19 void efi_init(void); 20 + void arm_efi_init(void); 20 21 21 22 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); 22 23 int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); ··· 38 37 void efi_virtmap_unload(void); 39 38 40 39 #else 41 - #define efi_init() 40 + #define arm_efi_init() 42 41 #endif /* CONFIG_EFI */ 43 42 44 43 /* arch specific definitions used by the stub code */
+79
arch/arm/kernel/efi.c
··· 4 4 */ 5 5 6 6 #include <linux/efi.h> 7 + #include <linux/memblock.h> 7 8 #include <asm/efi.h> 8 9 #include <asm/mach/map.h> 9 10 #include <asm/mmu_context.h> ··· 73 72 if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP)) 74 73 return efi_set_mapping_permissions(mm, md); 75 74 return 0; 75 + } 76 + 77 + static unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR; 78 + static unsigned long __initdata cpu_state_table = EFI_INVALID_TABLE_ADDR; 79 + 80 + const efi_config_table_type_t efi_arch_tables[] __initconst = { 81 + {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table}, 82 + {LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table}, 83 + {} 84 + }; 85 + 86 + static void __init load_screen_info_table(void) 87 + { 88 + struct screen_info *si; 89 + 90 + if (screen_info_table != EFI_INVALID_TABLE_ADDR) { 91 + si = early_memremap_ro(screen_info_table, sizeof(*si)); 92 + if (!si) { 93 + pr_err("Could not map screen_info config table\n"); 94 + return; 95 + } 96 + screen_info = *si; 97 + early_memunmap(si, sizeof(*si)); 98 + 99 + /* dummycon on ARM needs non-zero values for columns/lines */ 100 + screen_info.orig_video_cols = 80; 101 + screen_info.orig_video_lines = 25; 102 + 103 + if (memblock_is_map_memory(screen_info.lfb_base)) 104 + memblock_mark_nomap(screen_info.lfb_base, 105 + screen_info.lfb_size); 106 + } 107 + } 108 + 109 + static void __init load_cpu_state_table(void) 110 + { 111 + if (cpu_state_table != EFI_INVALID_TABLE_ADDR) { 112 + struct efi_arm_entry_state *state; 113 + bool dump_state = true; 114 + 115 + state = early_memremap_ro(cpu_state_table, 116 + sizeof(struct efi_arm_entry_state)); 117 + if (state == NULL) { 118 + pr_warn("Unable to map CPU entry state table.\n"); 119 + return; 120 + } 121 + 122 + if ((state->sctlr_before_ebs & 1) == 0) 123 + pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n"); 124 + else if ((state->sctlr_after_ebs & 1) == 0) 125 + pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n"); 126 + else 127 + dump_state = false; 128 + 129 + if (dump_state || efi_enabled(EFI_DBG)) { 130 + pr_info("CPSR at EFI stub entry : 0x%08x\n", 131 + state->cpsr_before_ebs); 132 + pr_info("SCTLR at EFI stub entry : 0x%08x\n", 133 + state->sctlr_before_ebs); 134 + pr_info("CPSR after ExitBootServices() : 0x%08x\n", 135 + state->cpsr_after_ebs); 136 + pr_info("SCTLR after ExitBootServices(): 0x%08x\n", 137 + state->sctlr_after_ebs); 138 + } 139 + early_memunmap(state, sizeof(struct efi_arm_entry_state)); 140 + } 141 + } 142 + 143 + void __init arm_efi_init(void) 144 + { 145 + efi_init(); 146 + 147 + load_screen_info_table(); 148 + 149 + /* ARM does not permit early mappings to persist across paging_init() */ 150 + efi_memmap_unmap(); 151 + 152 + load_cpu_state_table(); 76 153 }
+1 -1
arch/arm/kernel/setup.c
··· 1141 1141 #endif 1142 1142 setup_dma_zone(mdesc); 1143 1143 xen_early_init(); 1144 - efi_init(); 1144 + arm_efi_init(); 1145 1145 /* 1146 1146 * Make sure the calculation for lowmem/highmem is set appropriately 1147 1147 * before reserving/allocating any memory
+7 -2
arch/arm64/Makefile
··· 151 151 152 152 # Default target when executing plain make 153 153 boot := arch/arm64/boot 154 + 155 + ifeq ($(CONFIG_EFI_ZBOOT),) 154 156 KBUILD_IMAGE := $(boot)/Image.gz 157 + else 158 + KBUILD_IMAGE := $(boot)/vmlinuz.efi 159 + endif 155 160 156 - all: Image.gz 161 + all: $(notdir $(KBUILD_IMAGE)) 157 162 158 163 159 - Image: vmlinux 164 + Image vmlinuz.efi: vmlinux 160 165 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ 161 166 162 167 Image.%: Image
+1
arch/arm64/boot/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 Image 3 3 Image.gz 4 + vmlinuz*
+6
arch/arm64/boot/Makefile
··· 38 38 39 39 $(obj)/Image.zst: $(obj)/Image FORCE 40 40 $(call if_changed,zstd) 41 + 42 + EFI_ZBOOT_PAYLOAD := Image 43 + EFI_ZBOOT_BFD_TARGET := elf64-littleaarch64 44 + EFI_ZBOOT_MACH_TYPE := ARM64 45 + 46 + include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
-13
arch/arm64/kernel/image-vars.h
··· 24 24 */ 25 25 PROVIDE(__efistub_memcmp = __pi_memcmp); 26 26 PROVIDE(__efistub_memchr = __pi_memchr); 27 - PROVIDE(__efistub_memcpy = __pi_memcpy); 28 - PROVIDE(__efistub_memmove = __pi_memmove); 29 - PROVIDE(__efistub_memset = __pi_memset); 30 27 PROVIDE(__efistub_strlen = __pi_strlen); 31 28 PROVIDE(__efistub_strnlen = __pi_strnlen); 32 29 PROVIDE(__efistub_strcmp = __pi_strcmp); ··· 36 39 PROVIDE(__efistub__edata = _edata); 37 40 PROVIDE(__efistub_screen_info = screen_info); 38 41 PROVIDE(__efistub__ctype = _ctype); 39 - 40 - /* 41 - * The __ prefixed memcpy/memset/memmove symbols are provided by KASAN, which 42 - * instruments the conventional ones. Therefore, any references from the EFI 43 - * stub or other position independent, low level C code should be redirected to 44 - * the non-instrumented versions as well. 45 - */ 46 - PROVIDE(__efistub___memcpy = __pi_memcpy); 47 - PROVIDE(__efistub___memmove = __pi_memmove); 48 - PROVIDE(__efistub___memset = __pi_memset); 49 42 50 43 PROVIDE(__pi___memcpy = __pi_memcpy); 51 44 PROVIDE(__pi___memmove = __pi_memmove);
+9 -3
arch/loongarch/Kconfig
··· 105 105 select MODULES_USE_ELF_RELA if MODULES 106 106 select NEED_PER_CPU_EMBED_FIRST_CHUNK 107 107 select NEED_PER_CPU_PAGE_FIRST_CHUNK 108 - select OF 109 - select OF_EARLY_FLATTREE 110 108 select PCI 111 109 select PCI_DOMAINS_GENERIC 112 110 select PCI_ECAM if ACPI ··· 311 313 config EFI 312 314 bool "EFI runtime service support" 313 315 select UCS2_STRING 314 - select EFI_PARAMS_FROM_FDT 315 316 select EFI_RUNTIME_WRAPPERS 316 317 help 317 318 This enables the kernel to use EFI runtime services that are 318 319 available (such as the EFI variable services). 320 + 321 + config EFI_STUB 322 + bool "EFI boot stub support" 323 + default y 324 + depends on EFI 325 + select EFI_GENERIC_STUB 326 + help 327 + This kernel feature allows the kernel to be loaded directly by 328 + EFI firmware without the use of a bootloader. 319 329 320 330 config SMP 321 331 bool "Multi-Processing support"
+13 -5
arch/loongarch/Makefile
··· 7 7 8 8 KBUILD_DEFCONFIG := loongson3_defconfig 9 9 10 - KBUILD_IMAGE = $(boot)/vmlinux 10 + image-name-y := vmlinux 11 + image-name-$(CONFIG_EFI_ZBOOT) := vmlinuz 12 + 13 + ifndef CONFIG_EFI_STUB 14 + KBUILD_IMAGE := $(boot)/vmlinux.elf 15 + else 16 + KBUILD_IMAGE := $(boot)/$(image-name-y).efi 17 + endif 11 18 12 19 # 13 20 # Select the object file format to substitute into the linker script. ··· 82 75 head-y := arch/loongarch/kernel/head.o 83 76 84 77 libs-y += arch/loongarch/lib/ 78 + libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a 85 79 86 80 ifeq ($(KBUILD_EXTMOD),) 87 81 prepare: vdso_prepare ··· 94 86 vdso_install: 95 87 $(Q)$(MAKE) $(build)=arch/loongarch/vdso $@ 96 88 97 - all: $(KBUILD_IMAGE) 89 + all: $(notdir $(KBUILD_IMAGE)) 98 90 99 - $(KBUILD_IMAGE): vmlinux 100 - $(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $@ 91 + vmlinux.elf vmlinux.efi vmlinuz.efi: vmlinux 92 + $(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@ 101 93 102 94 install: 103 - $(Q)install -D -m 755 $(KBUILD_IMAGE) $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE) 95 + $(Q)install -D -m 755 $(KBUILD_IMAGE) $(INSTALL_PATH)/$(image-name-y)-$(KERNELRELEASE) 104 96 $(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE) 105 97 $(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE) 106 98
+1
arch/loongarch/boot/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 vmlinux* 3 + vmlinuz*
+12 -2
arch/loongarch/boot/Makefile
··· 8 8 strip-flags := $(addprefix --remove-section=,$(drop-sections)) -S 9 9 OBJCOPYFLAGS_vmlinux.efi := -O binary $(strip-flags) 10 10 11 - targets := vmlinux 12 11 quiet_cmd_strip = STRIP $@ 13 12 cmd_strip = $(STRIP) -s -o $@ $< 14 13 15 - $(obj)/vmlinux: vmlinux FORCE 14 + targets := vmlinux.elf 15 + $(obj)/vmlinux.elf: vmlinux FORCE 16 16 $(call if_changed,strip) 17 + 18 + targets += vmlinux.efi 19 + $(obj)/vmlinux.efi: vmlinux FORCE 20 + $(call if_changed,objcopy) 21 + 22 + EFI_ZBOOT_PAYLOAD := vmlinux.efi 23 + EFI_ZBOOT_BFD_TARGET := elf64-loongarch 24 + EFI_ZBOOT_MACH_TYPE := LOONGARCH64 25 + 26 + include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
+1 -1
arch/loongarch/include/asm/bootinfo.h
··· 36 36 }; 37 37 38 38 extern u64 efi_system_table; 39 - extern unsigned long fw_arg0, fw_arg1; 39 + extern unsigned long fw_arg0, fw_arg1, fw_arg2; 40 40 extern struct loongson_board_info b_info; 41 41 extern struct loongson_system_configuration loongson_sysconf; 42 42
+9 -2
arch/loongarch/include/asm/efi.h
··· 17 17 #define arch_efi_call_virt_teardown() 18 18 19 19 #define EFI_ALLOC_ALIGN SZ_64K 20 + #define EFI_RT_VIRTUAL_OFFSET CSR_DMW0_BASE 20 21 21 - struct screen_info *alloc_screen_info(void); 22 - void free_screen_info(struct screen_info *si); 22 + static inline struct screen_info *alloc_screen_info(void) 23 + { 24 + return &screen_info; 25 + } 26 + 27 + static inline void free_screen_info(struct screen_info *si) 28 + { 29 + } 23 30 24 31 static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr) 25 32 {
+99
arch/loongarch/kernel/efi-header.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 + */ 5 + 6 + #include <linux/pe.h> 7 + #include <linux/sizes.h> 8 + 9 + .macro __EFI_PE_HEADER 10 + .long PE_MAGIC 11 + .Lcoff_header: 12 + .short IMAGE_FILE_MACHINE_LOONGARCH64 /* Machine */ 13 + .short .Lsection_count /* NumberOfSections */ 14 + .long 0 /* TimeDateStamp */ 15 + .long 0 /* PointerToSymbolTable */ 16 + .long 0 /* NumberOfSymbols */ 17 + .short .Lsection_table - .Loptional_header /* SizeOfOptionalHeader */ 18 + .short IMAGE_FILE_DEBUG_STRIPPED | \ 19 + IMAGE_FILE_EXECUTABLE_IMAGE | \ 20 + IMAGE_FILE_LINE_NUMS_STRIPPED /* Characteristics */ 21 + 22 + .Loptional_header: 23 + .short PE_OPT_MAGIC_PE32PLUS /* PE32+ format */ 24 + .byte 0x02 /* MajorLinkerVersion */ 25 + .byte 0x14 /* MinorLinkerVersion */ 26 + .long __inittext_end - .Lefi_header_end /* SizeOfCode */ 27 + .long _end - __initdata_begin /* SizeOfInitializedData */ 28 + .long 0 /* SizeOfUninitializedData */ 29 + .long __efistub_efi_pe_entry - _head /* AddressOfEntryPoint */ 30 + .long .Lefi_header_end - _head /* BaseOfCode */ 31 + 32 + .Lextra_header_fields: 33 + .quad 0 /* ImageBase */ 34 + .long PECOFF_SEGMENT_ALIGN /* SectionAlignment */ 35 + .long PECOFF_FILE_ALIGN /* FileAlignment */ 36 + .short 0 /* MajorOperatingSystemVersion */ 37 + .short 0 /* MinorOperatingSystemVersion */ 38 + .short LINUX_EFISTUB_MAJOR_VERSION /* MajorImageVersion */ 39 + .short LINUX_EFISTUB_MINOR_VERSION /* MinorImageVersion */ 40 + .short 0 /* MajorSubsystemVersion */ 41 + .short 0 /* MinorSubsystemVersion */ 42 + .long 0 /* Win32VersionValue */ 43 + 44 + .long _end - _head /* SizeOfImage */ 45 + 46 + /* Everything before the kernel image is considered part of the header */ 47 + .long .Lefi_header_end - _head /* SizeOfHeaders */ 48 + .long 0 /* CheckSum */ 49 + .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ 50 + .short 0 /* DllCharacteristics */ 51 + .quad 0 /* SizeOfStackReserve */ 52 + .quad 0 /* SizeOfStackCommit */ 53 + .quad 0 /* SizeOfHeapReserve */ 54 + .quad 0 /* SizeOfHeapCommit */ 55 + .long 0 /* LoaderFlags */ 56 + .long (.Lsection_table - .) / 8 /* NumberOfRvaAndSizes */ 57 + 58 + .quad 0 /* ExportTable */ 59 + .quad 0 /* ImportTable */ 60 + .quad 0 /* ResourceTable */ 61 + .quad 0 /* ExceptionTable */ 62 + .quad 0 /* CertificationTable */ 63 + .quad 0 /* BaseRelocationTable */ 64 + 65 + /* Section table */ 66 + .Lsection_table: 67 + .ascii ".text\0\0\0" 68 + .long __inittext_end - .Lefi_header_end /* VirtualSize */ 69 + .long .Lefi_header_end - _head /* VirtualAddress */ 70 + .long __inittext_end - .Lefi_header_end /* SizeOfRawData */ 71 + .long .Lefi_header_end - _head /* PointerToRawData */ 72 + 73 + .long 0 /* PointerToRelocations */ 74 + .long 0 /* PointerToLineNumbers */ 75 + .short 0 /* NumberOfRelocations */ 76 + .short 0 /* NumberOfLineNumbers */ 77 + .long IMAGE_SCN_CNT_CODE | \ 78 + IMAGE_SCN_MEM_READ | \ 79 + IMAGE_SCN_MEM_EXECUTE /* Characteristics */ 80 + 81 + .ascii ".data\0\0\0" 82 + .long _end - __initdata_begin /* VirtualSize */ 83 + .long __initdata_begin - _head /* VirtualAddress */ 84 + .long _edata - __initdata_begin /* SizeOfRawData */ 85 + .long __initdata_begin - _head /* PointerToRawData */ 86 + 87 + .long 0 /* PointerToRelocations */ 88 + .long 0 /* PointerToLineNumbers */ 89 + .short 0 /* NumberOfRelocations */ 90 + .short 0 /* NumberOfLineNumbers */ 91 + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 92 + IMAGE_SCN_MEM_READ | \ 93 + IMAGE_SCN_MEM_WRITE /* Characteristics */ 94 + 95 + .set .Lsection_count, (. - .Lsection_table) / 40 96 + 97 + .balign 0x10000 /* PECOFF_SEGMENT_ALIGN */ 98 + .Lefi_header_end: 99 + .endm
+32 -1
arch/loongarch/kernel/efi.c
··· 27 27 static unsigned long efi_nr_tables; 28 28 static unsigned long efi_config_table; 29 29 30 + static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR; 31 + 30 32 static efi_system_table_t *efi_systab; 31 - static efi_config_table_type_t arch_tables[] __initdata = {{},}; 33 + static efi_config_table_type_t arch_tables[] __initdata = { 34 + {LINUX_EFI_BOOT_MEMMAP_GUID, &boot_memmap, "MEMMAP" }, 35 + {}, 36 + }; 32 37 33 38 void __init efi_runtime_init(void) 34 39 { ··· 56 51 { 57 52 int size; 58 53 void *config_tables; 54 + struct efi_boot_memmap *tbl; 59 55 60 56 if (!efi_system_table) 61 57 return; ··· 67 61 return; 68 62 } 69 63 64 + efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor); 65 + 70 66 set_bit(EFI_64BIT, &efi.flags); 71 67 efi_nr_tables = efi_systab->nr_tables; 72 68 efi_config_table = (unsigned long)efi_systab->tables; ··· 77 69 config_tables = early_memremap(efi_config_table, efi_nr_tables * size); 78 70 efi_config_parse_tables(config_tables, efi_systab->nr_tables, arch_tables); 79 71 early_memunmap(config_tables, efi_nr_tables * size); 72 + 73 + set_bit(EFI_CONFIG_TABLES, &efi.flags); 74 + 75 + if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) 76 + memblock_reserve(screen_info.lfb_base, screen_info.lfb_size); 77 + 78 + if (boot_memmap == EFI_INVALID_TABLE_ADDR) 79 + return; 80 + 81 + tbl = early_memremap_ro(boot_memmap, sizeof(*tbl)); 82 + if (tbl) { 83 + struct efi_memory_map_data data; 84 + 85 + data.phys_map = boot_memmap + sizeof(*tbl); 86 + data.size = tbl->map_size; 87 + data.desc_size = tbl->desc_size; 88 + data.desc_version = tbl->desc_ver; 89 + 90 + if (efi_memmap_init_early(&data) < 0) 91 + panic("Unable to map EFI memory map.\n"); 92 + 93 + early_memunmap(tbl, sizeof(*tbl)); 94 + } 80 95 }
+4 -9
arch/loongarch/kernel/env.c
··· 8 8 #include <linux/efi.h> 9 9 #include <linux/export.h> 10 10 #include <linux/memblock.h> 11 - #include <linux/of_fdt.h> 12 11 #include <asm/early_ioremap.h> 13 12 #include <asm/bootinfo.h> 14 13 #include <asm/loongson.h> ··· 19 20 void __init init_environ(void) 20 21 { 21 22 int efi_boot = fw_arg0; 22 - struct efi_memory_map_data data; 23 - void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); 23 + char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE); 24 24 25 25 if (efi_boot) 26 26 set_bit(EFI_BOOT, &efi.flags); 27 27 else 28 28 clear_bit(EFI_BOOT, &efi.flags); 29 29 30 - early_init_dt_scan(fdt_ptr); 31 - early_init_fdt_reserve_self(); 32 - efi_system_table = efi_get_fdt_params(&data); 30 + strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE); 31 + early_memunmap(cmdline, COMMAND_LINE_SIZE); 33 32 34 - efi_memmap_init_early(&data); 35 - memblock_reserve(data.phys_map & PAGE_MASK, 36 - PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK))); 33 + efi_system_table = fw_arg2; 37 34 } 38 35 39 36 static int __init init_cpu_fullname(void)
+22
arch/loongarch/kernel/head.S
··· 12 12 #include <asm/loongarch.h> 13 13 #include <asm/stackframe.h> 14 14 15 + #ifdef CONFIG_EFI_STUB 16 + 17 + #include "efi-header.S" 18 + 19 + __HEAD 20 + 21 + _head: 22 + .word MZ_MAGIC /* "MZ", MS-DOS header */ 23 + .org 0x3c /* 0x04 ~ 0x3b reserved */ 24 + .long pe_header - _head /* Offset to the PE header */ 25 + 26 + pe_header: 27 + __EFI_PE_HEADER 28 + 29 + SYM_DATA(kernel_asize, .long _end - _text); 30 + SYM_DATA(kernel_fsize, .long _edata - _text); 31 + SYM_DATA(kernel_offset, .long kernel_offset - _text); 32 + 33 + #endif 34 + 15 35 __REF 16 36 17 37 .align 12 ··· 69 49 st.d a0, t0, 0 # firmware arguments 70 50 la t0, fw_arg1 71 51 st.d a1, t0, 0 52 + la t0, fw_arg2 53 + st.d a2, t0, 0 72 54 73 55 /* KSave3 used for percpu base, initialized as 0 */ 74 56 csrwr zero, PERCPU_BASE_KS
+27
arch/loongarch/kernel/image-vars.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 + */ 5 + #ifndef __LOONGARCH_KERNEL_IMAGE_VARS_H 6 + #define __LOONGARCH_KERNEL_IMAGE_VARS_H 7 + 8 + #ifdef CONFIG_EFI_STUB 9 + 10 + __efistub_memcmp = memcmp; 11 + __efistub_memchr = memchr; 12 + __efistub_strcat = strcat; 13 + __efistub_strcmp = strcmp; 14 + __efistub_strlen = strlen; 15 + __efistub_strncat = strncat; 16 + __efistub_strnstr = strnstr; 17 + __efistub_strnlen = strnlen; 18 + __efistub_strrchr = strrchr; 19 + __efistub_kernel_entry = kernel_entry; 20 + __efistub_kernel_asize = kernel_asize; 21 + __efistub_kernel_fsize = kernel_fsize; 22 + __efistub_kernel_offset = kernel_offset; 23 + __efistub_screen_info = screen_info; 24 + 25 + #endif 26 + 27 + #endif /* __LOONGARCH_KERNEL_IMAGE_VARS_H */
+3 -12
arch/loongarch/kernel/setup.c
··· 49 49 #define SMBIOS_CORE_PACKAGE_OFFSET 0x23 50 50 #define LOONGSON_EFI_ENABLE (1 << 3) 51 51 52 - #ifdef CONFIG_VT 53 - struct screen_info screen_info; 54 - #endif 52 + struct screen_info screen_info __section(".data"); 55 53 56 - unsigned long fw_arg0, fw_arg1; 54 + unsigned long fw_arg0, fw_arg1, fw_arg2; 57 55 DEFINE_PER_CPU(unsigned long, kernelsp); 58 56 struct cpuinfo_loongarch cpu_data[NR_CPUS] __read_mostly; 59 57 ··· 120 122 121 123 static void __init parse_bios_table(const struct dmi_header *dm) 122 124 { 123 - int bios_extern; 124 125 char *dmi_data = (char *)dm; 125 126 126 - bios_extern = *(dmi_data + SMBIOS_BIOSEXTERN_OFFSET); 127 127 b_info.bios_size = (*(dmi_data + SMBIOS_BIOSSIZE_OFFSET) + 1) << 6; 128 - 129 - if (bios_extern & LOONGSON_EFI_ENABLE) 130 - set_bit(EFI_BOOT, &efi.flags); 131 - else 132 - clear_bit(EFI_BOOT, &efi.flags); 133 128 } 134 129 135 130 static void __init find_tokens(const struct dmi_header *dm, void *dummy) ··· 187 196 188 197 void __init platform_init(void) 189 198 { 190 - efi_init(); 191 199 #ifdef CONFIG_ACPI_TABLE_UPGRADE 192 200 acpi_table_upgrade(); 193 201 #endif ··· 346 356 *cmdline_p = boot_command_line; 347 357 348 358 init_environ(); 359 + efi_init(); 349 360 memblock_init(); 350 361 parse_early_param(); 351 362
+1
arch/loongarch/kernel/vmlinux.lds.S
··· 12 12 #define BSS_FIRST_SECTIONS *(.bss..swapper_pg_dir) 13 13 14 14 #include <asm-generic/vmlinux.lds.h> 15 + #include "image-vars.h" 15 16 16 17 /* 17 18 * Max avaliable Page Size is 64K, so we set SectionAlignment
+5 -1
arch/riscv/Makefile
··· 136 136 ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy) 137 137 KBUILD_IMAGE := $(boot)/loader.bin 138 138 else 139 + ifeq ($(CONFIG_EFI_ZBOOT),) 139 140 KBUILD_IMAGE := $(boot)/Image.gz 141 + else 142 + KBUILD_IMAGE := $(boot)/vmlinuz.efi 140 143 endif 141 144 endif 142 - BOOT_TARGETS := Image Image.gz loader loader.bin xipImage 145 + endif 146 + BOOT_TARGETS := Image Image.gz loader loader.bin xipImage vmlinuz.efi 143 147 144 148 all: $(notdir $(KBUILD_IMAGE)) 145 149
+1
arch/riscv/boot/.gitignore
··· 4 4 loader 5 5 loader.lds 6 6 loader.bin 7 + vmlinuz* 7 8 xipImage
+6
arch/riscv/boot/Makefile
··· 58 58 59 59 $(obj)/loader.bin: $(obj)/loader FORCE 60 60 $(call if_changed,objcopy) 61 + 62 + EFI_ZBOOT_PAYLOAD := Image 63 + EFI_ZBOOT_BFD_TARGET := elf$(BITS)-littleriscv 64 + EFI_ZBOOT_MACH_TYPE := RISCV$(BITS) 65 + 66 + include $(srctree)/drivers/firmware/efi/libstub/Makefile.zboot
-9
arch/riscv/kernel/image-vars.h
··· 25 25 */ 26 26 __efistub_memcmp = memcmp; 27 27 __efistub_memchr = memchr; 28 - __efistub_memcpy = memcpy; 29 - __efistub_memmove = memmove; 30 - __efistub_memset = memset; 31 28 __efistub_strlen = strlen; 32 29 __efistub_strnlen = strnlen; 33 30 __efistub_strcmp = strcmp; 34 31 __efistub_strncmp = strncmp; 35 32 __efistub_strrchr = strrchr; 36 - 37 - #ifdef CONFIG_KASAN 38 - __efistub___memcpy = memcpy; 39 - __efistub___memmove = memmove; 40 - __efistub___memset = memset; 41 - #endif 42 33 43 34 __efistub__start = _start; 44 35 __efistub__start_kernel = _start_kernel;
+13 -5
arch/x86/platform/efi/efi_64.c
··· 176 176 177 177 int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) 178 178 { 179 - unsigned long pfn, text, pf, rodata; 179 + extern const u8 __efi64_thunk_ret_tramp[]; 180 + unsigned long pfn, text, pf, rodata, tramp; 180 181 struct page *page; 181 182 unsigned npages; 182 183 pgd_t *pgd = efi_mm.pgd; ··· 239 238 240 239 npages = (_etext - _text) >> PAGE_SHIFT; 241 240 text = __pa(_text); 242 - pfn = text >> PAGE_SHIFT; 243 241 244 - pf = _PAGE_ENC; 245 - if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, pf)) { 246 - pr_err("Failed to map kernel text 1:1\n"); 242 + if (kernel_unmap_pages_in_pgd(pgd, text, npages)) { 243 + pr_err("Failed to unmap kernel text 1:1 mapping\n"); 247 244 return 1; 248 245 } 249 246 ··· 252 253 pf = _PAGE_NX | _PAGE_ENC; 253 254 if (kernel_map_pages_in_pgd(pgd, pfn, rodata, npages, pf)) { 254 255 pr_err("Failed to map kernel rodata 1:1\n"); 256 + return 1; 257 + } 258 + 259 + tramp = __pa(__efi64_thunk_ret_tramp); 260 + pfn = tramp >> PAGE_SHIFT; 261 + 262 + pf = _PAGE_ENC; 263 + if (kernel_map_pages_in_pgd(pgd, pfn, tramp, 1, pf)) { 264 + pr_err("Failed to map mixed mode return trampoline\n"); 255 265 return 1; 256 266 } 257 267
+10 -3
arch/x86/platform/efi/efi_thunk_64.S
··· 23 23 #include <linux/objtool.h> 24 24 #include <asm/page_types.h> 25 25 #include <asm/segment.h> 26 - #include <asm/nospec-branch.h> 27 26 28 27 .text 29 28 .code64 ··· 72 73 pushq %rdi /* EFI runtime service address */ 73 74 lretq 74 75 76 + // This return instruction is not needed for correctness, as it will 77 + // never be reached. It only exists to make objtool happy, which will 78 + // otherwise complain about unreachable instructions in the callers. 79 + RET 80 + SYM_FUNC_END(__efi64_thunk) 81 + 82 + .section ".rodata", "a", @progbits 83 + .balign 16 84 + SYM_DATA_START(__efi64_thunk_ret_tramp) 75 85 1: movq 0x20(%rsp), %rsp 76 86 pop %rbx 77 87 pop %rbp 78 - ANNOTATE_UNRET_SAFE 79 88 ret 80 89 int3 81 90 ··· 91 84 2: pushl $__KERNEL_CS 92 85 pushl %ebp 93 86 lret 94 - SYM_FUNC_END(__efi64_thunk) 87 + SYM_DATA_END(__efi64_thunk_ret_tramp) 95 88 96 89 .bss 97 90 .balign 8
+43 -2
drivers/firmware/efi/Kconfig
··· 105 105 config EFI_GENERIC_STUB 106 106 bool 107 107 108 + config EFI_ZBOOT 109 + bool "Enable the generic EFI decompressor" 110 + depends on EFI_GENERIC_STUB && !ARM 111 + select HAVE_KERNEL_GZIP 112 + select HAVE_KERNEL_LZ4 113 + select HAVE_KERNEL_LZMA 114 + select HAVE_KERNEL_LZO 115 + select HAVE_KERNEL_XZ 116 + select HAVE_KERNEL_ZSTD 117 + help 118 + Create the bootable image as an EFI application that carries the 119 + actual kernel image in compressed form, and decompresses it into 120 + memory before executing it via LoadImage/StartImage EFI boot service 121 + calls. For compatibility with non-EFI loaders, the payload can be 122 + decompressed and executed by the loader as well, provided that the 123 + loader implements the decompression algorithm and that non-EFI boot 124 + is supported by the encapsulated image. (The compression algorithm 125 + used is described in the zboot image header) 126 + 127 + config EFI_ZBOOT_SIGNED 128 + def_bool y 129 + depends on EFI_ZBOOT_SIGNING_CERT != "" 130 + depends on EFI_ZBOOT_SIGNING_KEY != "" 131 + 132 + config EFI_ZBOOT_SIGNING 133 + bool "Sign the EFI decompressor for UEFI secure boot" 134 + depends on EFI_ZBOOT 135 + help 136 + Use the 'sbsign' command line tool (which must exist on the host 137 + path) to sign both the EFI decompressor PE/COFF image, as well as the 138 + encapsulated PE/COFF image, which is subsequently compressed and 139 + wrapped by the former image. 140 + 141 + config EFI_ZBOOT_SIGNING_CERT 142 + string "Certificate to use for signing the compressed EFI boot image" 143 + depends on EFI_ZBOOT_SIGNING 144 + 145 + config EFI_ZBOOT_SIGNING_KEY 146 + string "Private key to use for signing the compressed EFI boot image" 147 + depends on EFI_ZBOOT_SIGNING 148 + 108 149 config EFI_ARMSTUB_DTB_LOADER 109 150 bool "Enable the DTB loader" 110 - depends on EFI_GENERIC_STUB && !RISCV 151 + depends on EFI_GENERIC_STUB && !RISCV && !LOONGARCH 111 152 default y 112 153 help 113 154 Select this config option to add support for the dtb= command ··· 165 124 bool "Enable the command line initrd loader" if !X86 166 125 depends on EFI_STUB && (EFI_GENERIC_STUB || X86) 167 126 default y if X86 168 - depends on !RISCV 127 + depends on !RISCV && !LOONGARCH 169 128 help 170 129 Select this config option to add support for the initrd= command 171 130 line parameter, allowing an initrd that resides on the same volume
+2 -59
drivers/firmware/efi/efi-init.c
··· 51 51 return addr; 52 52 } 53 53 54 - static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR; 55 - static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR; 56 - 57 - static const efi_config_table_type_t arch_tables[] __initconst = { 58 - {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table}, 59 - {LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table}, 60 - {} 61 - }; 54 + extern __weak const efi_config_table_type_t efi_arch_tables[]; 62 55 63 56 static void __init init_screen_info(void) 64 57 { 65 - struct screen_info *si; 66 - 67 - if (IS_ENABLED(CONFIG_ARM) && 68 - screen_info_table != EFI_INVALID_TABLE_ADDR) { 69 - si = early_memremap_ro(screen_info_table, sizeof(*si)); 70 - if (!si) { 71 - pr_err("Could not map screen_info config table\n"); 72 - return; 73 - } 74 - screen_info = *si; 75 - early_memunmap(si, sizeof(*si)); 76 - 77 - /* dummycon on ARM needs non-zero values for columns/lines */ 78 - screen_info.orig_video_cols = 80; 79 - screen_info.orig_video_lines = 25; 80 - } 81 - 82 58 if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && 83 59 memblock_is_map_memory(screen_info.lfb_base)) 84 60 memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size); ··· 95 119 goto out; 96 120 } 97 121 retval = efi_config_parse_tables(config_tables, systab->nr_tables, 98 - IS_ENABLED(CONFIG_ARM) ? arch_tables 99 - : NULL); 122 + efi_arch_tables); 100 123 101 124 early_memunmap(config_tables, table_size); 102 125 out: ··· 223 248 PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK))); 224 249 225 250 init_screen_info(); 226 - 227 - #ifdef CONFIG_ARM 228 - /* ARM does not permit early mappings to persist across paging_init() */ 229 - efi_memmap_unmap(); 230 - 231 - if (cpu_state_table != EFI_INVALID_TABLE_ADDR) { 232 - struct efi_arm_entry_state *state; 233 - bool dump_state = true; 234 - 235 - state = early_memremap_ro(cpu_state_table, 236 - sizeof(struct efi_arm_entry_state)); 237 - if (state == NULL) { 238 - pr_warn("Unable to map CPU entry state table.\n"); 239 - return; 240 - } 241 - 242 - if ((state->sctlr_before_ebs & 1) == 0) 243 - pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n"); 244 - else if ((state->sctlr_after_ebs & 1) == 0) 245 - pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n"); 246 - else 247 - dump_state = false; 248 - 249 - if (dump_state || efi_enabled(EFI_DBG)) { 250 - pr_info("CPSR at EFI stub entry : 0x%08x\n", state->cpsr_before_ebs); 251 - pr_info("SCTLR at EFI stub entry : 0x%08x\n", state->sctlr_before_ebs); 252 - pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs); 253 - pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs); 254 - } 255 - early_memunmap(state, sizeof(struct efi_arm_entry_state)); 256 - } 257 - #endif 258 251 }
+15
drivers/firmware/efi/efi.c
··· 21 21 #include <linux/device.h> 22 22 #include <linux/efi.h> 23 23 #include <linux/of.h> 24 + #include <linux/initrd.h> 24 25 #include <linux/io.h> 25 26 #include <linux/kexec.h> 26 27 #include <linux/platform_device.h> ··· 56 55 unsigned long __ro_after_init efi_rng_seed = EFI_INVALID_TABLE_ADDR; 57 56 static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR; 58 57 static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR; 58 + static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR; 59 59 60 60 struct mm_struct efi_mm = { 61 61 .mm_rb = RB_ROOT, ··· 534 532 {LINUX_EFI_TPM_EVENT_LOG_GUID, &efi.tpm_log, "TPMEventLog" }, 535 533 {LINUX_EFI_TPM_FINAL_LOG_GUID, &efi.tpm_final_log, "TPMFinalLog" }, 536 534 {LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" }, 535 + {LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" }, 537 536 {EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" }, 538 537 #ifdef CONFIG_EFI_RCI2_TABLE 539 538 {DELLEMC_EFI_RCI2_TABLE_GUID, &rci2_table_phys }, ··· 673 670 tbl = early_memremap(rt_prop, sizeof(*tbl)); 674 671 if (tbl) { 675 672 efi.runtime_supported_mask &= tbl->runtime_services_supported; 673 + early_memunmap(tbl, sizeof(*tbl)); 674 + } 675 + } 676 + 677 + if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && 678 + initrd != EFI_INVALID_TABLE_ADDR && phys_initrd_size == 0) { 679 + struct linux_efi_initrd *tbl; 680 + 681 + tbl = early_memremap(initrd, sizeof(*tbl)); 682 + if (tbl) { 683 + phys_initrd_start = tbl->base; 684 + phys_initrd_size = tbl->size; 676 685 early_memunmap(tbl, sizeof(*tbl)); 677 686 } 678 687 }
+24 -8
drivers/firmware/efi/libstub/Makefile
··· 26 26 $(call cc-option,-mno-single-pic-base) 27 27 cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ 28 28 -fpic 29 + cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ 30 + -fpie 29 31 30 - cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt 32 + cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt 31 33 32 34 KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ 33 35 -include $(srctree)/include/linux/hidden.h \ ··· 68 66 skip_spaces.o lib-cmdline.o lib-ctype.o \ 69 67 alignedmem.o relocate.o vsprintf.o 70 68 71 - # include the stub's generic dependencies from lib/ when building for ARM/arm64 72 - efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c 69 + # include the stub's libfdt dependencies from lib/ when needed 70 + libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \ 71 + fdt_empty_tree.c fdt_sw.c 72 + 73 + lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \ 74 + $(patsubst %.c,lib-%.o,$(libfdt-deps)) 73 75 74 76 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE 75 77 $(call if_changed_rule,cc_o_c) 76 78 77 - lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o \ 78 - $(patsubst %.c,lib-%.o,$(efi-deps-y)) 79 + lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o 79 80 80 81 lib-$(CONFIG_ARM) += arm32-stub.o 81 82 lib-$(CONFIG_ARM64) += arm64-stub.o 82 83 lib-$(CONFIG_X86) += x86-stub.o 83 84 lib-$(CONFIG_RISCV) += riscv-stub.o 85 + lib-$(CONFIG_LOONGARCH) += loongarch-stub.o 86 + 84 87 CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) 88 + 89 + zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o 90 + lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y) 91 + 92 + extra-y := $(lib-y) 93 + lib-y := $(patsubst %.o,%.stub.o,$(lib-y)) 85 94 86 95 # Even when -mbranch-protection=none is set, Clang will generate a 87 96 # .note.gnu.property for code-less object files (like lib/ctype.c), ··· 133 120 # a verification pass to see if any absolute relocations exist in any of the 134 121 # object files. 135 122 # 136 - extra-y := $(lib-y) 137 - lib-y := $(patsubst %.o,%.stub.o,$(lib-y)) 138 - 139 123 STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ 140 124 --prefix-symbols=__efistub_ 141 125 STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS ··· 143 133 STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \ 144 134 --prefix-symbols=__efistub_ 145 135 STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20 136 + 137 + # For LoongArch, keep all the symbols in .init section and make sure that no 138 + # absolute symbols references exist. 139 + STUBCOPY_FLAGS-$(CONFIG_LOONGARCH) += --prefix-alloc-sections=.init \ 140 + --prefix-symbols=__efistub_ 141 + STUBCOPY_RELOC-$(CONFIG_LOONGARCH) := R_LARCH_MARK_LA 146 142 147 143 $(obj)/%.stub.o: $(obj)/%.o FORCE 148 144 $(call if_changed,stubcopy)
+70
drivers/firmware/efi/libstub/Makefile.zboot
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + # to be include'd by arch/$(ARCH)/boot/Makefile after setting 4 + # EFI_ZBOOT_PAYLOAD, EFI_ZBOOT_BFD_TARGET and EFI_ZBOOT_MACH_TYPE 5 + 6 + comp-type-$(CONFIG_KERNEL_GZIP) := gzip 7 + comp-type-$(CONFIG_KERNEL_LZ4) := lz4 8 + comp-type-$(CONFIG_KERNEL_LZMA) := lzma 9 + comp-type-$(CONFIG_KERNEL_LZO) := lzo 10 + comp-type-$(CONFIG_KERNEL_XZ) := xzkern 11 + comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22 12 + 13 + # in GZIP, the appended le32 carrying the uncompressed size is part of the 14 + # format, but in other cases, we just append it at the end for convenience, 15 + # causing the original tools to complain when checking image integrity. 16 + # So disregard it when calculating the payload size in the zimage header. 17 + zboot-method-y := $(comp-type-y)_with_size 18 + zboot-size-len-y := 4 19 + 20 + zboot-method-$(CONFIG_KERNEL_GZIP) := gzip 21 + zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0 22 + 23 + quiet_cmd_sbsign = SBSIGN $@ 24 + cmd_sbsign = sbsign --out $@ $< \ 25 + --key $(CONFIG_EFI_ZBOOT_SIGNING_KEY) \ 26 + --cert $(CONFIG_EFI_ZBOOT_SIGNING_CERT) 27 + 28 + $(obj)/$(EFI_ZBOOT_PAYLOAD).signed: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE 29 + $(call if_changed,sbsign) 30 + 31 + ZBOOT_PAYLOAD-y := $(EFI_ZBOOT_PAYLOAD) 32 + ZBOOT_PAYLOAD-$(CONFIG_EFI_ZBOOT_SIGNED) := $(EFI_ZBOOT_PAYLOAD).signed 33 + 34 + $(obj)/vmlinuz: $(obj)/$(ZBOOT_PAYLOAD-y) FORCE 35 + $(call if_changed,$(zboot-method-y)) 36 + 37 + OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \ 38 + --rename-section .data=.gzdata,load,alloc,readonly,contents 39 + $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE 40 + $(call if_changed,objcopy) 41 + 42 + AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \ 43 + -DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \ 44 + -DZBOOT_SIZE_LEN=$(zboot-size-len-y) \ 45 + -DCOMP_TYPE="\"$(comp-type-y)\"" 46 + 47 + $(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE 48 + $(call if_changed_rule,as_o_S) 49 + 50 + ZBOOT_DEPS := $(obj)/zboot-header.o $(objtree)/drivers/firmware/efi/libstub/lib.a 51 + 52 + LDFLAGS_vmlinuz.efi.elf := -T $(srctree)/drivers/firmware/efi/libstub/zboot.lds 53 + $(obj)/vmlinuz.efi.elf: $(obj)/vmlinuz.o $(ZBOOT_DEPS) FORCE 54 + $(call if_changed,ld) 55 + 56 + ZBOOT_EFI-y := vmlinuz.efi 57 + ZBOOT_EFI-$(CONFIG_EFI_ZBOOT_SIGNED) := vmlinuz.efi.unsigned 58 + 59 + OBJCOPYFLAGS_$(ZBOOT_EFI-y) := -O binary 60 + $(obj)/$(ZBOOT_EFI-y): $(obj)/vmlinuz.efi.elf FORCE 61 + $(call if_changed,objcopy) 62 + 63 + targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi 64 + 65 + ifneq ($(CONFIG_EFI_ZBOOT_SIGNED),) 66 + $(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.unsigned FORCE 67 + $(call if_changed,sbsign) 68 + endif 69 + 70 + targets += $(EFI_ZBOOT_PAYLOAD).signed vmlinuz.efi.unsigned
+13 -14
drivers/firmware/efi/libstub/arm64-stub.c
··· 19 19 { 20 20 u64 tg; 21 21 22 + /* 23 + * If we have 48 bits of VA space for TTBR0 mappings, we can map the 24 + * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is 25 + * unnecessary. 26 + */ 27 + if (VA_BITS_MIN >= 48) 28 + efi_novamap = true; 29 + 22 30 /* UEFI mandates support for 4 KB granularity, no need to check */ 23 31 if (IS_ENABLED(CONFIG_ARM64_4K_PAGES)) 24 32 return EFI_SUCCESS; ··· 50 42 */ 51 43 static bool check_image_region(u64 base, u64 size) 52 44 { 53 - unsigned long map_size, desc_size, buff_size; 54 - efi_memory_desc_t *memory_map; 55 - struct efi_boot_memmap map; 45 + struct efi_boot_memmap *map; 56 46 efi_status_t status; 57 47 bool ret = false; 58 48 int map_offset; 59 49 60 - map.map = &memory_map; 61 - map.map_size = &map_size; 62 - map.desc_size = &desc_size; 63 - map.desc_ver = NULL; 64 - map.key_ptr = NULL; 65 - map.buff_size = &buff_size; 66 - 67 - status = efi_get_memory_map(&map); 50 + status = efi_get_memory_map(&map, false); 68 51 if (status != EFI_SUCCESS) 69 52 return false; 70 53 71 - for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { 72 - efi_memory_desc_t *md = (void *)memory_map + map_offset; 54 + for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) { 55 + efi_memory_desc_t *md = (void *)map->map + map_offset; 73 56 u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE; 74 57 75 58 /* ··· 73 74 } 74 75 } 75 76 76 - efi_bs_call(free_pool, memory_map); 77 + efi_bs_call(free_pool, map); 77 78 78 79 return ret; 79 80 }
+167 -123
drivers/firmware/efi/libstub/efi-stub-helper.c
··· 218 218 efi_noinitrd = true; 219 219 } else if (!strcmp(param, "efi") && val) { 220 220 efi_nochunk = parse_option_str(val, "nochunk"); 221 - efi_novamap = parse_option_str(val, "novamap"); 221 + efi_novamap |= parse_option_str(val, "novamap"); 222 222 223 223 efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) && 224 224 parse_option_str(val, "nosoftreserve"); ··· 310 310 * 311 311 * Detect this case and extract OptionalData. 312 312 */ 313 - void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size) 313 + void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size) 314 314 { 315 315 const efi_load_option_t *load_option = *load_options; 316 316 efi_load_option_unpacked_t load_option_unpacked; ··· 334 334 *load_options_size = load_option_unpacked.optional_data_size; 335 335 } 336 336 337 + enum efistub_event { 338 + EFISTUB_EVT_INITRD, 339 + EFISTUB_EVT_LOAD_OPTIONS, 340 + EFISTUB_EVT_COUNT, 341 + }; 342 + 343 + #define STR_WITH_SIZE(s) sizeof(s), s 344 + 345 + static const struct { 346 + u32 pcr_index; 347 + u32 event_id; 348 + u32 event_data_len; 349 + u8 event_data[52]; 350 + } events[] = { 351 + [EFISTUB_EVT_INITRD] = { 352 + 9, 353 + INITRD_EVENT_TAG_ID, 354 + STR_WITH_SIZE("Linux initrd") 355 + }, 356 + [EFISTUB_EVT_LOAD_OPTIONS] = { 357 + 9, 358 + LOAD_OPTIONS_EVENT_TAG_ID, 359 + STR_WITH_SIZE("LOADED_IMAGE::LoadOptions") 360 + }, 361 + }; 362 + 363 + static efi_status_t efi_measure_tagged_event(unsigned long load_addr, 364 + unsigned long load_size, 365 + enum efistub_event event) 366 + { 367 + efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; 368 + efi_tcg2_protocol_t *tcg2 = NULL; 369 + efi_status_t status; 370 + 371 + efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2); 372 + if (tcg2) { 373 + struct efi_measured_event { 374 + efi_tcg2_event_t event_data; 375 + efi_tcg2_tagged_event_t tagged_event; 376 + u8 tagged_event_data[]; 377 + } *evt; 378 + int size = sizeof(*evt) + events[event].event_data_len; 379 + 380 + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 381 + (void **)&evt); 382 + if (status != EFI_SUCCESS) 383 + goto fail; 384 + 385 + evt->event_data = (struct efi_tcg2_event){ 386 + .event_size = size, 387 + .event_header.header_size = sizeof(evt->event_data.event_header), 388 + .event_header.header_version = EFI_TCG2_EVENT_HEADER_VERSION, 389 + .event_header.pcr_index = events[event].pcr_index, 390 + .event_header.event_type = EV_EVENT_TAG, 391 + }; 392 + 393 + evt->tagged_event = (struct efi_tcg2_tagged_event){ 394 + .tagged_event_id = events[event].event_id, 395 + .tagged_event_data_size = events[event].event_data_len, 396 + }; 397 + 398 + memcpy(evt->tagged_event_data, events[event].event_data, 399 + events[event].event_data_len); 400 + 401 + status = efi_call_proto(tcg2, hash_log_extend_event, 0, 402 + load_addr, load_size, &evt->event_data); 403 + efi_bs_call(free_pool, evt); 404 + 405 + if (status != EFI_SUCCESS) 406 + goto fail; 407 + return EFI_SUCCESS; 408 + } 409 + 410 + return EFI_UNSUPPORTED; 411 + fail: 412 + efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status); 413 + return status; 414 + } 415 + 337 416 /* 338 417 * Convert the unicode UEFI command line to ASCII to pass to kernel. 339 418 * Size of memory allocated return in *cmd_line_len. ··· 420 341 */ 421 342 char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len) 422 343 { 423 - const u16 *s2; 424 - unsigned long cmdline_addr = 0; 425 - int options_chars = efi_table_attr(image, load_options_size); 426 - const u16 *options = efi_table_attr(image, load_options); 344 + const efi_char16_t *options = efi_table_attr(image, load_options); 345 + u32 options_size = efi_table_attr(image, load_options_size); 427 346 int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */ 347 + unsigned long cmdline_addr = 0; 348 + const efi_char16_t *s2; 428 349 bool in_quote = false; 429 350 efi_status_t status; 351 + u32 options_chars; 430 352 431 - efi_apply_loadoptions_quirk((const void **)&options, &options_chars); 432 - options_chars /= sizeof(*options); 353 + if (options_size > 0) 354 + efi_measure_tagged_event((unsigned long)options, options_size, 355 + EFISTUB_EVT_LOAD_OPTIONS); 356 + 357 + efi_apply_loadoptions_quirk((const void **)&options, &options_size); 358 + options_chars = options_size / sizeof(efi_char16_t); 433 359 434 360 if (options) { 435 361 s2 = options; 436 362 while (options_bytes < COMMAND_LINE_SIZE && options_chars--) { 437 - u16 c = *s2++; 363 + efi_char16_t c = *s2++; 438 364 439 365 if (c < 0x80) { 440 366 if (c == L'\0' || c == L'\n') ··· 503 419 /** 504 420 * efi_exit_boot_services() - Exit boot services 505 421 * @handle: handle of the exiting image 506 - * @map: pointer to receive the memory map 507 422 * @priv: argument to be passed to @priv_func 508 423 * @priv_func: function to process the memory map before exiting boot services 509 424 * ··· 515 432 * 516 433 * Return: status code 517 434 */ 518 - efi_status_t efi_exit_boot_services(void *handle, 519 - struct efi_boot_memmap *map, 520 - void *priv, 435 + efi_status_t efi_exit_boot_services(void *handle, void *priv, 521 436 efi_exit_boot_map_processing priv_func) 522 437 { 438 + struct efi_boot_memmap *map; 523 439 efi_status_t status; 524 440 525 - status = efi_get_memory_map(map); 526 - 441 + status = efi_get_memory_map(&map, true); 527 442 if (status != EFI_SUCCESS) 528 - goto fail; 443 + return status; 529 444 530 445 status = priv_func(map, priv); 531 - if (status != EFI_SUCCESS) 532 - goto free_map; 446 + if (status != EFI_SUCCESS) { 447 + efi_bs_call(free_pool, map); 448 + return status; 449 + } 533 450 534 451 if (efi_disable_pci_dma) 535 452 efi_pci_disable_bridge_busmaster(); 536 453 537 - status = efi_bs_call(exit_boot_services, handle, *map->key_ptr); 454 + status = efi_bs_call(exit_boot_services, handle, map->map_key); 538 455 539 456 if (status == EFI_INVALID_PARAMETER) { 540 457 /* ··· 550 467 * buffer should account for any changes in the map so the call 551 468 * to get_memory_map() is expected to succeed here. 552 469 */ 553 - *map->map_size = *map->buff_size; 470 + map->map_size = map->buff_size; 554 471 status = efi_bs_call(get_memory_map, 555 - map->map_size, 556 - *map->map, 557 - map->key_ptr, 558 - map->desc_size, 559 - map->desc_ver); 472 + &map->map_size, 473 + &map->map, 474 + &map->map_key, 475 + &map->desc_size, 476 + &map->desc_ver); 560 477 561 478 /* exit_boot_services() was called, thus cannot free */ 562 479 if (status != EFI_SUCCESS) 563 - goto fail; 480 + return status; 564 481 565 482 status = priv_func(map, priv); 566 483 /* exit_boot_services() was called, thus cannot free */ 567 484 if (status != EFI_SUCCESS) 568 - goto fail; 485 + return status; 569 486 570 - status = efi_bs_call(exit_boot_services, handle, *map->key_ptr); 487 + status = efi_bs_call(exit_boot_services, handle, map->map_key); 571 488 } 572 489 573 - /* exit_boot_services() was called, thus cannot free */ 574 - if (status != EFI_SUCCESS) 575 - goto fail; 576 - 577 - return EFI_SUCCESS; 578 - 579 - free_map: 580 - efi_bs_call(free_pool, *map->map); 581 - fail: 582 490 return status; 583 491 } 584 492 ··· 634 560 * * %EFI_SUCCESS if the initrd was loaded successfully, in which 635 561 * case @load_addr and @load_size are assigned accordingly 636 562 * * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path 637 - * * %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL 638 563 * * %EFI_OUT_OF_RESOURCES if memory allocation failed 639 564 * * %EFI_LOAD_ERROR in all other cases 640 565 */ 641 566 static 642 - efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr, 643 - unsigned long *load_size, 567 + efi_status_t efi_load_initrd_dev_path(struct linux_efi_initrd *initrd, 644 568 unsigned long max) 645 569 { 646 570 efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID; 647 571 efi_device_path_protocol_t *dp; 648 572 efi_load_file2_protocol_t *lf2; 649 - unsigned long initrd_addr; 650 - unsigned long initrd_size; 651 573 efi_handle_t handle; 652 574 efi_status_t status; 653 575 ··· 657 587 if (status != EFI_SUCCESS) 658 588 return status; 659 589 660 - status = efi_call_proto(lf2, load_file, dp, false, &initrd_size, NULL); 590 + initrd->size = 0; 591 + status = efi_call_proto(lf2, load_file, dp, false, &initrd->size, NULL); 661 592 if (status != EFI_BUFFER_TOO_SMALL) 662 593 return EFI_LOAD_ERROR; 663 594 664 - status = efi_allocate_pages(initrd_size, &initrd_addr, max); 595 + status = efi_allocate_pages(initrd->size, &initrd->base, max); 665 596 if (status != EFI_SUCCESS) 666 597 return status; 667 598 668 - status = efi_call_proto(lf2, load_file, dp, false, &initrd_size, 669 - (void *)initrd_addr); 599 + status = efi_call_proto(lf2, load_file, dp, false, &initrd->size, 600 + (void *)initrd->base); 670 601 if (status != EFI_SUCCESS) { 671 - efi_free(initrd_size, initrd_addr); 602 + efi_free(initrd->size, initrd->base); 672 603 return EFI_LOAD_ERROR; 673 604 } 674 - 675 - *load_addr = initrd_addr; 676 - *load_size = initrd_size; 677 605 return EFI_SUCCESS; 678 606 } 679 607 680 608 static 681 609 efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, 682 - unsigned long *load_addr, 683 - unsigned long *load_size, 610 + struct linux_efi_initrd *initrd, 684 611 unsigned long soft_limit, 685 612 unsigned long hard_limit) 686 613 { 687 614 if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) || 688 - (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) { 689 - *load_addr = *load_size = 0; 690 - return EFI_SUCCESS; 691 - } 615 + (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) 616 + return EFI_UNSUPPORTED; 692 617 693 618 return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, 694 619 soft_limit, hard_limit, 695 - load_addr, load_size); 696 - } 697 - 698 - static const struct { 699 - efi_tcg2_event_t event_data; 700 - efi_tcg2_tagged_event_t tagged_event; 701 - u8 tagged_event_data[]; 702 - } initrd_tcg2_event = { 703 - { 704 - sizeof(initrd_tcg2_event) + sizeof("Linux initrd"), 705 - { 706 - sizeof(initrd_tcg2_event.event_data.event_header), 707 - EFI_TCG2_EVENT_HEADER_VERSION, 708 - 9, 709 - EV_EVENT_TAG, 710 - }, 711 - }, 712 - { 713 - INITRD_EVENT_TAG_ID, 714 - sizeof("Linux initrd"), 715 - }, 716 - { "Linux initrd" }, 717 - }; 718 - 719 - static void efi_measure_initrd(unsigned long load_addr, unsigned long load_size) 720 - { 721 - efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; 722 - efi_tcg2_protocol_t *tcg2 = NULL; 723 - efi_status_t status; 724 - 725 - efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2); 726 - if (tcg2) { 727 - status = efi_call_proto(tcg2, hash_log_extend_event, 728 - 0, load_addr, load_size, 729 - &initrd_tcg2_event.event_data); 730 - if (status != EFI_SUCCESS) 731 - efi_warn("Failed to measure initrd data: 0x%lx\n", 732 - status); 733 - else 734 - efi_info("Measured initrd data into PCR %d\n", 735 - initrd_tcg2_event.event_data.event_header.pcr_index); 736 - } 620 + &initrd->base, &initrd->size); 737 621 } 738 622 739 623 /** 740 624 * efi_load_initrd() - Load initial RAM disk 741 625 * @image: EFI loaded image protocol 742 - * @load_addr: pointer to loaded initrd 743 - * @load_size: size of loaded initrd 744 626 * @soft_limit: preferred address for loading the initrd 745 627 * @hard_limit: upper limit address for loading the initrd 746 628 * 747 629 * Return: status code 748 630 */ 749 631 efi_status_t efi_load_initrd(efi_loaded_image_t *image, 750 - unsigned long *load_addr, 751 - unsigned long *load_size, 752 632 unsigned long soft_limit, 753 - unsigned long hard_limit) 633 + unsigned long hard_limit, 634 + const struct linux_efi_initrd **out) 754 635 { 755 - efi_status_t status; 636 + efi_guid_t tbl_guid = LINUX_EFI_INITRD_MEDIA_GUID; 637 + efi_status_t status = EFI_SUCCESS; 638 + struct linux_efi_initrd initrd, *tbl; 756 639 757 - if (efi_noinitrd) { 758 - *load_addr = *load_size = 0; 759 - status = EFI_SUCCESS; 760 - } else { 761 - status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit); 762 - if (status == EFI_SUCCESS) { 763 - efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n"); 764 - if (*load_size > 0) 765 - efi_measure_initrd(*load_addr, *load_size); 766 - } else if (status == EFI_NOT_FOUND) { 767 - status = efi_load_initrd_cmdline(image, load_addr, load_size, 768 - soft_limit, hard_limit); 769 - if (status == EFI_SUCCESS && *load_size > 0) 770 - efi_info("Loaded initrd from command line option\n"); 771 - } 772 - if (status != EFI_SUCCESS) { 773 - efi_err("Failed to load initrd: 0x%lx\n", status); 774 - *load_addr = *load_size = 0; 775 - } 640 + if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD) || efi_noinitrd) 641 + return EFI_SUCCESS; 642 + 643 + status = efi_load_initrd_dev_path(&initrd, hard_limit); 644 + if (status == EFI_SUCCESS) { 645 + efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n"); 646 + if (initrd.size > 0 && 647 + efi_measure_tagged_event(initrd.base, initrd.size, 648 + EFISTUB_EVT_INITRD) == EFI_SUCCESS) 649 + efi_info("Measured initrd data into PCR 9\n"); 650 + } else if (status == EFI_NOT_FOUND) { 651 + status = efi_load_initrd_cmdline(image, &initrd, soft_limit, 652 + hard_limit); 653 + /* command line loader disabled or no initrd= passed? */ 654 + if (status == EFI_UNSUPPORTED || status == EFI_NOT_READY) 655 + return EFI_SUCCESS; 656 + if (status == EFI_SUCCESS) 657 + efi_info("Loaded initrd from command line option\n"); 776 658 } 659 + if (status != EFI_SUCCESS) 660 + goto failed; 777 661 662 + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd), 663 + (void **)&tbl); 664 + if (status != EFI_SUCCESS) 665 + goto free_initrd; 666 + 667 + *tbl = initrd; 668 + status = efi_bs_call(install_configuration_table, &tbl_guid, tbl); 669 + if (status != EFI_SUCCESS) 670 + goto free_tbl; 671 + 672 + if (out) 673 + *out = tbl; 674 + return EFI_SUCCESS; 675 + 676 + free_tbl: 677 + efi_bs_call(free_pool, tbl); 678 + free_initrd: 679 + efi_free(initrd.size, initrd.base); 680 + failed: 681 + efi_err("Failed to load initrd: 0x%lx\n", status); 778 682 return status; 779 683 } 780 684
+50 -68
drivers/firmware/efi/libstub/efi-stub.c
··· 10 10 */ 11 11 12 12 #include <linux/efi.h> 13 - #include <linux/libfdt.h> 14 13 #include <asm/efi.h> 15 14 16 15 #include "efistub.h" ··· 39 40 40 41 #ifdef CONFIG_ARM64 41 42 # define EFI_RT_VIRTUAL_LIMIT DEFAULT_MAP_WINDOW_64 42 - #elif defined(CONFIG_RISCV) 43 + #elif defined(CONFIG_RISCV) || defined(CONFIG_LOONGARCH) 43 44 # define EFI_RT_VIRTUAL_LIMIT TASK_SIZE_MIN 44 - #else 45 + #else /* Only if TASK_SIZE is a constant */ 45 46 # define EFI_RT_VIRTUAL_LIMIT TASK_SIZE 46 47 #endif 47 48 48 - static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; 49 - static bool flat_va_mapping; 49 + /* 50 + * Some architectures map the EFI regions into the kernel's linear map using a 51 + * fixed offset. 52 + */ 53 + #ifndef EFI_RT_VIRTUAL_OFFSET 54 + #define EFI_RT_VIRTUAL_OFFSET 0 55 + #endif 50 56 51 - const efi_system_table_t *efi_system_table; 57 + static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; 58 + static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0); 52 59 53 60 static struct screen_info *setup_graphics(void) 54 61 { ··· 129 124 unsigned long image_addr; 130 125 unsigned long image_size = 0; 131 126 /* addr/point and size pairs for memory management*/ 132 - unsigned long initrd_addr = 0; 133 - unsigned long initrd_size = 0; 134 - unsigned long fdt_addr = 0; /* Original DTB */ 135 - unsigned long fdt_size = 0; 136 127 char *cmdline_ptr = NULL; 137 128 int cmdline_size = 0; 138 129 efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; 139 130 unsigned long reserve_addr = 0; 140 131 unsigned long reserve_size = 0; 141 - enum efi_secureboot_mode secure_boot; 142 132 struct screen_info *si; 143 133 efi_properties_table_t *prop_tbl; 144 134 ··· 154 154 * information about the running image, such as size and the command 155 155 * line. 156 156 */ 157 - status = efi_system_table->boottime->handle_protocol(handle, 158 - &loaded_image_proto, (void *)&image); 157 + status = efi_bs_call(handle_protocol, handle, &loaded_image_proto, 158 + (void *)&image); 159 159 if (status != EFI_SUCCESS) { 160 160 efi_err("Failed to get loaded image protocol\n"); 161 161 goto fail; ··· 209 209 /* Ask the firmware to clear memory on unclean shutdown */ 210 210 efi_enable_reset_attack_mitigation(); 211 211 212 - secure_boot = efi_get_secureboot(); 213 - 214 - /* 215 - * Unauthenticated device tree data is a security hazard, so ignore 216 - * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure 217 - * boot is enabled if we can't determine its state. 218 - */ 219 - if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) || 220 - secure_boot != efi_secureboot_mode_disabled) { 221 - if (strstr(cmdline_ptr, "dtb=")) 222 - efi_err("Ignoring DTB from command line.\n"); 223 - } else { 224 - status = efi_load_dtb(image, &fdt_addr, &fdt_size); 225 - 226 - if (status != EFI_SUCCESS) { 227 - efi_err("Failed to load device tree!\n"); 228 - goto fail_free_image; 229 - } 230 - } 231 - 232 - if (fdt_addr) { 233 - efi_info("Using DTB from command line\n"); 234 - } else { 235 - /* Look for a device tree configuration table entry. */ 236 - fdt_addr = (uintptr_t)get_fdt(&fdt_size); 237 - if (fdt_addr) 238 - efi_info("Using DTB from configuration table\n"); 239 - } 240 - 241 - if (!fdt_addr) 242 - efi_info("Generating empty DTB\n"); 243 - 244 - efi_load_initrd(image, &initrd_addr, &initrd_size, ULONG_MAX, 245 - efi_get_max_initrd_addr(image_addr)); 212 + efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr), 213 + NULL); 246 214 247 215 efi_random_get_seed(); 248 216 ··· 222 254 * The easiest way to achieve that is to simply use a 1:1 mapping. 223 255 */ 224 256 prop_tbl = get_efi_config_table(EFI_PROPERTIES_TABLE_GUID); 225 - flat_va_mapping = prop_tbl && 226 - (prop_tbl->memory_protection_attribute & 257 + flat_va_mapping |= prop_tbl && 258 + (prop_tbl->memory_protection_attribute & 227 259 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA); 228 260 229 261 /* force efi_novamap if SetVirtualAddressMap() is unsupported */ ··· 252 284 253 285 install_memreserve_table(); 254 286 255 - status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr, 256 - initrd_addr, initrd_size, 257 - cmdline_ptr, fdt_addr, fdt_size); 258 - if (status != EFI_SUCCESS) 259 - goto fail_free_initrd; 287 + status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr); 260 288 261 - if (IS_ENABLED(CONFIG_ARM)) 262 - efi_handle_post_ebs_state(); 263 - 264 - efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr)); 265 - /* not reached */ 266 - 267 - fail_free_initrd: 268 - efi_err("Failed to update FDT and exit boot services\n"); 269 - 270 - efi_free(initrd_size, initrd_addr); 271 - efi_free(fdt_size, fdt_addr); 272 - 273 - fail_free_image: 274 289 efi_free(image_size, image_addr); 275 290 efi_free(reserve_size, reserve_addr); 276 291 fail_free_screeninfo: ··· 262 311 efi_bs_call(free_pool, cmdline_ptr); 263 312 fail: 264 313 return status; 314 + } 315 + 316 + /* 317 + * efi_allocate_virtmap() - create a pool allocation for the virtmap 318 + * 319 + * Create an allocation that is of sufficient size to hold all the memory 320 + * descriptors that will be passed to SetVirtualAddressMap() to inform the 321 + * firmware about the virtual mapping that will be used under the OS to call 322 + * into the firmware. 323 + */ 324 + efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap, 325 + unsigned long *desc_size, u32 *desc_ver) 326 + { 327 + unsigned long size, mmap_key; 328 + efi_status_t status; 329 + 330 + /* 331 + * Use the size of the current memory map as an upper bound for the 332 + * size of the buffer we need to pass to SetVirtualAddressMap() to 333 + * cover all EFI_MEMORY_RUNTIME regions. 334 + */ 335 + size = 0; 336 + status = efi_bs_call(get_memory_map, &size, NULL, &mmap_key, desc_size, 337 + desc_ver); 338 + if (status != EFI_BUFFER_TOO_SMALL) 339 + return EFI_LOAD_ERROR; 340 + 341 + return efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, 342 + (void **)virtmap); 265 343 } 266 344 267 345 /* ··· 308 328 efi_memory_desc_t *in, *out = runtime_map; 309 329 int l; 310 330 331 + *count = 0; 332 + 311 333 for (l = 0; l < map_size; l += desc_size) { 312 334 u64 paddr, size; 313 335 ··· 320 338 paddr = in->phys_addr; 321 339 size = in->num_pages * EFI_PAGE_SIZE; 322 340 323 - in->virt_addr = in->phys_addr; 341 + in->virt_addr = in->phys_addr + EFI_RT_VIRTUAL_OFFSET; 324 342 if (efi_novamap) { 325 343 continue; 326 344 }
+39 -30
drivers/firmware/efi/libstub/efistub.h
··· 160 160 */ 161 161 #define EFI_MMAP_NR_SLACK_SLOTS 8 162 162 163 - struct efi_boot_memmap { 164 - efi_memory_desc_t **map; 165 - unsigned long *map_size; 166 - unsigned long *desc_size; 167 - u32 *desc_ver; 168 - unsigned long *key_ptr; 169 - unsigned long *buff_size; 163 + typedef struct efi_generic_dev_path efi_device_path_protocol_t; 164 + 165 + union efi_device_path_to_text_protocol { 166 + struct { 167 + efi_char16_t *(__efiapi *convert_device_node_to_text)( 168 + const efi_device_path_protocol_t *, 169 + bool, bool); 170 + efi_char16_t *(__efiapi *convert_device_path_to_text)( 171 + const efi_device_path_protocol_t *, 172 + bool, bool); 173 + }; 174 + struct { 175 + u32 convert_device_node_to_text; 176 + u32 convert_device_path_to_text; 177 + } mixed_mode; 170 178 }; 171 179 172 - typedef struct efi_generic_dev_path efi_device_path_protocol_t; 180 + typedef union efi_device_path_to_text_protocol efi_device_path_to_text_protocol_t; 173 181 174 182 typedef void *efi_event_t; 175 183 /* Note that notifications won't work in mixed mode */ ··· 262 254 efi_handle_t *); 263 255 efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, 264 256 void *); 265 - void *load_image; 266 - void *start_image; 257 + efi_status_t (__efiapi *load_image)(bool, efi_handle_t, 258 + efi_device_path_protocol_t *, 259 + void *, unsigned long, 260 + efi_handle_t *); 261 + efi_status_t (__efiapi *start_image)(efi_handle_t, unsigned long *, 262 + efi_char16_t **); 267 263 efi_status_t __noreturn (__efiapi *exit)(efi_handle_t, 268 264 efi_status_t, 269 265 unsigned long, 270 266 efi_char16_t *); 271 - void *unload_image; 267 + efi_status_t (__efiapi *unload_image)(efi_handle_t); 272 268 efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, 273 269 unsigned long); 274 270 void *get_next_monotonic_count; ··· 289 277 void *locate_handle_buffer; 290 278 efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, 291 279 void **); 292 - void *install_multiple_protocol_interfaces; 293 - void *uninstall_multiple_protocol_interfaces; 280 + efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...); 281 + efi_status_t (__efiapi *uninstall_multiple_protocol_interfaces)(efi_handle_t, ...); 294 282 void *calculate_crc32; 295 - void *copy_mem; 296 - void *set_mem; 283 + void (__efiapi *copy_mem)(void *, const void *, unsigned long); 284 + void (__efiapi *set_mem)(void *, unsigned long, unsigned char); 297 285 void *create_event_ex; 298 286 }; 299 287 struct { ··· 753 741 typedef u32 efi_tcg2_event_log_format; 754 742 755 743 #define INITRD_EVENT_TAG_ID 0x8F3B22ECU 744 + #define LOAD_OPTIONS_EVENT_TAG_ID 0x8F3B22EDU 756 745 #define EV_EVENT_TAG 0x00000006U 757 746 #define EFI_TCG2_EVENT_HEADER_VERSION 0x1 758 747 ··· 853 840 u16 file_path_list_length; 854 841 const efi_char16_t *description; 855 842 const efi_device_path_protocol_t *file_path_list; 856 - size_t optional_data_size; 843 + u32 optional_data_size; 857 844 const void *optional_data; 858 845 } efi_load_option_unpacked_t; 859 846 ··· 863 850 struct efi_boot_memmap *map, 864 851 void *priv); 865 852 866 - efi_status_t efi_exit_boot_services(void *handle, 867 - struct efi_boot_memmap *map, 868 - void *priv, 853 + efi_status_t efi_exit_boot_services(void *handle, void *priv, 869 854 efi_exit_boot_map_processing priv_func); 870 855 871 - efi_status_t allocate_new_fdt_and_exit_boot(void *handle, 872 - unsigned long *new_fdt_addr, 873 - u64 initrd_addr, u64 initrd_size, 874 - char *cmdline_ptr, 875 - unsigned long fdt_addr, 876 - unsigned long fdt_size); 856 + efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 857 + unsigned long kernel_addr, char *cmdline_ptr); 877 858 878 859 void *get_fdt(unsigned long *fdt_size); 879 860 861 + efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap, 862 + unsigned long *desc_size, u32 *desc_ver); 880 863 void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, 881 864 unsigned long desc_size, efi_memory_desc_t *runtime_map, 882 865 int *count); ··· 894 885 895 886 void efi_free(unsigned long size, unsigned long addr); 896 887 897 - void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size); 888 + void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size); 898 889 899 890 char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len); 900 891 901 - efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); 892 + efi_status_t efi_get_memory_map(struct efi_boot_memmap **map, 893 + bool install_cfg_tbl); 902 894 903 895 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, 904 896 unsigned long max); ··· 942 932 } 943 933 944 934 efi_status_t efi_load_initrd(efi_loaded_image_t *image, 945 - unsigned long *load_addr, 946 - unsigned long *load_size, 947 935 unsigned long soft_limit, 948 - unsigned long hard_limit); 936 + unsigned long hard_limit, 937 + const struct linux_efi_initrd **out); 949 938 /* 950 939 * This function handles the architcture specific differences between arm and 951 940 * arm64 regarding where the kernel image must be loaded and any memory that
+93 -82
drivers/firmware/efi/libstub/fdt.c
··· 28 28 } 29 29 30 30 static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size, 31 - void *fdt, int new_fdt_size, char *cmdline_ptr, 32 - u64 initrd_addr, u64 initrd_size) 31 + void *fdt, int new_fdt_size, char *cmdline_ptr) 33 32 { 34 33 int node, num_rsv; 35 34 int status; ··· 88 89 if (cmdline_ptr != NULL && strlen(cmdline_ptr) > 0) { 89 90 status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, 90 91 strlen(cmdline_ptr) + 1); 91 - if (status) 92 - goto fdt_set_fail; 93 - } 94 - 95 - /* Set initrd address/end in device tree, if present */ 96 - if (initrd_size != 0) { 97 - u64 initrd_image_end; 98 - u64 initrd_image_start = cpu_to_fdt64(initrd_addr); 99 - 100 - status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start); 101 - if (status) 102 - goto fdt_set_fail; 103 - 104 - initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); 105 - status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end); 106 92 if (status) 107 93 goto fdt_set_fail; 108 94 } ··· 154 170 if (node < 0) 155 171 return EFI_LOAD_ERROR; 156 172 157 - fdt_val64 = cpu_to_fdt64((unsigned long)*map->map); 173 + fdt_val64 = cpu_to_fdt64((unsigned long)map->map); 158 174 159 175 err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64); 160 176 if (err) 161 177 return EFI_LOAD_ERROR; 162 178 163 - fdt_val32 = cpu_to_fdt32(*map->map_size); 179 + fdt_val32 = cpu_to_fdt32(map->map_size); 164 180 165 181 err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32); 166 182 if (err) 167 183 return EFI_LOAD_ERROR; 168 184 169 - fdt_val32 = cpu_to_fdt32(*map->desc_size); 185 + fdt_val32 = cpu_to_fdt32(map->desc_size); 170 186 171 187 err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32); 172 188 if (err) 173 189 return EFI_LOAD_ERROR; 174 190 175 - fdt_val32 = cpu_to_fdt32(*map->desc_ver); 191 + fdt_val32 = cpu_to_fdt32(map->desc_ver); 176 192 177 193 err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32); 178 194 if (err) ··· 182 198 } 183 199 184 200 struct exit_boot_struct { 201 + struct efi_boot_memmap *boot_memmap; 185 202 efi_memory_desc_t *runtime_map; 186 - int *runtime_entry_count; 203 + int runtime_entry_count; 187 204 void *new_fdt_addr; 188 205 }; 189 206 190 - static efi_status_t exit_boot_func(struct efi_boot_memmap *map, 191 - void *priv) 207 + static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) 192 208 { 193 209 struct exit_boot_struct *p = priv; 210 + 211 + p->boot_memmap = map; 212 + 194 213 /* 195 214 * Update the memory map with virtual addresses. The function will also 196 215 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 197 216 * entries so that we can pass it straight to SetVirtualAddressMap() 198 217 */ 199 - efi_get_virtmap(*map->map, *map->map_size, *map->desc_size, 200 - p->runtime_map, p->runtime_entry_count); 218 + efi_get_virtmap(map->map, map->map_size, map->desc_size, 219 + p->runtime_map, &p->runtime_entry_count); 201 220 202 221 return update_fdt_memmap(p->new_fdt_addr, map); 203 222 } ··· 210 223 #endif 211 224 212 225 /* 213 - * Allocate memory for a new FDT, then add EFI, commandline, and 214 - * initrd related fields to the FDT. This routine increases the 215 - * FDT allocation size until the allocated memory is large 216 - * enough. EFI allocations are in EFI_PAGE_SIZE granules, 217 - * which are fixed at 4K bytes, so in most cases the first 218 - * allocation should succeed. 219 - * EFI boot services are exited at the end of this function. 220 - * There must be no allocations between the get_memory_map() 221 - * call and the exit_boot_services() call, so the exiting of 222 - * boot services is very tightly tied to the creation of the FDT 223 - * with the final memory map in it. 226 + * Allocate memory for a new FDT, then add EFI and commandline related fields 227 + * to the FDT. This routine increases the FDT allocation size until the 228 + * allocated memory is large enough. EFI allocations are in EFI_PAGE_SIZE 229 + * granules, which are fixed at 4K bytes, so in most cases the first allocation 230 + * should succeed. EFI boot services are exited at the end of this function. 231 + * There must be no allocations between the get_memory_map() call and the 232 + * exit_boot_services() call, so the exiting of boot services is very tightly 233 + * tied to the creation of the FDT with the final memory map in it. 224 234 */ 225 - 235 + static 226 236 efi_status_t allocate_new_fdt_and_exit_boot(void *handle, 237 + efi_loaded_image_t *image, 227 238 unsigned long *new_fdt_addr, 228 - u64 initrd_addr, u64 initrd_size, 229 - char *cmdline_ptr, 230 - unsigned long fdt_addr, 231 - unsigned long fdt_size) 239 + char *cmdline_ptr) 232 240 { 233 - unsigned long map_size, desc_size, buff_size; 241 + unsigned long desc_size; 234 242 u32 desc_ver; 235 - unsigned long mmap_key; 236 - efi_memory_desc_t *memory_map, *runtime_map; 237 243 efi_status_t status; 238 - int runtime_entry_count; 239 - struct efi_boot_memmap map; 240 244 struct exit_boot_struct priv; 245 + unsigned long fdt_addr = 0; 246 + unsigned long fdt_size = 0; 241 247 242 - map.map = &runtime_map; 243 - map.map_size = &map_size; 244 - map.desc_size = &desc_size; 245 - map.desc_ver = &desc_ver; 246 - map.key_ptr = &mmap_key; 247 - map.buff_size = &buff_size; 248 + if (!efi_novamap) { 249 + status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, 250 + &desc_ver); 251 + if (status != EFI_SUCCESS) { 252 + efi_err("Unable to retrieve UEFI memory map.\n"); 253 + return status; 254 + } 255 + } 248 256 249 257 /* 250 - * Get a copy of the current memory map that we will use to prepare 251 - * the input for SetVirtualAddressMap(). We don't have to worry about 252 - * subsequent allocations adding entries, since they could not affect 253 - * the number of EFI_MEMORY_RUNTIME regions. 258 + * Unauthenticated device tree data is a security hazard, so ignore 259 + * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure 260 + * boot is enabled if we can't determine its state. 254 261 */ 255 - status = efi_get_memory_map(&map); 256 - if (status != EFI_SUCCESS) { 257 - efi_err("Unable to retrieve UEFI memory map.\n"); 258 - return status; 262 + if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) || 263 + efi_get_secureboot() != efi_secureboot_mode_disabled) { 264 + if (strstr(cmdline_ptr, "dtb=")) 265 + efi_err("Ignoring DTB from command line.\n"); 266 + } else { 267 + status = efi_load_dtb(image, &fdt_addr, &fdt_size); 268 + 269 + if (status != EFI_SUCCESS && status != EFI_NOT_READY) { 270 + efi_err("Failed to load device tree!\n"); 271 + goto fail; 272 + } 259 273 } 274 + 275 + if (fdt_addr) { 276 + efi_info("Using DTB from command line\n"); 277 + } else { 278 + /* Look for a device tree configuration table entry. */ 279 + fdt_addr = (uintptr_t)get_fdt(&fdt_size); 280 + if (fdt_addr) 281 + efi_info("Using DTB from configuration table\n"); 282 + } 283 + 284 + if (!fdt_addr) 285 + efi_info("Generating empty DTB\n"); 260 286 261 287 efi_info("Exiting boot services...\n"); 262 288 263 - map.map = &memory_map; 264 289 status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX); 265 290 if (status != EFI_SUCCESS) { 266 291 efi_err("Unable to allocate memory for new device tree.\n"); 267 292 goto fail; 268 293 } 269 294 270 - /* 271 - * Now that we have done our final memory allocation (and free) 272 - * we can get the memory map key needed for exit_boot_services(). 273 - */ 274 - status = efi_get_memory_map(&map); 275 - if (status != EFI_SUCCESS) 276 - goto fail_free_new_fdt; 277 - 278 295 status = update_fdt((void *)fdt_addr, fdt_size, 279 - (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr, 280 - initrd_addr, initrd_size); 296 + (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr); 281 297 282 298 if (status != EFI_SUCCESS) { 283 299 efi_err("Unable to construct new device tree.\n"); 284 300 goto fail_free_new_fdt; 285 301 } 286 302 287 - runtime_entry_count = 0; 288 - priv.runtime_map = runtime_map; 289 - priv.runtime_entry_count = &runtime_entry_count; 290 - priv.new_fdt_addr = (void *)*new_fdt_addr; 303 + priv.new_fdt_addr = (void *)*new_fdt_addr; 291 304 292 - status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func); 305 + status = efi_exit_boot_services(handle, &priv, exit_boot_func); 293 306 294 307 if (status == EFI_SUCCESS) { 295 308 efi_set_virtual_address_map_t *svam; ··· 299 312 300 313 /* Install the new virtual address map */ 301 314 svam = efi_system_table->runtime->set_virtual_address_map; 302 - status = svam(runtime_entry_count * desc_size, desc_size, 303 - desc_ver, runtime_map); 315 + status = svam(priv.runtime_entry_count * desc_size, desc_size, 316 + desc_ver, priv.runtime_map); 304 317 305 318 /* 306 319 * We are beyond the point of no return here, so if the call to ··· 308 321 * incoming kernel but proceed normally otherwise. 309 322 */ 310 323 if (status != EFI_SUCCESS) { 324 + efi_memory_desc_t *p; 311 325 int l; 312 326 313 327 /* ··· 317 329 * the incoming kernel that no virtual translation has 318 330 * been installed. 319 331 */ 320 - for (l = 0; l < map_size; l += desc_size) { 321 - efi_memory_desc_t *p = (void *)memory_map + l; 332 + for (l = 0; l < priv.boot_memmap->map_size; 333 + l += priv.boot_memmap->desc_size) { 334 + p = (void *)priv.boot_memmap->map + l; 322 335 323 336 if (p->attribute & EFI_MEMORY_RUNTIME) 324 337 p->virt_addr = 0; ··· 334 345 efi_free(MAX_FDT_SIZE, *new_fdt_addr); 335 346 336 347 fail: 337 - efi_system_table->boottime->free_pool(runtime_map); 348 + efi_free(fdt_size, fdt_addr); 349 + 350 + efi_bs_call(free_pool, priv.runtime_map); 338 351 339 352 return EFI_LOAD_ERROR; 353 + } 354 + 355 + efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 356 + unsigned long kernel_addr, char *cmdline_ptr) 357 + { 358 + unsigned long fdt_addr; 359 + efi_status_t status; 360 + 361 + status = allocate_new_fdt_and_exit_boot(handle, image, &fdt_addr, 362 + cmdline_ptr); 363 + if (status != EFI_SUCCESS) { 364 + efi_err("Failed to update FDT and exit boot services\n"); 365 + return status; 366 + } 367 + 368 + if (IS_ENABLED(CONFIG_ARM)) 369 + efi_handle_post_ebs_state(); 370 + 371 + efi_enter_kernel(kernel_addr, fdt_addr, fdt_totalsize((void *)fdt_addr)); 372 + /* not reached */ 340 373 } 341 374 342 375 void *get_fdt(unsigned long *fdt_size)
+22 -1
drivers/firmware/efi/libstub/file.c
··· 66 66 static efi_status_t efi_open_volume(efi_loaded_image_t *image, 67 67 efi_file_protocol_t **fh) 68 68 { 69 + struct efi_vendor_dev_path *dp = image->file_path; 70 + efi_guid_t li_proto = LOADED_IMAGE_PROTOCOL_GUID; 69 71 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; 70 72 efi_simple_file_system_protocol_t *io; 71 73 efi_status_t status; 74 + 75 + // If we are using EFI zboot, we should look for the file system 76 + // protocol on the parent image's handle instead 77 + if (IS_ENABLED(CONFIG_EFI_ZBOOT) && 78 + image->parent_handle != NULL && 79 + dp != NULL && 80 + dp->header.type == EFI_DEV_MEDIA && 81 + dp->header.sub_type == EFI_DEV_MEDIA_VENDOR && 82 + !efi_guidcmp(dp->vendorguid, LINUX_EFI_ZBOOT_MEDIA_GUID)) { 83 + status = efi_bs_call(handle_protocol, image->parent_handle, 84 + &li_proto, (void *)&image); 85 + if (status != EFI_SUCCESS) { 86 + efi_err("Failed to locate parent image handle\n"); 87 + return status; 88 + } 89 + } 72 90 73 91 status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, 74 92 (void **)&io); ··· 154 136 unsigned long *load_size) 155 137 { 156 138 const efi_char16_t *cmdline = image->load_options; 157 - int cmdline_len = image->load_options_size; 139 + u32 cmdline_len = image->load_options_size; 158 140 unsigned long efi_chunk_size = ULONG_MAX; 159 141 efi_file_protocol_t *volume = NULL; 160 142 efi_file_protocol_t *file; ··· 256 238 257 239 if (volume) 258 240 volume->close(volume); 241 + 242 + if (*load_size == 0) 243 + return EFI_NOT_READY; 259 244 return EFI_SUCCESS; 260 245 261 246 err_close_file:
+30
drivers/firmware/efi/libstub/intrinsics.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/efi.h> 4 + #include <asm/efi.h> 5 + #include <asm/string.h> 6 + 7 + #include "efistub.h" 8 + 9 + #ifdef CONFIG_KASAN 10 + #undef memcpy 11 + #undef memmove 12 + #undef memset 13 + void *__memcpy(void *__dest, const void *__src, size_t __n) __alias(memcpy); 14 + void *__memmove(void *__dest, const void *__src, size_t count) __alias(memmove); 15 + void *__memset(void *s, int c, size_t count) __alias(memset); 16 + #endif 17 + 18 + void *memcpy(void *dst, const void *src, size_t len) 19 + { 20 + efi_bs_call(copy_mem, dst, src, len); 21 + return dst; 22 + } 23 + 24 + extern void *memmove(void *dst, const void *src, size_t len) __alias(memcpy); 25 + 26 + void *memset(void *dst, int c, size_t len) 27 + { 28 + efi_bs_call(set_mem, dst, len, c & U8_MAX); 29 + return dst; 30 + }
+102
drivers/firmware/efi/libstub/loongarch-stub.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Author: Yun Liu <liuyun@loongson.cn> 4 + * Huacai Chen <chenhuacai@loongson.cn> 5 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6 + */ 7 + 8 + #include <asm/efi.h> 9 + #include <asm/addrspace.h> 10 + #include "efistub.h" 11 + 12 + typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline, 13 + unsigned long systab); 14 + 15 + extern int kernel_asize; 16 + extern int kernel_fsize; 17 + extern int kernel_offset; 18 + extern kernel_entry_t kernel_entry; 19 + 20 + efi_status_t check_platform_features(void) 21 + { 22 + return EFI_SUCCESS; 23 + } 24 + 25 + efi_status_t handle_kernel_image(unsigned long *image_addr, 26 + unsigned long *image_size, 27 + unsigned long *reserve_addr, 28 + unsigned long *reserve_size, 29 + efi_loaded_image_t *image, 30 + efi_handle_t image_handle) 31 + { 32 + efi_status_t status; 33 + unsigned long kernel_addr = 0; 34 + 35 + kernel_addr = (unsigned long)&kernel_offset - kernel_offset; 36 + 37 + status = efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize, 38 + PHYSADDR(VMLINUX_LOAD_ADDRESS), SZ_2M, 0x0); 39 + 40 + *image_addr = kernel_addr; 41 + *image_size = kernel_asize; 42 + 43 + return status; 44 + } 45 + 46 + struct exit_boot_struct { 47 + efi_memory_desc_t *runtime_map; 48 + int runtime_entry_count; 49 + }; 50 + 51 + static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) 52 + { 53 + struct exit_boot_struct *p = priv; 54 + 55 + /* 56 + * Update the memory map with virtual addresses. The function will also 57 + * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 58 + * entries so that we can pass it straight to SetVirtualAddressMap() 59 + */ 60 + efi_get_virtmap(map->map, map->map_size, map->desc_size, 61 + p->runtime_map, &p->runtime_entry_count); 62 + 63 + return EFI_SUCCESS; 64 + } 65 + 66 + efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 67 + unsigned long kernel_addr, char *cmdline_ptr) 68 + { 69 + kernel_entry_t real_kernel_entry; 70 + struct exit_boot_struct priv; 71 + unsigned long desc_size; 72 + efi_status_t status; 73 + u32 desc_ver; 74 + 75 + status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver); 76 + if (status != EFI_SUCCESS) { 77 + efi_err("Unable to retrieve UEFI memory map.\n"); 78 + return status; 79 + } 80 + 81 + efi_info("Exiting boot services\n"); 82 + 83 + efi_novamap = false; 84 + status = efi_exit_boot_services(handle, &priv, exit_boot_func); 85 + if (status != EFI_SUCCESS) 86 + return status; 87 + 88 + /* Install the new virtual address map */ 89 + efi_rt_call(set_virtual_address_map, 90 + priv.runtime_entry_count * desc_size, desc_size, 91 + desc_ver, priv.runtime_map); 92 + 93 + /* Config Direct Mapping */ 94 + csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); 95 + csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); 96 + 97 + real_kernel_entry = (kernel_entry_t) 98 + ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS); 99 + 100 + real_kernel_entry(true, (unsigned long)cmdline_ptr, 101 + (unsigned long)efi_system_table); 102 + }
+42 -47
drivers/firmware/efi/libstub/mem.c
··· 5 5 6 6 #include "efistub.h" 7 7 8 - static inline bool mmap_has_headroom(unsigned long buff_size, 9 - unsigned long map_size, 10 - unsigned long desc_size) 11 - { 12 - unsigned long slack = buff_size - map_size; 13 - 14 - return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS; 15 - } 16 - 17 8 /** 18 9 * efi_get_memory_map() - get memory map 19 - * @map: on return pointer to memory map 10 + * @map: pointer to memory map pointer to which to assign the 11 + * newly allocated memory map 12 + * @install_cfg_tbl: whether or not to install the boot memory map as a 13 + * configuration table 20 14 * 21 15 * Retrieve the UEFI memory map. The allocated memory leaves room for 22 16 * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries. 23 17 * 24 18 * Return: status code 25 19 */ 26 - efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) 20 + efi_status_t efi_get_memory_map(struct efi_boot_memmap **map, 21 + bool install_cfg_tbl) 27 22 { 28 - efi_memory_desc_t *m = NULL; 23 + int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY 24 + : EFI_LOADER_DATA; 25 + efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID; 26 + struct efi_boot_memmap *m, tmp; 29 27 efi_status_t status; 30 - unsigned long key; 31 - u32 desc_version; 28 + unsigned long size; 32 29 33 - *map->desc_size = sizeof(*m); 34 - *map->map_size = *map->desc_size * 32; 35 - *map->buff_size = *map->map_size; 36 - again: 37 - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, 38 - *map->map_size, (void **)&m); 30 + tmp.map_size = 0; 31 + status = efi_bs_call(get_memory_map, &tmp.map_size, NULL, &tmp.map_key, 32 + &tmp.desc_size, &tmp.desc_ver); 33 + if (status != EFI_BUFFER_TOO_SMALL) 34 + return EFI_LOAD_ERROR; 35 + 36 + size = tmp.map_size + tmp.desc_size * EFI_MMAP_NR_SLACK_SLOTS; 37 + status = efi_bs_call(allocate_pool, memtype, sizeof(*m) + size, 38 + (void **)&m); 39 39 if (status != EFI_SUCCESS) 40 - goto fail; 40 + return status; 41 41 42 - *map->desc_size = 0; 43 - key = 0; 44 - status = efi_bs_call(get_memory_map, map->map_size, m, 45 - &key, map->desc_size, &desc_version); 46 - if (status == EFI_BUFFER_TOO_SMALL || 47 - !mmap_has_headroom(*map->buff_size, *map->map_size, 48 - *map->desc_size)) { 49 - efi_bs_call(free_pool, m); 42 + if (install_cfg_tbl) { 50 43 /* 51 - * Make sure there is some entries of headroom so that the 52 - * buffer can be reused for a new map after allocations are 53 - * no longer permitted. Its unlikely that the map will grow to 54 - * exceed this headroom once we are ready to trigger 55 - * ExitBootServices() 44 + * Installing a configuration table might allocate memory, and 45 + * this may modify the memory map. This means we should install 46 + * the configuration table first, and re-install or delete it 47 + * as needed. 56 48 */ 57 - *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS; 58 - *map->buff_size = *map->map_size; 59 - goto again; 49 + status = efi_bs_call(install_configuration_table, &tbl_guid, m); 50 + if (status != EFI_SUCCESS) 51 + goto free_map; 60 52 } 61 53 62 - if (status == EFI_SUCCESS) { 63 - if (map->key_ptr) 64 - *map->key_ptr = key; 65 - if (map->desc_ver) 66 - *map->desc_ver = desc_version; 67 - } else { 68 - efi_bs_call(free_pool, m); 69 - } 54 + m->buff_size = m->map_size = size; 55 + status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key, 56 + &m->desc_size, &m->desc_ver); 57 + if (status != EFI_SUCCESS) 58 + goto uninstall_table; 70 59 71 - fail: 72 - *map->map = m; 60 + *map = m; 61 + return EFI_SUCCESS; 62 + 63 + uninstall_table: 64 + if (install_cfg_tbl) 65 + efi_bs_call(install_configuration_table, &tbl_guid, NULL); 66 + free_map: 67 + efi_bs_call(free_pool, m); 73 68 return status; 74 69 } 75 70
+8 -17
drivers/firmware/efi/libstub/randomalloc.c
··· 55 55 unsigned long *addr, 56 56 unsigned long random_seed) 57 57 { 58 - unsigned long map_size, desc_size, total_slots = 0, target_slot; 58 + unsigned long total_slots = 0, target_slot; 59 59 unsigned long total_mirrored_slots = 0; 60 - unsigned long buff_size; 60 + struct efi_boot_memmap *map; 61 61 efi_status_t status; 62 - efi_memory_desc_t *memory_map; 63 62 int map_offset; 64 - struct efi_boot_memmap map; 65 63 66 - map.map = &memory_map; 67 - map.map_size = &map_size; 68 - map.desc_size = &desc_size; 69 - map.desc_ver = NULL; 70 - map.key_ptr = NULL; 71 - map.buff_size = &buff_size; 72 - 73 - status = efi_get_memory_map(&map); 64 + status = efi_get_memory_map(&map, false); 74 65 if (status != EFI_SUCCESS) 75 66 return status; 76 67 ··· 71 80 size = round_up(size, EFI_ALLOC_ALIGN); 72 81 73 82 /* count the suitable slots in each memory map entry */ 74 - for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { 75 - efi_memory_desc_t *md = (void *)memory_map + map_offset; 83 + for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) { 84 + efi_memory_desc_t *md = (void *)map->map + map_offset; 76 85 unsigned long slots; 77 86 78 87 slots = get_entry_num_slots(md, size, ilog2(align)); ··· 100 109 * to calculate the randomly chosen address, and allocate it directly 101 110 * using EFI_ALLOCATE_ADDRESS. 102 111 */ 103 - for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { 104 - efi_memory_desc_t *md = (void *)memory_map + map_offset; 112 + for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) { 113 + efi_memory_desc_t *md = (void *)map->map + map_offset; 105 114 efi_physical_addr_t target; 106 115 unsigned long pages; 107 116 ··· 124 133 break; 125 134 } 126 135 127 - efi_bs_call(free_pool, memory_map); 136 + efi_bs_call(free_pool, map); 128 137 129 138 return status; 130 139 }
+6 -15
drivers/firmware/efi/libstub/relocate.c
··· 23 23 efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, 24 24 unsigned long *addr, unsigned long min) 25 25 { 26 - unsigned long map_size, desc_size, buff_size; 27 - efi_memory_desc_t *map; 26 + struct efi_boot_memmap *map; 28 27 efi_status_t status; 29 28 unsigned long nr_pages; 30 29 int i; 31 - struct efi_boot_memmap boot_map; 32 30 33 - boot_map.map = &map; 34 - boot_map.map_size = &map_size; 35 - boot_map.desc_size = &desc_size; 36 - boot_map.desc_ver = NULL; 37 - boot_map.key_ptr = NULL; 38 - boot_map.buff_size = &buff_size; 39 - 40 - status = efi_get_memory_map(&boot_map); 31 + status = efi_get_memory_map(&map, false); 41 32 if (status != EFI_SUCCESS) 42 33 goto fail; 43 34 ··· 43 52 44 53 size = round_up(size, EFI_ALLOC_ALIGN); 45 54 nr_pages = size / EFI_PAGE_SIZE; 46 - for (i = 0; i < map_size / desc_size; i++) { 55 + for (i = 0; i < map->map_size / map->desc_size; i++) { 47 56 efi_memory_desc_t *desc; 48 - unsigned long m = (unsigned long)map; 57 + unsigned long m = (unsigned long)map->map; 49 58 u64 start, end; 50 59 51 - desc = efi_early_memdesc_ptr(m, desc_size, i); 60 + desc = efi_early_memdesc_ptr(m, map->desc_size, i); 52 61 53 62 if (desc->type != EFI_CONVENTIONAL_MEMORY) 54 63 continue; ··· 78 87 } 79 88 } 80 89 81 - if (i == map_size / desc_size) 90 + if (i == map->map_size / map->desc_size) 82 91 status = EFI_NOT_FOUND; 83 92 84 93 efi_bs_call(free_pool, map);
+8
drivers/firmware/efi/libstub/systable.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/efi.h> 4 + #include <asm/efi.h> 5 + 6 + #include "efistub.h" 7 + 8 + const efi_system_table_t *efi_system_table;
+12 -21
drivers/firmware/efi/libstub/x86-stub.c
··· 722 722 723 723 efi_set_u64_split((unsigned long)efi_system_table, 724 724 &p->efi->efi_systab, &p->efi->efi_systab_hi); 725 - p->efi->efi_memdesc_size = *map->desc_size; 726 - p->efi->efi_memdesc_version = *map->desc_ver; 727 - efi_set_u64_split((unsigned long)*map->map, 725 + p->efi->efi_memdesc_size = map->desc_size; 726 + p->efi->efi_memdesc_version = map->desc_ver; 727 + efi_set_u64_split((unsigned long)map->map, 728 728 &p->efi->efi_memmap, &p->efi->efi_memmap_hi); 729 - p->efi->efi_memmap_size = *map->map_size; 729 + p->efi->efi_memmap_size = map->map_size; 730 730 731 731 return EFI_SUCCESS; 732 732 } 733 733 734 734 static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) 735 735 { 736 - unsigned long map_sz, key, desc_size, buff_size; 737 - efi_memory_desc_t *mem_map; 738 736 struct setup_data *e820ext = NULL; 739 737 __u32 e820ext_size = 0; 740 738 efi_status_t status; 741 - __u32 desc_version; 742 - struct efi_boot_memmap map; 743 739 struct exit_boot_struct priv; 744 740 745 - map.map = &mem_map; 746 - map.map_size = &map_sz; 747 - map.desc_size = &desc_size; 748 - map.desc_ver = &desc_version; 749 - map.key_ptr = &key; 750 - map.buff_size = &buff_size; 751 741 priv.boot_params = boot_params; 752 742 priv.efi = &boot_params->efi_info; 753 743 ··· 746 756 return status; 747 757 748 758 /* Might as well exit boot services now */ 749 - status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func); 759 + status = efi_exit_boot_services(handle, &priv, exit_boot_func); 750 760 if (status != EFI_SUCCESS) 751 761 return status; 752 762 ··· 772 782 unsigned long bzimage_addr = (unsigned long)startup_32; 773 783 unsigned long buffer_start, buffer_end; 774 784 struct setup_header *hdr = &boot_params->hdr; 775 - unsigned long addr, size; 785 + const struct linux_efi_initrd *initrd = NULL; 776 786 efi_status_t status; 777 787 778 788 efi_system_table = sys_table_arg; ··· 867 877 * arguments will be processed only if image is not NULL, which will be 868 878 * the case only if we were loaded via the PE entry point. 869 879 */ 870 - status = efi_load_initrd(image, &addr, &size, hdr->initrd_addr_max, 871 - ULONG_MAX); 880 + status = efi_load_initrd(image, hdr->initrd_addr_max, ULONG_MAX, 881 + &initrd); 872 882 if (status != EFI_SUCCESS) 873 883 goto fail; 874 - if (size > 0) { 875 - efi_set_u64_split(addr, &hdr->ramdisk_image, 884 + if (initrd && initrd->size > 0) { 885 + efi_set_u64_split(initrd->base, &hdr->ramdisk_image, 876 886 &boot_params->ext_ramdisk_image); 877 - efi_set_u64_split(size, &hdr->ramdisk_size, 887 + efi_set_u64_split(initrd->size, &hdr->ramdisk_size, 878 888 &boot_params->ext_ramdisk_size); 879 889 } 890 + 880 891 881 892 /* 882 893 * If the boot loader gave us a value for secure_boot then we use that,
+143
drivers/firmware/efi/libstub/zboot-header.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #include <linux/pe.h> 4 + 5 + #ifdef CONFIG_64BIT 6 + .set .Lextra_characteristics, 0x0 7 + .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32PLUS 8 + #else 9 + .set .Lextra_characteristics, IMAGE_FILE_32BIT_MACHINE 10 + .set .Lpe_opt_magic, PE_OPT_MAGIC_PE32 11 + #endif 12 + 13 + .section ".head", "a" 14 + .globl __efistub_efi_zboot_header 15 + __efistub_efi_zboot_header: 16 + .Ldoshdr: 17 + .long MZ_MAGIC 18 + .ascii "zimg" // image type 19 + .long __efistub__gzdata_start - .Ldoshdr // payload offset 20 + .long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size 21 + .long 0, 0 // reserved 22 + .asciz COMP_TYPE // compression type 23 + .org .Ldoshdr + 0x3c 24 + .long .Lpehdr - .Ldoshdr // PE header offset 25 + 26 + .Lpehdr: 27 + .long PE_MAGIC 28 + .short MACHINE_TYPE 29 + .short .Lsection_count 30 + .long 0 31 + .long 0 32 + .long 0 33 + .short .Lsection_table - .Loptional_header 34 + .short IMAGE_FILE_DEBUG_STRIPPED | \ 35 + IMAGE_FILE_EXECUTABLE_IMAGE | \ 36 + IMAGE_FILE_LINE_NUMS_STRIPPED |\ 37 + .Lextra_characteristics 38 + 39 + .Loptional_header: 40 + .short .Lpe_opt_magic 41 + .byte 0, 0 42 + .long _etext - .Lefi_header_end 43 + .long __data_size 44 + .long 0 45 + .long __efistub_efi_zboot_entry - .Ldoshdr 46 + .long .Lefi_header_end - .Ldoshdr 47 + 48 + #ifdef CONFIG_64BIT 49 + .quad 0 50 + #else 51 + .long _etext - .Ldoshdr, 0x0 52 + #endif 53 + .long 4096 54 + .long 512 55 + .short 0, 0 56 + .short LINUX_EFISTUB_MAJOR_VERSION // MajorImageVersion 57 + .short LINUX_EFISTUB_MINOR_VERSION // MinorImageVersion 58 + .short 0, 0 59 + .long 0 60 + .long _end - .Ldoshdr 61 + 62 + .long .Lefi_header_end - .Ldoshdr 63 + .long 0 64 + .short IMAGE_SUBSYSTEM_EFI_APPLICATION 65 + .short 0 66 + #ifdef CONFIG_64BIT 67 + .quad 0, 0, 0, 0 68 + #else 69 + .long 0, 0, 0, 0 70 + #endif 71 + .long 0 72 + .long (.Lsection_table - .) / 8 73 + 74 + .quad 0 // ExportTable 75 + .quad 0 // ImportTable 76 + .quad 0 // ResourceTable 77 + .quad 0 // ExceptionTable 78 + .quad 0 // CertificationTable 79 + .quad 0 // BaseRelocationTable 80 + #ifdef CONFIG_DEBUG_EFI 81 + .long .Lefi_debug_table - .Ldoshdr // DebugTable 82 + .long .Lefi_debug_table_size 83 + #endif 84 + 85 + .Lsection_table: 86 + .ascii ".text\0\0\0" 87 + .long _etext - .Lefi_header_end 88 + .long .Lefi_header_end - .Ldoshdr 89 + .long _etext - .Lefi_header_end 90 + .long .Lefi_header_end - .Ldoshdr 91 + 92 + .long 0, 0 93 + .short 0, 0 94 + .long IMAGE_SCN_CNT_CODE | \ 95 + IMAGE_SCN_MEM_READ | \ 96 + IMAGE_SCN_MEM_EXECUTE 97 + 98 + .ascii ".data\0\0\0" 99 + .long __data_size 100 + .long _etext - .Ldoshdr 101 + .long __data_rawsize 102 + .long _etext - .Ldoshdr 103 + 104 + .long 0, 0 105 + .short 0, 0 106 + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 107 + IMAGE_SCN_MEM_READ | \ 108 + IMAGE_SCN_MEM_WRITE 109 + 110 + .set .Lsection_count, (. - .Lsection_table) / 40 111 + 112 + #ifdef CONFIG_DEBUG_EFI 113 + .section ".rodata", "a" 114 + .align 2 115 + .Lefi_debug_table: 116 + // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY 117 + .long 0 // Characteristics 118 + .long 0 // TimeDateStamp 119 + .short 0 // MajorVersion 120 + .short 0 // MinorVersion 121 + .long IMAGE_DEBUG_TYPE_CODEVIEW // Type 122 + .long .Lefi_debug_entry_size // SizeOfData 123 + .long 0 // RVA 124 + .long .Lefi_debug_entry - .Ldoshdr // FileOffset 125 + 126 + .set .Lefi_debug_table_size, . - .Lefi_debug_table 127 + .previous 128 + 129 + .Lefi_debug_entry: 130 + // EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY 131 + .ascii "NB10" // Signature 132 + .long 0 // Unknown 133 + .long 0 // Unknown2 134 + .long 0 // Unknown3 135 + 136 + .asciz ZBOOT_EFI_PATH 137 + 138 + .set .Lefi_debug_entry_size, . - .Lefi_debug_entry 139 + #endif 140 + 141 + .p2align 12 142 + .Lefi_header_end: 143 +
+302
drivers/firmware/efi/libstub/zboot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/efi.h> 4 + #include <linux/pe.h> 5 + #include <asm/efi.h> 6 + #include <asm/unaligned.h> 7 + 8 + #include "efistub.h" 9 + 10 + static unsigned char zboot_heap[SZ_256K] __aligned(64); 11 + static unsigned long free_mem_ptr, free_mem_end_ptr; 12 + 13 + #define STATIC static 14 + #if defined(CONFIG_KERNEL_GZIP) 15 + #include "../../../../lib/decompress_inflate.c" 16 + #elif defined(CONFIG_KERNEL_LZ4) 17 + #include "../../../../lib/decompress_unlz4.c" 18 + #elif defined(CONFIG_KERNEL_LZMA) 19 + #include "../../../../lib/decompress_unlzma.c" 20 + #elif defined(CONFIG_KERNEL_LZO) 21 + #include "../../../../lib/decompress_unlzo.c" 22 + #elif defined(CONFIG_KERNEL_XZ) 23 + #undef memcpy 24 + #define memcpy memcpy 25 + #undef memmove 26 + #define memmove memmove 27 + #include "../../../../lib/decompress_unxz.c" 28 + #elif defined(CONFIG_KERNEL_ZSTD) 29 + #include "../../../../lib/decompress_unzstd.c" 30 + #endif 31 + 32 + extern char efi_zboot_header[]; 33 + extern char _gzdata_start[], _gzdata_end[]; 34 + 35 + static void log(efi_char16_t str[]) 36 + { 37 + efi_call_proto(efi_table_attr(efi_system_table, con_out), 38 + output_string, L"EFI decompressor: "); 39 + efi_call_proto(efi_table_attr(efi_system_table, con_out), 40 + output_string, str); 41 + efi_call_proto(efi_table_attr(efi_system_table, con_out), 42 + output_string, L"\n"); 43 + } 44 + 45 + static void error(char *x) 46 + { 47 + log(L"error() called from decompressor library\n"); 48 + } 49 + 50 + // Local version to avoid pulling in memcmp() 51 + static bool guids_eq(const efi_guid_t *a, const efi_guid_t *b) 52 + { 53 + const u32 *l = (u32 *)a; 54 + const u32 *r = (u32 *)b; 55 + 56 + return l[0] == r[0] && l[1] == r[1] && l[2] == r[2] && l[3] == r[3]; 57 + } 58 + 59 + static efi_status_t __efiapi 60 + load_file(efi_load_file_protocol_t *this, efi_device_path_protocol_t *rem, 61 + bool boot_policy, unsigned long *bufsize, void *buffer) 62 + { 63 + unsigned long compressed_size = _gzdata_end - _gzdata_start; 64 + struct efi_vendor_dev_path *vendor_dp; 65 + bool decompress = false; 66 + unsigned long size; 67 + int ret; 68 + 69 + if (rem == NULL || bufsize == NULL) 70 + return EFI_INVALID_PARAMETER; 71 + 72 + if (boot_policy) 73 + return EFI_UNSUPPORTED; 74 + 75 + // Look for our vendor media device node in the remaining file path 76 + if (rem->type == EFI_DEV_MEDIA && 77 + rem->sub_type == EFI_DEV_MEDIA_VENDOR) { 78 + vendor_dp = container_of(rem, struct efi_vendor_dev_path, header); 79 + if (!guids_eq(&vendor_dp->vendorguid, &LINUX_EFI_ZBOOT_MEDIA_GUID)) 80 + return EFI_NOT_FOUND; 81 + 82 + decompress = true; 83 + rem = (void *)(vendor_dp + 1); 84 + } 85 + 86 + if (rem->type != EFI_DEV_END_PATH || 87 + rem->sub_type != EFI_DEV_END_ENTIRE) 88 + return EFI_NOT_FOUND; 89 + 90 + // The uncompressed size of the payload is appended to the raw bit 91 + // stream, and may therefore appear misaligned in memory 92 + size = decompress ? get_unaligned_le32(_gzdata_end - 4) 93 + : compressed_size; 94 + if (buffer == NULL || *bufsize < size) { 95 + *bufsize = size; 96 + return EFI_BUFFER_TOO_SMALL; 97 + } 98 + 99 + if (decompress) { 100 + ret = __decompress(_gzdata_start, compressed_size, NULL, NULL, 101 + buffer, size, NULL, error); 102 + if (ret < 0) { 103 + log(L"Decompression failed"); 104 + return EFI_DEVICE_ERROR; 105 + } 106 + } else { 107 + memcpy(buffer, _gzdata_start, compressed_size); 108 + } 109 + 110 + return EFI_SUCCESS; 111 + } 112 + 113 + // Return the length in bytes of the device path up to the first end node. 114 + static int device_path_length(const efi_device_path_protocol_t *dp) 115 + { 116 + int len = 0; 117 + 118 + while (dp->type != EFI_DEV_END_PATH) { 119 + len += dp->length; 120 + dp = (void *)((u8 *)dp + dp->length); 121 + } 122 + return len; 123 + } 124 + 125 + static void append_rel_offset_node(efi_device_path_protocol_t **dp, 126 + unsigned long start, unsigned long end) 127 + { 128 + struct efi_rel_offset_dev_path *rodp = (void *)*dp; 129 + 130 + rodp->header.type = EFI_DEV_MEDIA; 131 + rodp->header.sub_type = EFI_DEV_MEDIA_REL_OFFSET; 132 + rodp->header.length = sizeof(struct efi_rel_offset_dev_path); 133 + rodp->reserved = 0; 134 + rodp->starting_offset = start; 135 + rodp->ending_offset = end; 136 + 137 + *dp = (void *)(rodp + 1); 138 + } 139 + 140 + static void append_ven_media_node(efi_device_path_protocol_t **dp, 141 + efi_guid_t *guid) 142 + { 143 + struct efi_vendor_dev_path *vmdp = (void *)*dp; 144 + 145 + vmdp->header.type = EFI_DEV_MEDIA; 146 + vmdp->header.sub_type = EFI_DEV_MEDIA_VENDOR; 147 + vmdp->header.length = sizeof(struct efi_vendor_dev_path); 148 + vmdp->vendorguid = *guid; 149 + 150 + *dp = (void *)(vmdp + 1); 151 + } 152 + 153 + static void append_end_node(efi_device_path_protocol_t **dp) 154 + { 155 + (*dp)->type = EFI_DEV_END_PATH; 156 + (*dp)->sub_type = EFI_DEV_END_ENTIRE; 157 + (*dp)->length = sizeof(struct efi_generic_dev_path); 158 + 159 + ++*dp; 160 + } 161 + 162 + asmlinkage efi_status_t __efiapi 163 + efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) 164 + { 165 + struct efi_mem_mapped_dev_path mmdp = { 166 + .header.type = EFI_DEV_HW, 167 + .header.sub_type = EFI_DEV_MEM_MAPPED, 168 + .header.length = sizeof(struct efi_mem_mapped_dev_path) 169 + }; 170 + efi_device_path_protocol_t *parent_dp, *dpp, *lf2_dp, *li_dp; 171 + efi_load_file2_protocol_t zboot_load_file2; 172 + efi_loaded_image_t *parent, *child; 173 + unsigned long exit_data_size; 174 + efi_handle_t child_handle; 175 + efi_handle_t zboot_handle; 176 + efi_char16_t *exit_data; 177 + efi_status_t status; 178 + void *dp_alloc; 179 + int dp_len; 180 + 181 + WRITE_ONCE(efi_system_table, systab); 182 + 183 + free_mem_ptr = (unsigned long)&zboot_heap; 184 + free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap); 185 + 186 + exit_data = NULL; 187 + exit_data_size = 0; 188 + 189 + status = efi_bs_call(handle_protocol, handle, 190 + &LOADED_IMAGE_PROTOCOL_GUID, (void **)&parent); 191 + if (status != EFI_SUCCESS) { 192 + log(L"Failed to locate parent's loaded image protocol"); 193 + return status; 194 + } 195 + 196 + status = efi_bs_call(handle_protocol, handle, 197 + &LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID, 198 + (void **)&parent_dp); 199 + if (status != EFI_SUCCESS || parent_dp == NULL) { 200 + // Create a MemoryMapped() device path node to describe 201 + // the parent image if no device path was provided. 202 + mmdp.memory_type = parent->image_code_type; 203 + mmdp.starting_addr = (unsigned long)parent->image_base; 204 + mmdp.ending_addr = (unsigned long)parent->image_base + 205 + parent->image_size - 1; 206 + parent_dp = &mmdp.header; 207 + dp_len = sizeof(mmdp); 208 + } else { 209 + dp_len = device_path_length(parent_dp); 210 + } 211 + 212 + // Allocate some pool memory for device path protocol data 213 + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, 214 + 2 * (dp_len + sizeof(struct efi_rel_offset_dev_path) + 215 + sizeof(struct efi_generic_dev_path)) + 216 + sizeof(struct efi_vendor_dev_path), 217 + (void **)&dp_alloc); 218 + if (status != EFI_SUCCESS) { 219 + log(L"Failed to allocate device path pool memory"); 220 + return status; 221 + } 222 + 223 + // Create a device path describing the compressed payload in this image 224 + // <...parent_dp...>/Offset(<start>, <end>) 225 + lf2_dp = memcpy(dp_alloc, parent_dp, dp_len); 226 + dpp = (void *)((u8 *)lf2_dp + dp_len); 227 + append_rel_offset_node(&dpp, 228 + (unsigned long)(_gzdata_start - efi_zboot_header), 229 + (unsigned long)(_gzdata_end - efi_zboot_header - 1)); 230 + append_end_node(&dpp); 231 + 232 + // Create a device path describing the decompressed payload in this image 233 + // <...parent_dp...>/Offset(<start>, <end>)/VenMedia(ZBOOT_MEDIA_GUID) 234 + dp_len += sizeof(struct efi_rel_offset_dev_path); 235 + li_dp = memcpy(dpp, lf2_dp, dp_len); 236 + dpp = (void *)((u8 *)li_dp + dp_len); 237 + append_ven_media_node(&dpp, &LINUX_EFI_ZBOOT_MEDIA_GUID); 238 + append_end_node(&dpp); 239 + 240 + zboot_handle = NULL; 241 + zboot_load_file2.load_file = load_file; 242 + status = efi_bs_call(install_multiple_protocol_interfaces, 243 + &zboot_handle, 244 + &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp, 245 + &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2, 246 + NULL); 247 + if (status != EFI_SUCCESS) { 248 + log(L"Failed to install LoadFile2 protocol and device path"); 249 + goto free_dpalloc; 250 + } 251 + 252 + status = efi_bs_call(load_image, false, handle, li_dp, NULL, 0, 253 + &child_handle); 254 + if (status != EFI_SUCCESS) { 255 + log(L"Failed to load image"); 256 + goto uninstall_lf2; 257 + } 258 + 259 + status = efi_bs_call(handle_protocol, child_handle, 260 + &LOADED_IMAGE_PROTOCOL_GUID, (void **)&child); 261 + if (status != EFI_SUCCESS) { 262 + log(L"Failed to locate child's loaded image protocol"); 263 + goto unload_image; 264 + } 265 + 266 + // Copy the kernel command line 267 + child->load_options = parent->load_options; 268 + child->load_options_size = parent->load_options_size; 269 + 270 + status = efi_bs_call(start_image, child_handle, &exit_data_size, 271 + &exit_data); 272 + if (status != EFI_SUCCESS) { 273 + log(L"StartImage() returned with error"); 274 + if (exit_data_size > 0) 275 + log(exit_data); 276 + 277 + // If StartImage() returns EFI_SECURITY_VIOLATION, the image is 278 + // not unloaded so we need to do it by hand. 279 + if (status == EFI_SECURITY_VIOLATION) 280 + unload_image: 281 + efi_bs_call(unload_image, child_handle); 282 + } 283 + 284 + uninstall_lf2: 285 + efi_bs_call(uninstall_multiple_protocol_interfaces, 286 + zboot_handle, 287 + &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp, 288 + &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2, 289 + NULL); 290 + 291 + free_dpalloc: 292 + efi_bs_call(free_pool, dp_alloc); 293 + 294 + efi_bs_call(exit, handle, status, exit_data_size, exit_data); 295 + 296 + // Free ExitData in case Exit() returned with a failure code, 297 + // but return the original status code. 298 + log(L"Exit() returned with failure code"); 299 + if (exit_data != NULL) 300 + efi_bs_call(free_pool, exit_data); 301 + return status; 302 + }
+44
drivers/firmware/efi/libstub/zboot.lds
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + ENTRY(__efistub_efi_zboot_header); 4 + 5 + SECTIONS 6 + { 7 + .head : ALIGN(4096) { 8 + *(.head) 9 + } 10 + 11 + .text : { 12 + *(.text* .init.text*) 13 + } 14 + 15 + .rodata : ALIGN(8) { 16 + __efistub__gzdata_start = .; 17 + *(.gzdata) 18 + __efistub__gzdata_end = .; 19 + *(.rodata* .init.rodata* .srodata*) 20 + _etext = ALIGN(4096); 21 + . = _etext; 22 + } 23 + 24 + .data : ALIGN(4096) { 25 + *(.data* .init.data*) 26 + _edata = ALIGN(512); 27 + . = _edata; 28 + } 29 + 30 + .bss : { 31 + *(.bss* .init.bss*) 32 + _end = ALIGN(512); 33 + . = _end; 34 + } 35 + 36 + /DISCARD/ : { 37 + *(.modinfo .init.modinfo) 38 + } 39 + } 40 + 41 + PROVIDE(__efistub__gzdata_size = ABSOLUTE(. - __efistub__gzdata_start)); 42 + 43 + PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext)); 44 + PROVIDE(__data_size = ABSOLUTE(_end - _etext));
+35
include/linux/efi.h
··· 368 368 #define UV_SYSTEM_TABLE_GUID EFI_GUID(0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93) 369 369 #define LINUX_EFI_CRASH_GUID EFI_GUID(0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0) 370 370 #define LOADED_IMAGE_PROTOCOL_GUID EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) 371 + #define LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID EFI_GUID(0xbc62157e, 0x3e33, 0x4fec, 0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf) 372 + #define EFI_DEVICE_PATH_PROTOCOL_GUID EFI_GUID(0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) 373 + #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c) 371 374 #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) 372 375 #define EFI_UGA_PROTOCOL_GUID EFI_GUID(0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39) 373 376 #define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a) ··· 411 408 #define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) 412 409 #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) 413 410 #define LINUX_EFI_INITRD_MEDIA_GUID EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68) 411 + #define LINUX_EFI_ZBOOT_MEDIA_GUID EFI_GUID(0xe565a30d, 0x47da, 0x4dbd, 0xb3, 0x54, 0x9b, 0xb5, 0xc8, 0x4f, 0x8b, 0xe2) 414 412 #define LINUX_EFI_MOK_VARIABLE_TABLE_GUID EFI_GUID(0xc451ed2b, 0x9694, 0x45d3, 0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89) 415 413 #define LINUX_EFI_COCO_SECRET_AREA_GUID EFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47) 414 + #define LINUX_EFI_BOOT_MEMMAP_GUID EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4) 416 415 417 416 #define RISCV_EFI_BOOT_PROTOCOL_GUID EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf) 418 417 ··· 522 517 }; 523 518 efi_system_table_32_t mixed_mode; 524 519 } efi_system_table_t; 520 + 521 + struct efi_boot_memmap { 522 + unsigned long map_size; 523 + unsigned long desc_size; 524 + u32 desc_ver; 525 + unsigned long map_key; 526 + unsigned long buff_size; 527 + efi_memory_desc_t map[]; 528 + }; 525 529 526 530 /* 527 531 * Architecture independent structure for describing a memory map for the ··· 966 952 #define EFI_DEV_MEDIA_VENDOR 3 967 953 #define EFI_DEV_MEDIA_FILE 4 968 954 #define EFI_DEV_MEDIA_PROTOCOL 5 955 + #define EFI_DEV_MEDIA_REL_OFFSET 8 969 956 #define EFI_DEV_BIOS_BOOT 0x05 970 957 #define EFI_DEV_END_PATH 0x7F 971 958 #define EFI_DEV_END_PATH2 0xFF ··· 997 982 u8 vendordata[]; 998 983 } __packed; 999 984 985 + struct efi_rel_offset_dev_path { 986 + struct efi_generic_dev_path header; 987 + u32 reserved; 988 + u64 starting_offset; 989 + u64 ending_offset; 990 + } __packed; 991 + 992 + struct efi_mem_mapped_dev_path { 993 + struct efi_generic_dev_path header; 994 + u32 memory_type; 995 + u64 starting_addr; 996 + u64 ending_addr; 997 + } __packed; 998 + 1000 999 struct efi_dev_path { 1001 1000 union { 1002 1001 struct efi_generic_dev_path header; 1003 1002 struct efi_acpi_dev_path acpi; 1004 1003 struct efi_pci_dev_path pci; 1005 1004 struct efi_vendor_dev_path vendor; 1005 + struct efi_rel_offset_dev_path rel_offset; 1006 1006 }; 1007 1007 } __packed; 1008 1008 ··· 1349 1319 struct linux_efi_coco_secret_area { 1350 1320 u64 base_pa; 1351 1321 u64 size; 1322 + }; 1323 + 1324 + struct linux_efi_initrd { 1325 + unsigned long base; 1326 + unsigned long size; 1352 1327 }; 1353 1328 1354 1329 /* Header of a populated EFI secret area */
+2
include/linux/pe.h
··· 65 65 #define IMAGE_FILE_MACHINE_SH5 0x01a8 66 66 #define IMAGE_FILE_MACHINE_THUMB 0x01c2 67 67 #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 68 + #define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232 69 + #define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 68 70 69 71 /* flags */ 70 72 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001