Skip to content

Commit 40cd01a

Browse files
committed
efi/loongarch: libstub: remove dependency on flattened DT
LoongArch does not use FDT or DT natively [yet], and the only reason it currently uses it is so that it can reuse the existing EFI stub code. Overloading the DT with data passed between the EFI stub and the core kernel has been a source of problems: there is the overlap between information provided by EFI which DT can also provide (initrd base/size, command line, memory descriptions), requiring us to reason about which is which and what to prioritize. It has also resulted in ABI leaks, i.e., internal ABI being promoted to external ABI inadvertently because the bootloader can set the EFI stub's DT properties as well (e.g., "kaslr-seed"). This has become especially problematic with boot environments that want to pretend that EFI boot is being done (to access ACPI and SMBIOS tables, for instance) but have no ability to execute the EFI stub, and so the environment that the EFI stub creates is emulated [poorly, in some cases]. Another downside of treating DT like this is that the DT binary that the kernel receives is different from the one created by the firmware, which is undesirable in the context of secure and measured boot. Given that LoongArch support in Linux is brand new, we can avoid these pitfalls, and treat the DT strictly as a hardware description, and use a separate handover method between the EFI stub and the kernel. Now that initrd loading and passing the EFI memory map have been refactored into pure EFI routines that use EFI configuration tables, the only thing we need to pass directly is the kernel command line (even if we could pass this via a config table as well, it is used extremely early, so passing it directly is preferred in this case.) Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 171539f commit 40cd01a

8 files changed

Lines changed: 95 additions & 28 deletions

File tree

arch/loongarch/Kconfig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ config LOONGARCH
104104
select MODULES_USE_ELF_RELA if MODULES
105105
select NEED_PER_CPU_EMBED_FIRST_CHUNK
106106
select NEED_PER_CPU_PAGE_FIRST_CHUNK
107-
select OF
108-
select OF_EARLY_FLATTREE
109107
select PCI
110108
select PCI_DOMAINS_GENERIC
111109
select PCI_ECAM if ACPI
@@ -311,7 +309,6 @@ config DMI
311309
config EFI
312310
bool "EFI runtime service support"
313311
select UCS2_STRING
314-
select EFI_PARAMS_FROM_FDT
315312
select EFI_RUNTIME_WRAPPERS
316313
help
317314
This enables the kernel to use EFI runtime services that are

arch/loongarch/include/asm/bootinfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct loongson_system_configuration {
3636
};
3737

3838
extern u64 efi_system_table;
39-
extern unsigned long fw_arg0, fw_arg1;
39+
extern unsigned long fw_arg0, fw_arg1, fw_arg2;
4040
extern struct loongson_board_info b_info;
4141
extern struct loongson_system_configuration loongson_sysconf;
4242

arch/loongarch/kernel/efi.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
static unsigned long efi_nr_tables;
2828
static unsigned long efi_config_table;
2929

30+
static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;
31+
3032
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+
};
3237

3338
void __init efi_runtime_init(void)
3439
{
@@ -51,6 +56,7 @@ void __init efi_init(void)
5156
{
5257
int size;
5358
void *config_tables;
59+
struct efi_boot_memmap *tbl;
5460

5561
if (!efi_system_table)
5662
return;
@@ -61,6 +67,8 @@ void __init efi_init(void)
6167
return;
6268
}
6369

70+
efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor);
71+
6472
set_bit(EFI_64BIT, &efi.flags);
6573
efi_nr_tables = efi_systab->nr_tables;
6674
efi_config_table = (unsigned long)efi_systab->tables;
@@ -70,6 +78,26 @@ void __init efi_init(void)
7078
efi_config_parse_tables(config_tables, efi_systab->nr_tables, arch_tables);
7179
early_memunmap(config_tables, efi_nr_tables * size);
7280

81+
set_bit(EFI_CONFIG_TABLES, &efi.flags);
82+
7383
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI)
7484
memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
85+
86+
if (boot_memmap == EFI_INVALID_TABLE_ADDR)
87+
return;
88+
89+
tbl = early_memremap_ro(boot_memmap, sizeof(*tbl));
90+
if (tbl) {
91+
struct efi_memory_map_data data;
92+
93+
data.phys_map = boot_memmap + sizeof(*tbl);
94+
data.size = tbl->map_size;
95+
data.desc_size = tbl->desc_size;
96+
data.desc_version = tbl->desc_ver;
97+
98+
if (efi_memmap_init_early(&data) < 0)
99+
panic("Unable to map EFI memory map.\n");
100+
101+
early_memunmap(tbl, sizeof(*tbl));
102+
}
75103
}

