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:
Linus Torvalds
2026-04-16 08:06:25 -07:00
8 changed files with 68 additions and 58 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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.

View File

@@ -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);

View File

@@ -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