Merge tag 'efi-core-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI changes from Ingo Molnar: - Preliminary RISC-V enablement - the bulk of it will arrive via the RISCV tree. - Relax decompressed image placement rules for 32-bit ARM - Add support for passing MOK certificate table contents via a config table rather than a EFI variable. - Add support for 18 bit DIMM row IDs in the CPER records. - Work around broken Dell firmware that passes the entire Boot#### variable contents as the command line - Add definition of the EFI_MEMORY_CPU_CRYPTO memory attribute so we can identify it in the memory map listings. - Don't abort the boot on arm64 if the EFI RNG protocol is available but returns with an error - Replace slashes with exclamation marks in efivarfs file names - Split efi-pstore from the deprecated efivars sysfs code, so we can disable the latter on !x86. - Misc fixes, cleanups and updates. * tag 'efi-core-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (26 commits) efi: mokvar: add missing include of asm/early_ioremap.h efi: efivars: limit availability to X86 builds efi: remove some false dependencies on CONFIG_EFI_VARS efi: gsmi: fix false dependency on CONFIG_EFI_VARS efi: efivars: un-export efivars_sysfs_init() efi: pstore: move workqueue handling out of efivars efi: pstore: disentangle from deprecated efivars module efi: mokvar-table: fix some issues in new code efi/arm64: libstub: Deal gracefully with EFI_RNG_PROTOCOL failure efivarfs: Replace invalid slashes with exclamation marks in dentries. efi: Delete deprecated parameter comments efi/libstub: Fix missing-prototypes in string.c efi: Add definition of EFI_MEMORY_CPU_CRYPTO and ability to report it cper,edac,efi: Memory Error Record: bank group/address and chip id edac,ghes,cper: Add Row Extension to Memory Error Record efi/x86: Add a quirk to support command line arguments on Dell EFI firmware efi/libstub: Add efi_warn and *_once logging helpers integrity: Load certs from the EFI MOK config table integrity: Move import of MokListRT certs to a separate routine efi: Support for MOK variable config table ...
This commit is contained in:
@@ -113,162 +113,58 @@ void free_screen_info(struct screen_info *si)
|
||||
efi_bs_call(free_pool, si);
|
||||
}
|
||||
|
||||
static efi_status_t reserve_kernel_base(unsigned long dram_base,
|
||||
unsigned long *reserve_addr,
|
||||
unsigned long *reserve_size)
|
||||
{
|
||||
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;
|
||||
|
||||
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
|
||||
* all that prevents any future allocations from conflicting
|
||||
* with the kernel. Since we can't tell from the compressed
|
||||
* image how much DRAM the kernel actually uses (due to BSS
|
||||
* size uncertainty) we allocate the maximum possible size.
|
||||
* Do this very early, as prints can cause memory allocations
|
||||
* that may conflict with this.
|
||||
*/
|
||||
alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
|
||||
nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
|
||||
status = efi_bs_call(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(&map);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("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:
|
||||
/* Skip soft reserved conventional memory */
|
||||
if (efi_soft_reserve_enabled() &&
|
||||
(desc->attribute & EFI_MEMORY_SP))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* 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_bs_call(allocate_pages,
|
||||
EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA,
|
||||
(end - start) / EFI_PAGE_SIZE,
|
||||
&start);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("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_bs_call(free_pool, memory_map);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(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)
|
||||
{
|
||||
unsigned long kernel_base;
|
||||
const int slack = TEXT_OFFSET - 5 * PAGE_SIZE;
|
||||
int alloc_size = MAX_UNCOMP_KERNEL_SIZE + EFI_PHYS_ALIGN;
|
||||
unsigned long alloc_base, kernel_base;
|
||||
efi_status_t status;
|
||||
|
||||
/* use a 16 MiB aligned base for the decompressed kernel */
|
||||
kernel_base = round_up(dram_base, SZ_16M) + TEXT_OFFSET;
|
||||
|
||||
/*
|
||||
* Note that some platforms (notably, the Raspberry Pi 2) put
|
||||
* spin-tables and other pieces of firmware at the base of RAM,
|
||||
* abusing the fact that the window of TEXT_OFFSET bytes at the
|
||||
* base of the kernel image is only partially used at the moment.
|
||||
* (Up to 5 pages are used for the swapper page tables)
|
||||
* Allocate space for the decompressed kernel as low as possible.
|
||||
* The region should be 16 MiB aligned, but the first 'slack' bytes
|
||||
* are not used by Linux, so we allow those to be occupied by the
|
||||
* firmware.
|
||||
*/
|
||||
status = reserve_kernel_base(kernel_base - 5 * PAGE_SIZE, reserve_addr,
|
||||
reserve_size);
|
||||
status = efi_low_alloc_above(alloc_size, EFI_PAGE_SIZE, &alloc_base, 0x0);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Unable to allocate memory for uncompressed kernel.\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
*image_addr = kernel_base;
|
||||
if ((alloc_base % EFI_PHYS_ALIGN) > slack) {
|
||||
/*
|
||||
* More than 'slack' bytes are already occupied at the base of
|
||||
* the allocation, so we need to advance to the next 16 MiB block.
|
||||
*/
|
||||
kernel_base = round_up(alloc_base, EFI_PHYS_ALIGN);
|
||||
efi_info("Free memory starts at 0x%lx, setting kernel_base to 0x%lx\n",
|
||||
alloc_base, kernel_base);
|
||||
} else {
|
||||
kernel_base = round_down(alloc_base, EFI_PHYS_ALIGN);
|
||||
}
|
||||
|
||||
*reserve_addr = kernel_base + slack;
|
||||
*reserve_size = MAX_UNCOMP_KERNEL_SIZE;
|
||||
|
||||
/* now free the parts that we will not use */
|
||||
if (*reserve_addr > alloc_base) {
|
||||
efi_bs_call(free_pages, alloc_base,
|
||||
(*reserve_addr - alloc_base) / EFI_PAGE_SIZE);
|
||||
alloc_size -= *reserve_addr - alloc_base;
|
||||
}
|
||||
efi_bs_call(free_pages, *reserve_addr + MAX_UNCOMP_KERNEL_SIZE,
|
||||
(alloc_size - MAX_UNCOMP_KERNEL_SIZE) / EFI_PAGE_SIZE);
|
||||
|
||||
*image_addr = kernel_base + TEXT_OFFSET;
|
||||
*image_size = 0;
|
||||
|
||||
efi_debug("image addr == 0x%lx, reserve_addr == 0x%lx\n",
|
||||
*image_addr, *reserve_addr);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ efi_status_t handle_kernel_image(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;
|
||||
@@ -62,10 +61,12 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
|
||||
status = efi_get_random_bytes(sizeof(phys_seed),
|
||||
(u8 *)&phys_seed);
|
||||
if (status == EFI_NOT_FOUND) {
|
||||
efi_info("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
|
||||
efi_info("EFI_RNG_PROTOCOL unavailable, KASLR will be disabled\n");
|
||||
efi_nokaslr = true;
|
||||
} else if (status != EFI_SUCCESS) {
|
||||
efi_err("efi_get_random_bytes() failed\n");
|
||||
return status;
|
||||
efi_err("efi_get_random_bytes() failed (0x%lx), KASLR will be disabled\n",
|
||||
status);
|
||||
efi_nokaslr = true;
|
||||
}
|
||||
} else {
|
||||
efi_info("KASLR disabled on kernel command line\n");
|
||||
|
||||
@@ -238,6 +238,102 @@ efi_status_t efi_parse_options(char const *cmdline)
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* The EFI_LOAD_OPTION descriptor has the following layout:
|
||||
* u32 Attributes;
|
||||
* u16 FilePathListLength;
|
||||
* u16 Description[];
|
||||
* efi_device_path_protocol_t FilePathList[];
|
||||
* u8 OptionalData[];
|
||||
*
|
||||
* This function validates and unpacks the variable-size data fields.
|
||||
*/
|
||||
static
|
||||
bool efi_load_option_unpack(efi_load_option_unpacked_t *dest,
|
||||
const efi_load_option_t *src, size_t size)
|
||||
{
|
||||
const void *pos;
|
||||
u16 c;
|
||||
efi_device_path_protocol_t header;
|
||||
const efi_char16_t *description;
|
||||
const efi_device_path_protocol_t *file_path_list;
|
||||
|
||||
if (size < offsetof(efi_load_option_t, variable_data))
|
||||
return false;
|
||||
pos = src->variable_data;
|
||||
size -= offsetof(efi_load_option_t, variable_data);
|
||||
|
||||
if ((src->attributes & ~EFI_LOAD_OPTION_MASK) != 0)
|
||||
return false;
|
||||
|
||||
/* Scan description. */
|
||||
description = pos;
|
||||
do {
|
||||
if (size < sizeof(c))
|
||||
return false;
|
||||
c = *(const u16 *)pos;
|
||||
pos += sizeof(c);
|
||||
size -= sizeof(c);
|
||||
} while (c != L'\0');
|
||||
|
||||
/* Scan file_path_list. */
|
||||
file_path_list = pos;
|
||||
do {
|
||||
if (size < sizeof(header))
|
||||
return false;
|
||||
header = *(const efi_device_path_protocol_t *)pos;
|
||||
if (header.length < sizeof(header))
|
||||
return false;
|
||||
if (size < header.length)
|
||||
return false;
|
||||
pos += header.length;
|
||||
size -= header.length;
|
||||
} while ((header.type != EFI_DEV_END_PATH && header.type != EFI_DEV_END_PATH2) ||
|
||||
(header.sub_type != EFI_DEV_END_ENTIRE));
|
||||
if (pos != (const void *)file_path_list + src->file_path_list_length)
|
||||
return false;
|
||||
|
||||
dest->attributes = src->attributes;
|
||||
dest->file_path_list_length = src->file_path_list_length;
|
||||
dest->description = description;
|
||||
dest->file_path_list = file_path_list;
|
||||
dest->optional_data_size = size;
|
||||
dest->optional_data = size ? pos : NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* At least some versions of Dell firmware pass the entire contents of the
|
||||
* Boot#### variable, i.e. the EFI_LOAD_OPTION descriptor, rather than just the
|
||||
* OptionalData field.
|
||||
*
|
||||
* Detect this case and extract OptionalData.
|
||||
*/
|
||||
void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size)
|
||||
{
|
||||
const efi_load_option_t *load_option = *load_options;
|
||||
efi_load_option_unpacked_t load_option_unpacked;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_X86))
|
||||
return;
|
||||
if (!load_option)
|
||||
return;
|
||||
if (*load_options_size < sizeof(*load_option))
|
||||
return;
|
||||
if ((load_option->attributes & ~EFI_LOAD_OPTION_BOOT_MASK) != 0)
|
||||
return;
|
||||
|
||||
if (!efi_load_option_unpack(&load_option_unpacked, load_option, *load_options_size))
|
||||
return;
|
||||
|
||||
efi_warn_once(FW_BUG "LoadOptions is an EFI_LOAD_OPTION descriptor\n");
|
||||
efi_warn_once(FW_BUG "Using OptionalData as a workaround\n");
|
||||
|
||||
*load_options = load_option_unpacked.optional_data;
|
||||
*load_options_size = load_option_unpacked.optional_data_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the unicode UEFI command line to ASCII to pass to kernel.
|
||||
* Size of memory allocated return in *cmd_line_len.
|
||||
@@ -247,12 +343,15 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
|
||||
{
|
||||
const u16 *s2;
|
||||
unsigned long cmdline_addr = 0;
|
||||
int options_chars = efi_table_attr(image, load_options_size) / 2;
|
||||
int options_chars = efi_table_attr(image, load_options_size);
|
||||
const u16 *options = efi_table_attr(image, load_options);
|
||||
int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */
|
||||
bool in_quote = false;
|
||||
efi_status_t status;
|
||||
|
||||
efi_apply_loadoptions_quirk((const void **)&options, &options_chars);
|
||||
options_chars /= sizeof(*options);
|
||||
|
||||
if (options) {
|
||||
s2 = options;
|
||||
while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {
|
||||
|
||||
@@ -87,40 +87,6 @@ static void install_memreserve_table(void)
|
||||
efi_err("Failed to install memreserve config table!\n");
|
||||
}
|
||||
|
||||
static unsigned long get_dram_base(void)
|
||||
{
|
||||
efi_status_t status;
|
||||
unsigned long map_size, buff_size;
|
||||
unsigned long membase = EFI_ERROR;
|
||||
struct efi_memory_map map;
|
||||
efi_memory_desc_t *md;
|
||||
struct efi_boot_memmap boot_map;
|
||||
|
||||
boot_map.map = (efi_memory_desc_t **)&map.map;
|
||||
boot_map.map_size = &map_size;
|
||||
boot_map.desc_size = &map.desc_size;
|
||||
boot_map.desc_ver = NULL;
|
||||
boot_map.key_ptr = NULL;
|
||||
boot_map.buff_size = &buff_size;
|
||||
|
||||
status = efi_get_memory_map(&boot_map);
|
||||
if (status != EFI_SUCCESS)
|
||||
return membase;
|
||||
|
||||
map.map_end = map.map + map_size;
|
||||
|
||||
for_each_efi_memory_desc_in_map(&map, md) {
|
||||
if (md->attribute & EFI_MEMORY_WB) {
|
||||
if (membase > md->phys_addr)
|
||||
membase = md->phys_addr;
|
||||
}
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, map.map);
|
||||
|
||||
return membase;
|
||||
}
|
||||
|
||||
/*
|
||||
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
|
||||
* that is described in the PE/COFF header. Most of the code is the same
|
||||
@@ -134,7 +100,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
efi_status_t status;
|
||||
unsigned long image_addr;
|
||||
unsigned long image_size = 0;
|
||||
unsigned long dram_base;
|
||||
/* addr/point and size pairs for memory management*/
|
||||
unsigned long initrd_addr = 0;
|
||||
unsigned long initrd_size = 0;
|
||||
@@ -174,13 +139,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dram_base = get_dram_base();
|
||||
if (dram_base == EFI_ERROR) {
|
||||
efi_err("Failed to find DRAM base\n");
|
||||
status = EFI_LOAD_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the command line from EFI, using the LOADED_IMAGE
|
||||
* protocol. We are going to copy the command line into the
|
||||
@@ -218,7 +176,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
status = handle_kernel_image(&image_addr, &image_size,
|
||||
&reserve_addr,
|
||||
&reserve_size,
|
||||
dram_base, image);
|
||||
image);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to relocate kernel\n");
|
||||
goto fail_free_screeninfo;
|
||||
@@ -262,7 +220,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
efi_info("Generating empty DTB\n");
|
||||
|
||||
if (!efi_noinitrd) {
|
||||
max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
|
||||
max_addr = efi_get_max_initrd_addr(image_addr);
|
||||
status = efi_load_initrd(image, &initrd_addr, &initrd_size,
|
||||
ULONG_MAX, max_addr);
|
||||
if (status != EFI_SUCCESS)
|
||||
@@ -306,7 +264,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
install_memreserve_table();
|
||||
|
||||
status = allocate_new_fdt_and_exit_boot(handle, &fdt_addr,
|
||||
efi_get_max_fdt_addr(dram_base),
|
||||
efi_get_max_fdt_addr(image_addr),
|
||||
initrd_addr, initrd_size,
|
||||
cmdline_ptr, fdt_addr, fdt_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
/* error code which can't be mistaken for valid address */
|
||||
#define EFI_ERROR (~0UL)
|
||||
|
||||
/*
|
||||
* __init annotations should not be used in the EFI stub, since the code is
|
||||
* either included in the decompressor (x86, ARM) where they have no effect,
|
||||
@@ -55,11 +52,34 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
|
||||
#define efi_info(fmt, ...) \
|
||||
efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
|
||||
#define efi_warn(fmt, ...) \
|
||||
efi_printk(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
|
||||
#define efi_err(fmt, ...) \
|
||||
efi_printk(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
|
||||
#define efi_debug(fmt, ...) \
|
||||
efi_printk(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
|
||||
|
||||
#define efi_printk_once(fmt, ...) \
|
||||
({ \
|
||||
static bool __print_once; \
|
||||
bool __ret_print_once = !__print_once; \
|
||||
\
|
||||
if (!__print_once) { \
|
||||
__print_once = true; \
|
||||
efi_printk(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
__ret_print_once; \
|
||||
})
|
||||
|
||||
#define efi_info_once(fmt, ...) \
|
||||
efi_printk_once(KERN_INFO fmt, ##__VA_ARGS__)
|
||||
#define efi_warn_once(fmt, ...) \
|
||||
efi_printk_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
|
||||
#define efi_err_once(fmt, ...) \
|
||||
efi_printk_once(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
|
||||
#define efi_debug_once(fmt, ...) \
|
||||
efi_printk_once(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Helper macros for the usual case of using simple C variables: */
|
||||
#ifndef fdt_setprop_inplace_var
|
||||
#define fdt_setprop_inplace_var(fdt, node_offset, name, var) \
|
||||
@@ -688,6 +708,35 @@ union efi_load_file_protocol {
|
||||
} mixed_mode;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u32 attributes;
|
||||
u16 file_path_list_length;
|
||||
u8 variable_data[];
|
||||
// efi_char16_t description[];
|
||||
// efi_device_path_protocol_t file_path_list[];
|
||||
// u8 optional_data[];
|
||||
} __packed efi_load_option_t;
|
||||
|
||||
#define EFI_LOAD_OPTION_ACTIVE 0x0001U
|
||||
#define EFI_LOAD_OPTION_FORCE_RECONNECT 0x0002U
|
||||
#define EFI_LOAD_OPTION_HIDDEN 0x0008U
|
||||
#define EFI_LOAD_OPTION_CATEGORY 0x1f00U
|
||||
#define EFI_LOAD_OPTION_CATEGORY_BOOT 0x0000U
|
||||
#define EFI_LOAD_OPTION_CATEGORY_APP 0x0100U
|
||||
|
||||
#define EFI_LOAD_OPTION_BOOT_MASK \
|
||||
(EFI_LOAD_OPTION_ACTIVE|EFI_LOAD_OPTION_HIDDEN|EFI_LOAD_OPTION_CATEGORY)
|
||||
#define EFI_LOAD_OPTION_MASK (EFI_LOAD_OPTION_FORCE_RECONNECT|EFI_LOAD_OPTION_BOOT_MASK)
|
||||
|
||||
typedef struct {
|
||||
u32 attributes;
|
||||
u16 file_path_list_length;
|
||||
const efi_char16_t *description;
|
||||
const efi_device_path_protocol_t *file_path_list;
|
||||
size_t optional_data_size;
|
||||
const void *optional_data;
|
||||
} efi_load_option_unpacked_t;
|
||||
|
||||
void efi_pci_disable_bridge_busmaster(void);
|
||||
|
||||
typedef efi_status_t (*efi_exit_boot_map_processing)(
|
||||
@@ -730,6 +779,8 @@ __printf(1, 2) int efi_printk(char const *fmt, ...);
|
||||
|
||||
void efi_free(unsigned long size, unsigned long addr);
|
||||
|
||||
void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size);
|
||||
|
||||
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
|
||||
|
||||
efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
|
||||
@@ -740,6 +791,9 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
|
||||
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
|
||||
unsigned long max, unsigned long align);
|
||||
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min);
|
||||
|
||||
efi_status_t efi_relocate_kernel(unsigned long *image_addr,
|
||||
unsigned long image_size,
|
||||
unsigned long alloc_size,
|
||||
@@ -786,7 +840,6 @@ efi_status_t handle_kernel_image(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);
|
||||
|
||||
asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
|
||||
|
||||
@@ -136,7 +136,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
|
||||
if (status)
|
||||
goto fdt_set_fail;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) {
|
||||
efi_status_t efi_status;
|
||||
|
||||
efi_status = efi_get_random_bytes(sizeof(fdt_val64),
|
||||
@@ -145,8 +145,6 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
|
||||
status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64);
|
||||
if (status)
|
||||
goto fdt_set_fail;
|
||||
} else if (efi_status != EFI_NOT_FOUND) {
|
||||
return efi_status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
unsigned long *load_size)
|
||||
{
|
||||
const efi_char16_t *cmdline = image->load_options;
|
||||
int cmdline_len = image->load_options_size / 2;
|
||||
int cmdline_len = image->load_options_size;
|
||||
unsigned long efi_chunk_size = ULONG_MAX;
|
||||
efi_file_protocol_t *volume = NULL;
|
||||
efi_file_protocol_t *file;
|
||||
@@ -148,6 +148,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
if (!load_addr || !load_size)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
efi_apply_loadoptions_quirk((const void **)&cmdline, &cmdline_len);
|
||||
cmdline_len /= sizeof(*cmdline);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86) && !efi_nochunk)
|
||||
efi_chunk_size = EFI_READ_CHUNK_SIZE;
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
{
|
||||
unsigned long map_size, desc_size, buff_size;
|
||||
efi_memory_desc_t *map;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ char *number(char *end, unsigned long long num, int base, char locase)
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
};
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user