arch/loongarch/kernel/env.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include <linux/efi.h>
99
#include <linux/export.h>
1010
#include <linux/memblock.h>
11-
#include <linux/of_fdt.h>
1211
#include <asm/early_ioremap.h>
1312
#include <asm/bootinfo.h>
1413
#include <asm/loongson.h>
@@ -20,21 +19,17 @@ EXPORT_SYMBOL(loongson_sysconf);
2019
void __init init_environ(void)
2120
{
2221
int efi_boot = fw_arg0;
23-
struct efi_memory_map_data data;
24-
void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
22+
char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE);
2523

2624
if (efi_boot)
2725
set_bit(EFI_BOOT, &efi.flags);
2826
else
2927
clear_bit(EFI_BOOT, &efi.flags);
3028

31-
early_init_dt_scan(fdt_ptr);
32-
early_init_fdt_reserve_self();
33-
efi_system_table = efi_get_fdt_params(&data);
29+
strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
30+
early_memunmap(cmdline, COMMAND_LINE_SIZE);
3431

35-
efi_memmap_init_early(&data);
36-
memblock_reserve(data.phys_map & PAGE_MASK,
37-
PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK)));
32+
efi_system_table = fw_arg2;
3833
}
3934

4035
static int __init init_cpu_fullname(void)

arch/loongarch/kernel/head.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point
6767
st.d a0, t0, 0 # firmware arguments
6868
la t0, fw_arg1
6969
st.d a1, t0, 0
70+
la t0, fw_arg2
71+
st.d a2, t0, 0
7072

7173
/* KSave3 used for percpu base, initialized as 0 */
7274
csrwr zero, PERCPU_BASE_KS

arch/loongarch/kernel/setup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
struct screen_info screen_info __section(".data");
5353

54-
unsigned long fw_arg0, fw_arg1;
54+
unsigned long fw_arg0, fw_arg1, fw_arg2;
5555
DEFINE_PER_CPU(unsigned long, kernelsp);
5656
struct cpuinfo_loongarch cpu_data[NR_CPUS] __read_mostly;
5757

@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);
187187

188188
void __init platform_init(void)
189189
{
190-
efi_init();
191190
#ifdef CONFIG_ACPI_TABLE_UPGRADE
192191
acpi_table_upgrade();
193192
#endif
@@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p)
347346
*cmdline_p = boot_command_line;
348347

349348
init_environ();
349+
efi_init();
350350
memblock_init();
351351
parse_early_param();
352352

drivers/firmware/efi/libstub/Makefile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
2929
cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
3030
-fpie
3131

32-
cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
32+
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
3333

3434
KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
3535
-include $(srctree)/include/linux/hidden.h \
@@ -59,14 +59,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
5959
skip_spaces.o lib-cmdline.o lib-ctype.o \
6060
alignedmem.o relocate.o vsprintf.o
6161

62-
# include the stub's generic dependencies from lib/ when building for ARM/arm64
63-
efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
62+
# include the stub's libfdt dependencies from lib/ when needed
63+
libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \
64+
fdt_empty_tree.c fdt_sw.c
65+
66+
lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \
67+
$(patsubst %.c,lib-%.o,$(libfdt-deps))
6468

6569
$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
6670
$(call if_changed_rule,cc_o_c)
6771

68-
lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o \
69-
$(patsubst %.c,lib-%.o,$(efi-deps-y))
72+
lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o
7073

7174
lib-$(CONFIG_ARM) += arm32-stub.o
7275
lib-$(CONFIG_ARM64) += arm64-stub.o

drivers/firmware/efi/libstub/loongarch-stub.c

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#include <asm/addrspace.h>
1010
#include "efistub.h"
1111

12-
typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long fdt);
12+
typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline,
13+
unsigned long systab);
1314

1415
extern int kernel_asize;
1516
extern int kernel_fsize;
@@ -42,19 +43,60 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
4243
return status;
4344
}
4445

45-
void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, unsigned long fdt_size)
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)
4668
{
4769
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);
4892

4993
/* Config Direct Mapping */
5094
csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
5195
csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
5296

5397
real_kernel_entry = (kernel_entry_t)
54-
((unsigned long)&kernel_entry - entrypoint + VMLINUX_LOAD_ADDRESS);
98+
((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS);
5599

56-
if (!efi_novamap)
57-
real_kernel_entry(true, fdt);
58-
else
59-
real_kernel_entry(false, fdt);
100+
real_kernel_entry(true, (unsigned long)cmdline_ptr,
101+
(unsigned long)efi_system_table);
60102
}

0 commit comments

Comments
 (0)