Commit 40cd01a9 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

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: default avatarArd Biesheuvel <ardb@kernel.org>
Acked-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 171539f5
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -104,8 +104,6 @@ config LOONGARCH
	select MODULES_USE_ELF_RELA if MODULES
	select NEED_PER_CPU_EMBED_FIRST_CHUNK
	select NEED_PER_CPU_PAGE_FIRST_CHUNK
	select OF
	select OF_EARLY_FLATTREE
	select PCI
	select PCI_DOMAINS_GENERIC
	select PCI_ECAM if ACPI
@@ -311,7 +309,6 @@ config DMI
config EFI
	bool "EFI runtime service support"
	select UCS2_STRING
	select EFI_PARAMS_FROM_FDT
	select EFI_RUNTIME_WRAPPERS
	help
	  This enables the kernel to use EFI runtime services that are
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ struct loongson_system_configuration {
};

extern u64 efi_system_table;
extern unsigned long fw_arg0, fw_arg1;
extern unsigned long fw_arg0, fw_arg1, fw_arg2;
extern struct loongson_board_info b_info;
extern struct loongson_system_configuration loongson_sysconf;

+29 −1
Original line number Diff line number Diff line
@@ -27,8 +27,13 @@
static unsigned long efi_nr_tables;
static unsigned long efi_config_table;

static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;

static efi_system_table_t *efi_systab;
static efi_config_table_type_t arch_tables[] __initdata = {{},};
static efi_config_table_type_t arch_tables[] __initdata = {
	{LINUX_EFI_BOOT_MEMMAP_GUID,	&boot_memmap,	"MEMMAP" },
	{},
};

void __init efi_runtime_init(void)
{
@@ -51,6 +56,7 @@ void __init efi_init(void)
{
	int size;
	void *config_tables;
	struct efi_boot_memmap *tbl;

	if (!efi_system_table)
		return;
@@ -61,6 +67,8 @@ void __init efi_init(void)
		return;
	}

	efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor);

	set_bit(EFI_64BIT, &efi.flags);
	efi_nr_tables	 = efi_systab->nr_tables;
	efi_config_table = (unsigned long)efi_systab->tables;
@@ -70,6 +78,26 @@ void __init efi_init(void)
	efi_config_parse_tables(config_tables, efi_systab->nr_tables, arch_tables);
	early_memunmap(config_tables, efi_nr_tables * size);

	set_bit(EFI_CONFIG_TABLES, &efi.flags);

	if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI)
		memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);

	if (boot_memmap == EFI_INVALID_TABLE_ADDR)
		return;

	tbl = early_memremap_ro(boot_memmap, sizeof(*tbl));
	if (tbl) {
		struct efi_memory_map_data data;

		data.phys_map		= boot_memmap + sizeof(*tbl);
		data.size		= tbl->map_size;
		data.desc_size		= tbl->desc_size;
		data.desc_version	= tbl->desc_ver;

		if (efi_memmap_init_early(&data) < 0)
			panic("Unable to map EFI memory map.\n");

		early_memunmap(tbl, sizeof(*tbl));
	}
}
+4 −9
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@
#include <linux/efi.h>
#include <linux/export.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <asm/early_ioremap.h>
#include <asm/bootinfo.h>
#include <asm/loongson.h>
@@ -20,21 +19,17 @@ EXPORT_SYMBOL(loongson_sysconf);
void __init init_environ(void)
{
	int efi_boot = fw_arg0;
	struct efi_memory_map_data data;
	void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
	char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE);

	if (efi_boot)
		set_bit(EFI_BOOT, &efi.flags);
	else
		clear_bit(EFI_BOOT, &efi.flags);

	early_init_dt_scan(fdt_ptr);
	early_init_fdt_reserve_self();
	efi_system_table = efi_get_fdt_params(&data);
	strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
	early_memunmap(cmdline, COMMAND_LINE_SIZE);

	efi_memmap_init_early(&data);
	memblock_reserve(data.phys_map & PAGE_MASK,
			 PAGE_ALIGN(data.size + (data.phys_map & ~PAGE_MASK)));
	efi_system_table = fw_arg2;
}

static int __init init_cpu_fullname(void)
+2 −0
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point
	st.d		a0, t0, 0		# firmware arguments
	la		t0, fw_arg1
	st.d		a1, t0, 0
	la		t0, fw_arg2
	st.d		a2, t0, 0

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