mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
Merge tag 'efi-next-for-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel:
"Again not a busy cycle for EFI, just some minor tweaks and bug fixes:
- Enable boot graphics resource table (BGRT) on Xen/x86
- Correct a misguided assumption in the memory attributes table
sanity check
- Start tagging efi_mem_reserve()'d regions as MEMBLOCK_RSRV_KERN
- Some other minor fixes and cleanups"
* tag 'efi-next-for-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
efi/capsule-loader: fix incorrect sizeof in phys array reallocation
efi: Tag memblock reservations of boot services regions as RSRV_KERN
memblock: Permit existing reserved regions to be marked RSRV_KERN
efi/memattr: Fix thinko in table size sanity check
efi: libstub: fix type of fdt 32 and 64bit variables
efi: Drop unused efi_range_is_wc() function
efi: Enable BGRT loading under Xen
efi: make efi_mem_type() and efi_mem_attributes() work on Xen PV
This commit is contained in:
@@ -67,7 +67,7 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)
|
||||
cap_info->pages = temp_page;
|
||||
|
||||
temp_page = krealloc(cap_info->phys,
|
||||
pages_needed * sizeof(phys_addr_t *),
|
||||
pages_needed * sizeof(phys_addr_t),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!temp_page)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -29,11 +29,12 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
|
||||
void *image;
|
||||
struct bmp_header bmp_header;
|
||||
struct acpi_table_bgrt *bgrt = &bgrt_tab;
|
||||
int mem_type;
|
||||
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
if (!efi_enabled(EFI_MEMMAP) && !efi_enabled(EFI_PARAVIRT))
|
||||
return;
|
||||
|
||||
if (table->length < sizeof(bgrt_tab)) {
|
||||
@@ -62,7 +63,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (efi_mem_type(bgrt->image_address) != EFI_BOOT_SERVICES_DATA) {
|
||||
mem_type = efi_mem_type(bgrt->image_address);
|
||||
if (mem_type != EFI_BOOT_SERVICES_DATA &&
|
||||
mem_type != EFI_ACPI_RECLAIM_MEMORY) {
|
||||
pr_notice("Ignoring BGRT: invalid image address\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -600,7 +600,9 @@ void __init efi_mem_reserve(phys_addr_t addr, u64 size)
|
||||
return;
|
||||
|
||||
if (!memblock_is_region_reserved(addr, size))
|
||||
memblock_reserve(addr, size);
|
||||
memblock_reserve_kern(addr, size);
|
||||
else
|
||||
memblock_reserved_mark_kern(addr, size);
|
||||
|
||||
/*
|
||||
* Some architectures (x86) reserve all boot services ranges
|
||||
@@ -983,18 +985,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
|
||||
*/
|
||||
u64 efi_mem_attributes(unsigned long phys_addr)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
efi_memory_desc_t md;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
if (efi_mem_desc_lookup(phys_addr, &md))
|
||||
return 0;
|
||||
|
||||
for_each_efi_memory_desc(md) {
|
||||
if ((md->phys_addr <= phys_addr) &&
|
||||
(phys_addr < (md->phys_addr +
|
||||
(md->num_pages << EFI_PAGE_SHIFT))))
|
||||
return md->attribute;
|
||||
}
|
||||
return 0;
|
||||
return md.attribute;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1007,18 +1003,15 @@ u64 efi_mem_attributes(unsigned long phys_addr)
|
||||
*/
|
||||
int efi_mem_type(unsigned long phys_addr)
|
||||
{
|
||||
const efi_memory_desc_t *md;
|
||||
efi_memory_desc_t md;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
if (!efi_enabled(EFI_MEMMAP) && !efi_enabled(EFI_PARAVIRT))
|
||||
return -ENOTSUPP;
|
||||
|
||||
for_each_efi_memory_desc(md) {
|
||||
if ((md->phys_addr <= phys_addr) &&
|
||||
(phys_addr < (md->phys_addr +
|
||||
(md->num_pages << EFI_PAGE_SHIFT))))
|
||||
return md->type;
|
||||
}
|
||||
return -EINVAL;
|
||||
if (efi_mem_desc_lookup(phys_addr, &md))
|
||||
return -EINVAL;
|
||||
|
||||
return md.type;
|
||||
}
|
||||
|
||||
int efi_status_to_err(efi_status_t status)
|
||||
|
||||
@@ -32,8 +32,8 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
|
||||
{
|
||||
int node, num_rsv;
|
||||
int status;
|
||||
u32 fdt_val32;
|
||||
u64 fdt_val64;
|
||||
fdt32_t fdt_val32;
|
||||
fdt64_t fdt_val64;
|
||||
|
||||
/* Do some checks on provided FDT, if it exists: */
|
||||
if (orig_fdt) {
|
||||
@@ -100,13 +100,13 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
|
||||
if (status)
|
||||
goto fdt_set_fail;
|
||||
|
||||
fdt_val64 = U64_MAX; /* placeholder */
|
||||
fdt_val64 = cpu_to_fdt64(U64_MAX); /* placeholder */
|
||||
|
||||
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
|
||||
if (status)
|
||||
goto fdt_set_fail;
|
||||
|
||||
fdt_val32 = U32_MAX; /* placeholder */
|
||||
fdt_val32 = cpu_to_fdt32(U32_MAX); /* placeholder */
|
||||
|
||||
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
|
||||
if (status)
|
||||
@@ -147,8 +147,8 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
|
||||
static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
|
||||
{
|
||||
int node = fdt_path_offset(fdt, "/chosen");
|
||||
u64 fdt_val64;
|
||||
u32 fdt_val32;
|
||||
fdt64_t fdt_val64;
|
||||
fdt32_t fdt_val32;
|
||||
int err;
|
||||
|
||||
if (node < 0)
|
||||
|
||||
@@ -22,7 +22,6 @@ unsigned long __ro_after_init efi_mem_attr_table = EFI_INVALID_TABLE_ADDR;
|
||||
void __init efi_memattr_init(void)
|
||||
{
|
||||
efi_memory_attributes_table_t *tbl;
|
||||
unsigned long size;
|
||||
|
||||
if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR)
|
||||
return;
|
||||
@@ -40,22 +39,42 @@ void __init efi_memattr_init(void)
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* The EFI memory attributes table descriptors might potentially be
|
||||
* smaller than those used by the EFI memory map, as long as they can
|
||||
* fit a efi_memory_desc_t. However, a larger descriptor size makes no
|
||||
* sense, and might be an indication that the table is corrupted.
|
||||
*
|
||||
* The only exception is kexec_load(), where the EFI memory map is
|
||||
* reconstructed by user space, and may use a smaller descriptor size
|
||||
* than the original. Given that, ignoring this companion table is
|
||||
* still the right thing to do here, but don't complain too loudly when
|
||||
* this happens.
|
||||
*/
|
||||
if (tbl->desc_size < sizeof(efi_memory_desc_t) ||
|
||||
tbl->desc_size > efi.memmap.desc_size) {
|
||||
pr_warn("Unexpected EFI Memory Attributes descriptor size %u (expected: %lu)\n",
|
||||
tbl->desc_size, efi.memmap.desc_size);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check: the Memory Attributes Table contains up to 3 entries
|
||||
* for each entry of type EfiRuntimeServicesCode in the EFI memory map.
|
||||
* So if the size of the table exceeds 3x the size of the entire EFI
|
||||
* memory map, there is clearly something wrong, and the table should
|
||||
* just be ignored altogether.
|
||||
* Sanity check: the Memory Attributes Table contains multiple entries
|
||||
* for each EFI runtime services code or data region in the EFI memory
|
||||
* map, each with the permission attributes that may be applied when
|
||||
* mapping the region. There is no upper bound for the number of
|
||||
* entries, as it could conceivably contain more entries than the EFI
|
||||
* memory map itself. So pick an arbitrary limit of 64k, which is
|
||||
* ludicrously high. This prevents a corrupted table from eating all
|
||||
* system RAM.
|
||||
*/
|
||||
size = tbl->num_entries * tbl->desc_size;
|
||||
if (size > 3 * efi.memmap.nr_map * efi.memmap.desc_size) {
|
||||
if (tbl->num_entries > SZ_64K) {
|
||||
pr_warn(FW_BUG "Corrupted EFI Memory Attributes Table detected! (version == %u, desc_size == %u, num_entries == %u)\n",
|
||||
tbl->version, tbl->desc_size, tbl->num_entries);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
tbl_size = sizeof(*tbl) + size;
|
||||
tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
|
||||
memblock_reserve(efi_mem_attr_table, tbl_size);
|
||||
set_bit(EFI_MEM_ATTR, &efi.flags);
|
||||
|
||||
|
||||
@@ -832,27 +832,6 @@ extern int __init parse_efi_signature_list(
|
||||
const void *data, size_t size,
|
||||
efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));
|
||||
|
||||
/**
|
||||
* efi_range_is_wc - check the WC bit on an address range
|
||||
* @start: starting kvirt address
|
||||
* @len: length of range
|
||||
*
|
||||
* Consult the EFI memory map and make sure it's ok to set this range WC.
|
||||
* Returns true or false.
|
||||
*/
|
||||
static inline int efi_range_is_wc(unsigned long start, unsigned long len)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) {
|
||||
unsigned long paddr = __pa(start + i);
|
||||
if (!(efi_mem_attributes(paddr) & EFI_MEMORY_WC))
|
||||
return 0;
|
||||
}
|
||||
/* The range checked out */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We play games with efi_enabled so that the compiler will, if
|
||||
* possible, remove EFI-related code altogether.
|
||||
|
||||
@@ -155,6 +155,7 @@ int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_reserved_mark_kern(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size);
|
||||
int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size);
|
||||
|
||||
|
||||
@@ -1115,6 +1115,21 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
|
||||
MEMBLOCK_RSRV_NOINIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_reserved_mark_kern - Mark a reserved memory region with flag
|
||||
* MEMBLOCK_RSRV_KERN
|
||||
*
|
||||
* @base: the base phys addr of the region
|
||||
* @size: the size of the region
|
||||
*
|
||||
* Return: 0 on success, -errno on failure.
|
||||
*/
|
||||
int __init_memblock memblock_reserved_mark_kern(phys_addr_t base, phys_addr_t size)
|
||||
{
|
||||
return memblock_setclr_flag(&memblock.reserved, base, size, 1,
|
||||
MEMBLOCK_RSRV_KERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_mark_kho_scratch - Mark a memory region as MEMBLOCK_KHO_SCRATCH.
|
||||
* @base: the base phys addr of the region
|
||||
|
||||
Reference in New Issue
Block a user