Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar: "The main changes in this cycle were: - move BGRT handling to drivers/acpi so it can be shared between x86 and ARM - bring the EFI stub's initrd and FDT allocation logic in line with the latest changes to the arm64 boot protocol - improvements and fixes to the EFI stub's command line parsing routines - randomize the virtual mapping of the UEFI runtime services on ARM/arm64 - ... and other misc enhancements, cleanups and fixes" * 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi/libstub/arm: Don't use TASK_SIZE when randomizing the RT space ef/libstub/arm/arm64: Randomize the base of the UEFI rt services region efi/libstub/arm/arm64: Disable debug prints on 'quiet' cmdline arg efi/libstub: Unify command line param parsing efi/libstub: Fix harmless command line parsing bug efi/arm32-stub: Allow boot-time allocations in the vmlinux region x86/efi: Clean up a minor mistake in comment efi/pstore: Return error code (if any) from efi_pstore_write() efi/bgrt: Enable ACPI BGRT handling on arm64 x86/efi/bgrt: Move efi-bgrt handling out of arch/x86 efi/arm-stub: Round up FDT allocation to mapping size efi/arm-stub: Correct FDT and initrd allocation rules for arm64
This commit is contained in:
commit
3711c94fd6
20 changed files with 305 additions and 123 deletions
|
@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
|||
*/
|
||||
#define ZIMAGE_OFFSET_LIMIT SZ_128M
|
||||
#define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE
|
||||
#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT
|
||||
|
||||
/* on ARM, the FDT should be located in the first 128 MB of RAM */
|
||||
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
|
||||
{
|
||||
return dram_base + ZIMAGE_OFFSET_LIMIT;
|
||||
}
|
||||
|
||||
/* on ARM, the initrd should be loaded in a lowmem region */
|
||||
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
|
||||
unsigned long image_addr)
|
||||
{
|
||||
return dram_base + SZ_512M;
|
||||
}
|
||||
|
||||
#endif /* _ASM_ARM_EFI_H */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _ASM_EFI_H
|
||||
#define _ASM_EFI_H
|
||||
|
||||
#include <asm/boot.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
@ -46,7 +47,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
|
|||
* 2MiB so we know it won't cross a 2MiB boundary.
|
||||
*/
|
||||
#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
|
||||
#define MAX_FDT_OFFSET SZ_512M
|
||||
|
||||
/* on arm64, the FDT may be located anywhere in system RAM */
|
||||
static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base)
|
||||
{
|
||||
return ULONG_MAX;
|
||||
}
|
||||
|
||||
/*
|
||||
* On arm64, we have to ensure that the initrd ends up in the linear region,
|
||||
* which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is
|
||||
* guaranteed to cover the kernel Image.
|
||||
*
|
||||
* Since the EFI stub is part of the kernel Image, we can relax the
|
||||
* usual requirements in Documentation/arm64/booting.txt, which still
|
||||
* apply to other bootloaders, and are required for some kernel
|
||||
* configurations.
|
||||
*/
|
||||
static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
|
||||
unsigned long image_addr)
|
||||
{
|
||||
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1));
|
||||
}
|
||||
|
||||
#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
|
||||
#define __efi_call_early(f, ...) f(__VA_ARGS__)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/acpi.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/efi-bgrt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
@ -233,6 +234,8 @@ void __init acpi_boot_table_init(void)
|
|||
early_init_dt_scan_chosen_stdout();
|
||||
} else {
|
||||
parse_spcr(earlycon_init_is_deferred);
|
||||
if (IS_ENABLED(CONFIG_ACPI_BGRT))
|
||||
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1564,12 +1564,6 @@ int __init early_acpi_boot_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init acpi_parse_bgrt(struct acpi_table_header *table)
|
||||
{
|
||||
efi_bgrt_init(table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init acpi_boot_init(void)
|
||||
{
|
||||
/* those are executed after early-quirks are executed */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
OBJECT_FILES_NON_STANDARD_efi_thunk_$(BITS).o := y
|
||||
|
||||
obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
|
||||
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
|
||||
obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
|
||||
obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include <asm/pgalloc.h>
|
||||
|
||||
/*
|
||||
* We allocate runtime services regions bottom-up, starting from -4G, i.e.
|
||||
* We allocate runtime services regions top-down, starting from -4G, i.e.
|
||||
* 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
|
||||
*/
|
||||
static u64 efi_va = EFI_VA_START;
|
||||
|
|
|
@ -440,7 +440,7 @@ config ACPI_CUSTOM_METHOD
|
|||
|
||||
config ACPI_BGRT
|
||||
bool "Boottime Graphics Resource Table support"
|
||||
depends on EFI && X86
|
||||
depends on EFI && (X86 || ARM64)
|
||||
help
|
||||
This driver adds support for exposing the ACPI Boottime Graphics
|
||||
Resource Table, which allows the operating system to obtain
|
||||
|
|
|
@ -81,6 +81,12 @@ static struct attribute_group bgrt_attribute_group = {
|
|||
.bin_attrs = bgrt_bin_attributes,
|
||||
};
|
||||
|
||||
int __init acpi_parse_bgrt(struct acpi_table_header *table)
|
||||
{
|
||||
efi_bgrt_init(table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init bgrt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#
|
||||
KASAN_SANITIZE_runtime-wrappers.o := n
|
||||
|
||||
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
|
||||
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o
|
||||
obj-$(CONFIG_EFI) += capsule.o memmap.o
|
||||
obj-$(CONFIG_EFI_VARS) += efivars.o
|
||||
|
|
|
@ -274,9 +274,9 @@ static int efi_pstore_write(enum pstore_type_id type,
|
|||
for (i = 0; i < DUMP_NAME_LEN; i++)
|
||||
efi_name[i] = name[i];
|
||||
|
||||
efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
|
||||
!pstore_cannot_block_path(reason),
|
||||
size, psi->buf);
|
||||
ret = efivar_entry_set_safe(efi_name, vendor, PSTORE_EFI_ATTRIBUTES,
|
||||
!pstore_cannot_block_path(reason),
|
||||
size, psi->buf);
|
||||
|
||||
if (reason == KMSG_DUMP_OOPS)
|
||||
efivar_run_worker();
|
||||
|
|
|
@ -18,7 +18,27 @@
|
|||
|
||||
#include "efistub.h"
|
||||
|
||||
bool __nokaslr;
|
||||
/*
|
||||
* This is the base address at which to start allocating virtual memory ranges
|
||||
* for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
|
||||
* any allocation we choose, and eliminate the risk of a conflict after kexec.
|
||||
* The value chosen is the largest non-zero power of 2 suitable for this purpose
|
||||
* both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
|
||||
* be mapped efficiently.
|
||||
* Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
|
||||
* map everything below 1 GB. (512 MB is a reasonable upper bound for the
|
||||
* entire footprint of the UEFI runtime services memory regions)
|
||||
*/
|
||||
#define EFI_RT_VIRTUAL_BASE SZ_512M
|
||||
#define EFI_RT_VIRTUAL_SIZE SZ_512M
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE_64
|
||||
#else
|
||||
# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE
|
||||
#endif
|
||||
|
||||
static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
|
||||
|
||||
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
|
||||
void *__image, void **__fh)
|
||||
|
@ -118,8 +138,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
||||
goto fail;
|
||||
|
||||
pr_efi(sys_table, "Booting Linux Kernel...\n");
|
||||
|
||||
status = check_platform_features(sys_table);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
|
@ -153,17 +171,15 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* check whether 'nokaslr' was passed on the command line */
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
|
||||
static const u8 default_cmdline[] = CONFIG_CMDLINE;
|
||||
const u8 *str, *cmdline = cmdline_ptr;
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
||||
cmdline_size == 0)
|
||||
efi_parse_options(CONFIG_CMDLINE);
|
||||
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_FORCE))
|
||||
cmdline = default_cmdline;
|
||||
str = strstr(cmdline, "nokaslr");
|
||||
if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
|
||||
__nokaslr = true;
|
||||
}
|
||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0)
|
||||
efi_parse_options(cmdline_ptr);
|
||||
|
||||
pr_efi(sys_table, "Booting Linux Kernel...\n");
|
||||
|
||||
si = setup_graphics(sys_table);
|
||||
|
||||
|
@ -176,10 +192,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
goto fail_free_cmdline;
|
||||
}
|
||||
|
||||
status = efi_parse_options(cmdline_ptr);
|
||||
if (status != EFI_SUCCESS)
|
||||
pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
|
||||
|
||||
secure_boot = efi_get_secureboot(sys_table);
|
||||
|
||||
/*
|
||||
|
@ -213,8 +225,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
if (!fdt_addr)
|
||||
pr_efi(sys_table, "Generating empty DTB\n");
|
||||
|
||||
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
|
||||
"initrd=", dram_base + SZ_512M,
|
||||
status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=",
|
||||
efi_get_max_initrd_addr(dram_base,
|
||||
*image_addr),
|
||||
(unsigned long *)&initrd_addr,
|
||||
(unsigned long *)&initrd_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
|
@ -222,9 +235,29 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
|
||||
efi_random_get_seed(sys_table);
|
||||
|
||||
if (!nokaslr()) {
|
||||
/*
|
||||
* Randomize the base of the UEFI runtime services region.
|
||||
* Preserve the 2 MB alignment of the region by taking a
|
||||
* shift of 21 bit positions into account when scaling
|
||||
* the headroom value using a 32-bit random value.
|
||||
*/
|
||||
static const u64 headroom = EFI_RT_VIRTUAL_LIMIT -
|
||||
EFI_RT_VIRTUAL_BASE -
|
||||
EFI_RT_VIRTUAL_SIZE;
|
||||
u32 rnd;
|
||||
|
||||
status = efi_get_random_bytes(sys_table, sizeof(rnd),
|
||||
(u8 *)&rnd);
|
||||
if (status == EFI_SUCCESS) {
|
||||
virtmap_base = EFI_RT_VIRTUAL_BASE +
|
||||
(((headroom >> 21) * rnd) >> (32 - 21));
|
||||
}
|
||||
}
|
||||
|
||||
new_fdt_addr = fdt_addr;
|
||||
status = allocate_new_fdt_and_exit_boot(sys_table, handle,
|
||||
&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
|
||||
&new_fdt_addr, efi_get_max_fdt_addr(dram_base),
|
||||
initrd_addr, initrd_size, cmdline_ptr,
|
||||
fdt_addr, fdt_size);
|
||||
|
||||
|
@ -251,18 +284,6 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
return EFI_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the base address at which to start allocating virtual memory ranges
|
||||
* for UEFI Runtime Services. This is in the low TTBR0 range so that we can use
|
||||
* any allocation we choose, and eliminate the risk of a conflict after kexec.
|
||||
* The value chosen is the largest non-zero power of 2 suitable for this purpose
|
||||
* both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
|
||||
* be mapped efficiently.
|
||||
* Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
|
||||
* map everything below 1 GB.
|
||||
*/
|
||||
#define EFI_RT_VIRTUAL_BASE SZ_512M
|
||||
|
||||
static int cmp_mem_desc(const void *l, const void *r)
|
||||
{
|
||||
const efi_memory_desc_t *left = l, *right = r;
|
||||
|
@ -312,7 +333,7 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
|
|||
unsigned long desc_size, efi_memory_desc_t *runtime_map,
|
||||
int *count)
|
||||
{
|
||||
u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
|
||||
u64 efi_virt_base = virtmap_base;
|
||||
efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
|
||||
int l;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
int block;
|
||||
|
@ -63,27 +65,25 @@ void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si)
|
|||
efi_call_early(free_pool, si);
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
|
||||
unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size,
|
||||
unsigned long dram_base,
|
||||
efi_loaded_image_t *image)
|
||||
static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
|
||||
unsigned long dram_base,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size)
|
||||
{
|
||||
unsigned long nr_pages;
|
||||
efi_status_t status;
|
||||
/* Use alloc_addr to tranlsate between types */
|
||||
efi_physical_addr_t alloc_addr;
|
||||
efi_memory_desc_t *memory_map;
|
||||
unsigned long nr_pages, map_size, desc_size, buff_size;
|
||||
efi_status_t status;
|
||||
unsigned long l;
|
||||
|
||||
/*
|
||||
* Verify that the DRAM base address is compatible with the ARM
|
||||
* boot protocol, which determines the base of DRAM by masking
|
||||
* off the low 27 bits of the address at which the zImage is
|
||||
* loaded. These assumptions are made by the decompressor,
|
||||
* before any memory map is available.
|
||||
*/
|
||||
dram_base = round_up(dram_base, SZ_128M);
|
||||
struct efi_boot_memmap map = {
|
||||
.map = &memory_map,
|
||||
.map_size = &map_size,
|
||||
.desc_size = &desc_size,
|
||||
.desc_ver = NULL,
|
||||
.key_ptr = NULL,
|
||||
.buff_size = &buff_size,
|
||||
};
|
||||
|
||||
/*
|
||||
* Reserve memory for the uncompressed kernel image. This is
|
||||
|
@ -94,18 +94,128 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
|
|||
* Do this very early, as prints can cause memory allocations
|
||||
* that may conflict with this.
|
||||
*/
|
||||
alloc_addr = dram_base;
|
||||
*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
|
||||
nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
|
||||
status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA,
|
||||
nr_pages, &alloc_addr);
|
||||
alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
|
||||
nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
|
||||
status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
|
||||
EFI_BOOT_SERVICES_DATA, nr_pages, &alloc_addr);
|
||||
if (status == EFI_SUCCESS) {
|
||||
if (alloc_addr == dram_base) {
|
||||
*reserve_addr = alloc_addr;
|
||||
*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
/*
|
||||
* If we end up here, the allocation succeeded but starts below
|
||||
* dram_base. This can only occur if the real base of DRAM is
|
||||
* not a multiple of 128 MB, in which case dram_base will have
|
||||
* been rounded up. Since this implies that a part of the region
|
||||
* was already occupied, we need to fall through to the code
|
||||
* below to ensure that the existing allocations don't conflict.
|
||||
* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
|
||||
* EFI_LOADER_DATA, which we wouldn't able to distinguish from
|
||||
* allocations that we want to disallow.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If the allocation above failed, we may still be able to proceed:
|
||||
* if the only allocations in the region are of types that will be
|
||||
* released to the OS after ExitBootServices(), the decompressor can
|
||||
* safely overwrite them.
|
||||
*/
|
||||
status = efi_get_memory_map(sys_table_arg, &map);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table_arg,
|
||||
"reserve_kernel_base(): Unable to retrieve memory map.\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
for (l = 0; l < map_size; l += desc_size) {
|
||||
efi_memory_desc_t *desc;
|
||||
u64 start, end;
|
||||
|
||||
desc = (void *)memory_map + l;
|
||||
start = desc->phys_addr;
|
||||
end = start + desc->num_pages * EFI_PAGE_SIZE;
|
||||
|
||||
/* Skip if entry does not intersect with region */
|
||||
if (start >= dram_base + MAX_UNCOMP_KERNEL_SIZE ||
|
||||
end <= dram_base)
|
||||
continue;
|
||||
|
||||
switch (desc->type) {
|
||||
case EFI_BOOT_SERVICES_CODE:
|
||||
case EFI_BOOT_SERVICES_DATA:
|
||||
/* Ignore types that are released to the OS anyway */
|
||||
continue;
|
||||
|
||||
case EFI_CONVENTIONAL_MEMORY:
|
||||
/*
|
||||
* Reserve the intersection between this entry and the
|
||||
* region.
|
||||
*/
|
||||
start = max(start, (u64)dram_base);
|
||||
end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);
|
||||
|
||||
status = efi_call_early(allocate_pages,
|
||||
EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA,
|
||||
(end - start) / EFI_PAGE_SIZE,
|
||||
&start);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table_arg,
|
||||
"reserve_kernel_base(): alloc failed.\n");
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case EFI_LOADER_CODE:
|
||||
case EFI_LOADER_DATA:
|
||||
/*
|
||||
* These regions may be released and reallocated for
|
||||
* another purpose (including EFI_RUNTIME_SERVICE_DATA)
|
||||
* at any time during the execution of the OS loader,
|
||||
* so we cannot consider them as safe.
|
||||
*/
|
||||
default:
|
||||
/*
|
||||
* Treat any other allocation in the region as unsafe */
|
||||
status = EFI_OUT_OF_RESOURCES;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
status = EFI_SUCCESS;
|
||||
out:
|
||||
efi_call_early(free_pool, memory_map);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
|
||||
unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size,
|
||||
unsigned long dram_base,
|
||||
efi_loaded_image_t *image)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
/*
|
||||
* Verify that the DRAM base address is compatible with the ARM
|
||||
* boot protocol, which determines the base of DRAM by masking
|
||||
* off the low 27 bits of the address at which the zImage is
|
||||
* loaded. These assumptions are made by the decompressor,
|
||||
* before any memory map is available.
|
||||
*/
|
||||
dram_base = round_up(dram_base, SZ_128M);
|
||||
|
||||
status = reserve_kernel_base(sys_table, dram_base, reserve_addr,
|
||||
reserve_size);
|
||||
if (status != EFI_SUCCESS) {
|
||||
*reserve_size = 0;
|
||||
pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
|
||||
return status;
|
||||
}
|
||||
*reserve_addr = alloc_addr;
|
||||
|
||||
/*
|
||||
* Relocate the zImage, so that it appears in the lowest 128 MB
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
#include "efistub.h"
|
||||
|
||||
extern bool __nokaslr;
|
||||
|
||||
efi_status_t check_platform_features(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
u64 tg;
|
||||
|
@ -52,7 +50,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table_arg,
|
|||
u64 phys_seed = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
|
||||
if (!__nokaslr) {
|
||||
if (!nokaslr()) {
|
||||
status = efi_get_random_bytes(sys_table_arg,
|
||||
sizeof(phys_seed),
|
||||
(u8 *)&phys_seed);
|
||||
|
|
|
@ -32,6 +32,18 @@
|
|||
|
||||
static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
|
||||
|
||||
static int __section(.data) __nokaslr;
|
||||
static int __section(.data) __quiet;
|
||||
|
||||
int __pure nokaslr(void)
|
||||
{
|
||||
return __nokaslr;
|
||||
}
|
||||
int __pure is_quiet(void)
|
||||
{
|
||||
return __quiet;
|
||||
}
|
||||
|
||||
#define EFI_MMAP_NR_SLACK_SLOTS 8
|
||||
|
||||
struct file_info {
|
||||
|
@ -409,17 +421,17 @@ static efi_status_t efi_file_close(void *handle)
|
|||
* environments, first in the early boot environment of the EFI boot
|
||||
* stub, and subsequently during the kernel boot.
|
||||
*/
|
||||
efi_status_t efi_parse_options(char *cmdline)
|
||||
efi_status_t efi_parse_options(char const *cmdline)
|
||||
{
|
||||
char *str;
|
||||
|
||||
/*
|
||||
* Currently, the only efi= option we look for is 'nochunk', which
|
||||
* is intended to work around known issues on certain x86 UEFI
|
||||
* versions. So ignore for now on other architectures.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_X86))
|
||||
return EFI_SUCCESS;
|
||||
str = strstr(cmdline, "nokaslr");
|
||||
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
|
||||
__nokaslr = 1;
|
||||
|
||||
str = strstr(cmdline, "quiet");
|
||||
if (str == cmdline || (str && str > cmdline && *(str - 1) == ' '))
|
||||
__quiet = 1;
|
||||
|
||||
/*
|
||||
* If no EFI parameters were specified on the cmdline we've got
|
||||
|
@ -436,14 +448,14 @@ efi_status_t efi_parse_options(char *cmdline)
|
|||
* Remember, because efi= is also used by the kernel we need to
|
||||
* skip over arguments we don't understand.
|
||||
*/
|
||||
while (*str) {
|
||||
while (*str && *str != ' ') {
|
||||
if (!strncmp(str, "nochunk", 7)) {
|
||||
str += strlen("nochunk");
|
||||
__chunk_size = -1UL;
|
||||
}
|
||||
|
||||
/* Group words together, delimited by "," */
|
||||
while (*str && *str != ',')
|
||||
while (*str && *str != ' ' && *str != ',')
|
||||
str++;
|
||||
|
||||
if (*str == ',')
|
||||
|
|
|
@ -24,6 +24,15 @@
|
|||
#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
|
||||
#endif
|
||||
|
||||
extern int __pure nokaslr(void);
|
||||
extern int __pure is_quiet(void);
|
||||
|
||||
#define pr_efi(sys_table, msg) do { \
|
||||
if (!is_quiet()) efi_printk(sys_table, "EFI stub: "msg); \
|
||||
} while (0)
|
||||
|
||||
#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
|
||||
|
||||
void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
|
||||
|
||||
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
|
||||
|
|
|
@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
|||
return update_fdt_memmap(p->new_fdt_addr, map);
|
||||
}
|
||||
|
||||
#ifndef MAX_FDT_SIZE
|
||||
#define MAX_FDT_SIZE SZ_2M
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate memory for a new FDT, then add EFI, commandline, and
|
||||
* initrd related fields to the FDT. This routine increases the
|
||||
|
@ -233,7 +237,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
|||
u32 desc_ver;
|
||||
unsigned long mmap_key;
|
||||
efi_memory_desc_t *memory_map, *runtime_map;
|
||||
unsigned long new_fdt_size;
|
||||
efi_status_t status;
|
||||
int runtime_entry_count = 0;
|
||||
struct efi_boot_memmap map;
|
||||
|
@ -262,41 +265,29 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
|||
"Exiting boot services and installing virtual address map...\n");
|
||||
|
||||
map.map = &memory_map;
|
||||
status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN,
|
||||
new_fdt_addr, max_addr);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table,
|
||||
"Unable to allocate memory for new device tree.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate size of new FDT, and allocate memory for it. We
|
||||
* will allocate a bigger buffer if this ends up being too
|
||||
* small, so a rough guess is OK here.
|
||||
* Now that we have done our final memory allocation (and free)
|
||||
* we can get the memory map key needed for exit_boot_services().
|
||||
*/
|
||||
new_fdt_size = fdt_size + EFI_PAGE_SIZE;
|
||||
while (1) {
|
||||
status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN,
|
||||
new_fdt_addr, max_addr);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n");
|
||||
goto fail;
|
||||
}
|
||||
status = efi_get_memory_map(sys_table, &map);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail_free_new_fdt;
|
||||
|
||||
status = update_fdt(sys_table,
|
||||
(void *)fdt_addr, fdt_size,
|
||||
(void *)*new_fdt_addr, new_fdt_size,
|
||||
cmdline_ptr, initrd_addr, initrd_size);
|
||||
status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
|
||||
(void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
|
||||
initrd_addr, initrd_size);
|
||||
|
||||
/* Succeeding the first time is the expected case. */
|
||||
if (status == EFI_SUCCESS)
|
||||
break;
|
||||
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
/*
|
||||
* We need to allocate more space for the new
|
||||
* device tree, so free existing buffer that is
|
||||
* too small.
|
||||
*/
|
||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||
new_fdt_size += EFI_PAGE_SIZE;
|
||||
} else {
|
||||
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
||||
goto fail_free_new_fdt;
|
||||
}
|
||||
if (status != EFI_SUCCESS) {
|
||||
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
||||
goto fail_free_new_fdt;
|
||||
}
|
||||
|
||||
priv.runtime_map = runtime_map;
|
||||
|
@ -340,7 +331,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
|||
pr_efi_err(sys_table, "Exit boot services failed.\n");
|
||||
|
||||
fail_free_new_fdt:
|
||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||
efi_free(sys_table, MAX_FDT_SIZE, *new_fdt_addr);
|
||||
|
||||
fail:
|
||||
sys_table->boottime->free_pool(runtime_map);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
/* BIOS variables */
|
||||
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
static const efi_char16_t const efi_SecureBoot_name[] = {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifdef CONFIG_ACPI_BGRT
|
||||
|
||||
void efi_bgrt_init(struct acpi_table_header *table);
|
||||
int __init acpi_parse_bgrt(struct acpi_table_header *table);
|
||||
|
||||
/* The BGRT data itself; only valid if bgrt_image != NULL. */
|
||||
extern size_t bgrt_image_size;
|
||||
|
@ -14,6 +15,10 @@ extern struct acpi_table_bgrt bgrt_tab;
|
|||
#else /* !CONFIG_ACPI_BGRT */
|
||||
|
||||
static inline void efi_bgrt_init(struct acpi_table_header *table) {}
|
||||
static inline int __init acpi_parse_bgrt(struct acpi_table_header *table)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_ACPI_BGRT */
|
||||
|
||||
|
|
|
@ -1435,9 +1435,6 @@ static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
|
|||
|
||||
/* prototypes shared between arch specific and generic stub code */
|
||||
|
||||
#define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg)
|
||||
#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
|
||||
|
||||
void efi_printk(efi_system_table_t *sys_table_arg, char *str);
|
||||
|
||||
void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
|
||||
|
@ -1471,7 +1468,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
|
|||
unsigned long *load_addr,
|
||||
unsigned long *load_size);
|
||||
|
||||
efi_status_t efi_parse_options(char *cmdline);
|
||||
efi_status_t efi_parse_options(char const *cmdline);
|
||||
|
||||
efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
|
||||
struct screen_info *si, efi_guid_t *proto,
|
||||
|
|
Loading…
Reference in a new issue