2022-05-31 06:04:11 -04:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* EFI initialization
|
|
|
|
*
|
|
|
|
* Author: Jianmin Lv <lvjianmin@loongson.cn>
|
|
|
|
* Huacai Chen <chenhuacai@loongson.cn>
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/acpi.h>
|
|
|
|
#include <linux/efi.h>
|
|
|
|
#include <linux/efi-bgrt.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/export.h>
|
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/kobject.h>
|
|
|
|
#include <linux/memblock.h>
|
|
|
|
#include <linux/reboot.h>
|
2023-07-06 06:42:14 -04:00
|
|
|
#include <linux/screen_info.h>
|
2022-05-31 06:04:11 -04:00
|
|
|
#include <linux/uaccess.h>
|
|
|
|
|
|
|
|
#include <asm/early_ioremap.h>
|
|
|
|
#include <asm/efi.h>
|
|
|
|
#include <asm/loongson.h>
|
|
|
|
|
|
|
|
static unsigned long efi_nr_tables;
|
|
|
|
static unsigned long efi_config_table;
|
|
|
|
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;
|
2022-12-10 09:40:05 -05:00
|
|
|
static unsigned long __initdata fdt_pointer = EFI_INVALID_TABLE_ADDR;
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
static efi_system_table_t *efi_systab;
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
static efi_config_table_type_t arch_tables[] __initdata = {
|
|
|
|
{LINUX_EFI_BOOT_MEMMAP_GUID, &boot_memmap, "MEMMAP" },
|
2022-12-10 09:40:05 -05:00
|
|
|
{DEVICE_TREE_GUID, &fdt_pointer, "FDTPTR" },
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
{},
|
|
|
|
};
|
2022-05-31 06:04:11 -04:00
|
|
|
|
2022-12-10 09:40:05 -05:00
|
|
|
void __init *efi_fdt_pointer(void)
|
|
|
|
{
|
|
|
|
if (!efi_systab)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (fdt_pointer == EFI_INVALID_TABLE_ADDR)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return early_memremap_ro(fdt_pointer, SZ_64K);
|
|
|
|
}
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
void __init efi_runtime_init(void)
|
|
|
|
{
|
2022-12-10 09:40:05 -05:00
|
|
|
if (!efi_enabled(EFI_BOOT) || !efi_systab->runtime)
|
2022-05-31 06:04:11 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (efi_runtime_disabled()) {
|
|
|
|
pr_info("EFI runtime services will be disabled.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
efi.runtime = (efi_runtime_services_t *)efi_systab->runtime;
|
|
|
|
efi.runtime_version = (unsigned int)efi.runtime->hdr.revision;
|
|
|
|
|
|
|
|
efi_native_runtime_setup();
|
|
|
|
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
|
|
|
|
}
|
|
|
|
|
2022-10-11 11:10:39 -04:00
|
|
|
unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
|
|
|
|
|
efi: move screen_info into efi init code
After the vga console no longer relies on global screen_info, there are
only two remaining use cases:
- on the x86 architecture, it is used for multiple boot methods
(bzImage, EFI, Xen, kexec) to commucate the initial VGA or framebuffer
settings to a number of device drivers.
- on other architectures, it is only used as part of the EFI stub,
and only for the three sysfb framebuffers (simpledrm, simplefb, efifb).
Remove the duplicate data structure definitions by moving it into the
efi-init.c file that sets it up initially for the EFI case, leaving x86
as an exception that retains its own definition for non-EFI boots.
The added #ifdefs here are optional, I added them to further limit the
reach of screen_info to configurations that have at least one of the
users enabled.
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20231017093947.3627976-1-arnd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-17 05:39:46 -04:00
|
|
|
#if defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON)
|
|
|
|
struct screen_info screen_info __section(".data");
|
|
|
|
EXPORT_SYMBOL_GPL(screen_info);
|
|
|
|
#endif
|
|
|
|
|
2022-10-11 11:10:39 -04:00
|
|
|
static void __init init_screen_info(void)
|
|
|
|
{
|
|
|
|
struct screen_info *si;
|
|
|
|
|
|
|
|
if (screen_info_table == EFI_INVALID_TABLE_ADDR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
si = early_memremap(screen_info_table, sizeof(*si));
|
|
|
|
if (!si) {
|
|
|
|
pr_err("Could not map screen_info config table\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
screen_info = *si;
|
|
|
|
memset(si, 0, sizeof(*si));
|
|
|
|
early_memunmap(si, sizeof(*si));
|
|
|
|
|
|
|
|
memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
|
|
|
|
}
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
void __init efi_init(void)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
void *config_tables;
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
struct efi_boot_memmap *tbl;
|
2022-05-31 06:04:11 -04:00
|
|
|
|
|
|
|
if (!efi_system_table)
|
|
|
|
return;
|
|
|
|
|
|
|
|
efi_systab = (efi_system_table_t *)early_memremap_ro(efi_system_table, sizeof(*efi_systab));
|
|
|
|
if (!efi_systab) {
|
|
|
|
pr_err("Can't find EFI system table.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor);
|
|
|
|
|
2022-05-31 06:04:11 -04:00
|
|
|
set_bit(EFI_64BIT, &efi.flags);
|
|
|
|
efi_nr_tables = efi_systab->nr_tables;
|
|
|
|
efi_config_table = (unsigned long)efi_systab->tables;
|
|
|
|
|
|
|
|
size = sizeof(efi_config_table_t);
|
|
|
|
config_tables = early_memremap(efi_config_table, efi_nr_tables * size);
|
|
|
|
efi_config_parse_tables(config_tables, efi_systab->nr_tables, arch_tables);
|
|
|
|
early_memunmap(config_tables, efi_nr_tables * size);
|
efi/loongarch: Add efistub booting support
This patch adds efistub booting support, which is the standard UEFI boot
protocol for LoongArch to use.
We use generic efistub, which means we can pass boot information (i.e.,
system table, memory map, kernel command line, initrd) via a light FDT
and drop a lot of non-standard code.
We use a flat mapping to map the efi runtime in the kernel's address
space. In efi, VA = PA; in kernel, VA = PA + PAGE_OFFSET. As a result,
flat mapping is not identity mapping, SetVirtualAddressMap() is still
needed for the efi runtime.
Tested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
[ardb: change fpic to fpie as suggested by Xi Ruoyao]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-08-19 06:20:37 -04:00
|
|
|
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
|
|
|
|
efi: move screen_info into efi init code
After the vga console no longer relies on global screen_info, there are
only two remaining use cases:
- on the x86 architecture, it is used for multiple boot methods
(bzImage, EFI, Xen, kexec) to commucate the initial VGA or framebuffer
settings to a number of device drivers.
- on other architectures, it is only used as part of the EFI stub,
and only for the three sysfb framebuffers (simpledrm, simplefb, efifb).
Remove the duplicate data structure definitions by moving it into the
efi-init.c file that sets it up initially for the EFI case, leaving x86
as an exception that retains its own definition for non-EFI boots.
The added #ifdefs here are optional, I added them to further limit the
reach of screen_info to configurations that have at least one of the
users enabled.
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20231017093947.3627976-1-arnd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-17 05:39:46 -04:00
|
|
|
if (IS_ENABLED(CONFIG_EFI_EARLYCON) || IS_ENABLED(CONFIG_SYSFB))
|
|
|
|
init_screen_info();
|
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>
2022-09-16 13:48:53 -04:00
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
2024-01-16 23:43:08 -05:00
|
|
|
|
|
|
|
efi_esrt_init();
|
2022-05-31 06:04:11 -04:00
|
|
|
}
|