aboutsummaryrefslogtreecommitdiff
path: root/arch/loongarch/kernel
diff options
context:
space:
mode:
authorArd Biesheuvel2022-09-16 19:48:53 +0200
committerArd Biesheuvel2022-09-27 13:22:49 +0200
commit40cd01a9c324bd238e107d9d5ecb6824146a7836 (patch)
treeb7b4c48c8da21e7429e6aaded84fd6ad563fbad3 /arch/loongarch/kernel
parent171539f5a90e3fdf7d17f5396fac79d7e44ad68e (diff)
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>
Diffstat (limited to 'arch/loongarch/kernel')
-rw-r--r--arch/loongarch/kernel/efi.c30
-rw-r--r--arch/loongarch/kernel/env.c13
-rw-r--r--arch/loongarch/kernel/head.S2
-rw-r--r--arch/loongarch/kernel/setup.c4
4 files changed, 37 insertions, 12 deletions
diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
index 1f1f755fb425..a31329971133 100644
--- a/arch/loongarch/kernel/efi.c
+++ b/arch/loongarch/kernel/efi.c
@@ -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));
+ }
}
diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c
index 82b478a5c665..6d56a463b091 100644
--- a/arch/loongarch/kernel/env.c
+++ b/arch/loongarch/kernel/env.c
@@ -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)
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S
index 01bac62a6442..8f89f39fd31b 100644
--- a/arch/loongarch/kernel/head.S
+++ b/arch/loongarch/kernel/head.S
@@ -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
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
index e8714b1d94c8..7fabf2306e80 100644
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -51,7 +51,7 @@
struct screen_info screen_info __section(".data");
-unsigned long fw_arg0, fw_arg1;
+unsigned long fw_arg0, fw_arg1, fw_arg2;
DEFINE_PER_CPU(unsigned long, kernelsp);
struct cpuinfo_loongarch cpu_data[NR_CPUS] __read_mostly;
@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);
void __init platform_init(void)
{
- efi_init();
#ifdef CONFIG_ACPI_TABLE_UPGRADE
acpi_table_upgrade();
#endif
@@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p)
*cmdline_p = boot_command_line;
init_environ();
+ efi_init();
memblock_init();
parse_early_param();