Skip to content

Commit 948ef73

Browse files
committed
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
2 parents f0bf3ea + 48a4282 commit 948ef73

8 files changed

Lines changed: 68 additions & 58 deletions

File tree

drivers/firmware/efi/capsule-loader.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)
6767
cap_info->pages = temp_page;
6868

6969
temp_page = krealloc(cap_info->phys,
70-
pages_needed * sizeof(phys_addr_t *),
70+
pages_needed * sizeof(phys_addr_t),
7171
GFP_KERNEL | __GFP_ZERO);
7272
if (!temp_page)
7373
return -ENOMEM;

drivers/firmware/efi/efi-bgrt.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
2929
void *image;
3030
struct bmp_header bmp_header;
3131
struct acpi_table_bgrt *bgrt = &bgrt_tab;
32+
int mem_type;
3233

3334
if (acpi_disabled)
3435
return;
3536

36-
if (!efi_enabled(EFI_MEMMAP))
37+
if (!efi_enabled(EFI_MEMMAP) && !efi_enabled(EFI_PARAVIRT))
3738
return;
3839

3940
if (table->length < sizeof(bgrt_tab)) {
@@ -62,7 +63,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
6263
goto out;
6364
}
6465

65-
if (efi_mem_type(bgrt->image_address) != EFI_BOOT_SERVICES_DATA) {
66+
mem_type = efi_mem_type(bgrt->image_address);
67+
if (mem_type != EFI_BOOT_SERVICES_DATA &&
68+
mem_type != EFI_ACPI_RECLAIM_MEMORY) {
6669
pr_notice("Ignoring BGRT: invalid image address\n");
6770
goto out;
6871
}

drivers/firmware/efi/efi.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,9 @@ void __init efi_mem_reserve(phys_addr_t addr, u64 size)
600600
return;
601601

602602
if (!memblock_is_region_reserved(addr, size))
603-
memblock_reserve(addr, size);
603+
memblock_reserve_kern(addr, size);
604+
else
605+
memblock_reserved_mark_kern(addr, size);
604606

605607
/*
606608
* Some architectures (x86) reserve all boot services ranges
@@ -983,18 +985,12 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
983985
*/
984986
u64 efi_mem_attributes(unsigned long phys_addr)
985987
{
986-
efi_memory_desc_t *md;
988+
efi_memory_desc_t md;
987989

988-
if (!efi_enabled(EFI_MEMMAP))
990+
if (efi_mem_desc_lookup(phys_addr, &md))
989991
return 0;
990992

991-
for_each_efi_memory_desc(md) {
992-
if ((md->phys_addr <= phys_addr) &&
993-
(phys_addr < (md->phys_addr +
994-
(md->num_pages << EFI_PAGE_SHIFT))))
995-
return md->attribute;
996-
}
997-
return 0;
993+
return md.attribute;
998994
}
999995

1000996
/*
@@ -1007,18 +1003,15 @@ u64 efi_mem_attributes(unsigned long phys_addr)
10071003
*/
10081004
int efi_mem_type(unsigned long phys_addr)
10091005
{
1010-
const efi_memory_desc_t *md;
1006+
efi_memory_desc_t md;
10111007

1012-
if (!efi_enabled(EFI_MEMMAP))
1008+
if (!efi_enabled(EFI_MEMMAP) && !efi_enabled(EFI_PARAVIRT))
10131009
return -ENOTSUPP;
10141010

1015-
for_each_efi_memory_desc(md) {
1016-
if ((md->phys_addr <= phys_addr) &&
1017-
(phys_addr < (md->phys_addr +
1018-
(md->num_pages << EFI_PAGE_SHIFT))))
1019-
return md->type;
1020-
}
1021-
return -EINVAL;
1011+
if (efi_mem_desc_lookup(phys_addr, &md))
1012+
return -EINVAL;
1013+
1014+
return md.type;
10221015
}
10231016

10241017
int efi_status_to_err(efi_status_t status)

drivers/firmware/efi/libstub/fdt.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
3232
{
3333
int node, num_rsv;
3434
int status;
35-
u32 fdt_val32;
36-
u64 fdt_val64;
35+
fdt32_t fdt_val32;
36+
fdt64_t fdt_val64;
3737

3838
/* Do some checks on provided FDT, if it exists: */
3939
if (orig_fdt) {
@@ -100,13 +100,13 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
100100
if (status)
101101
goto fdt_set_fail;
102102

103-
fdt_val64 = U64_MAX; /* placeholder */
103+
fdt_val64 = cpu_to_fdt64(U64_MAX); /* placeholder */
104104

105105
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64);
106106
if (status)
107107
goto fdt_set_fail;
108108

109-
fdt_val32 = U32_MAX; /* placeholder */
109+
fdt_val32 = cpu_to_fdt32(U32_MAX); /* placeholder */
110110

111111
status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32);
112112
if (status)
@@ -147,8 +147,8 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
147147
static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
148148
{
149149
int node = fdt_path_offset(fdt, "/chosen");
150-
u64 fdt_val64;
151-
u32 fdt_val32;
150+
fdt64_t fdt_val64;
151+
fdt32_t fdt_val32;
152152
int err;
153153

154154
if (node < 0)

drivers/firmware/efi/memattr.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ unsigned long __ro_after_init efi_mem_attr_table = EFI_INVALID_TABLE_ADDR;
2222
void __init efi_memattr_init(void)
2323
{
2424
efi_memory_attributes_table_t *tbl;
25-
unsigned long size;
2625

2726
if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR)
2827
return;
@@ -40,22 +39,42 @@ void __init efi_memattr_init(void)
4039
goto unmap;
4140
}
4241

42+
/*
43+
* The EFI memory attributes table descriptors might potentially be
44+
* smaller than those used by the EFI memory map, as long as they can
45+
* fit a efi_memory_desc_t. However, a larger descriptor size makes no
46+
* sense, and might be an indication that the table is corrupted.
47+
*
48+
* The only exception is kexec_load(), where the EFI memory map is
49+
* reconstructed by user space, and may use a smaller descriptor size
50+
* than the original. Given that, ignoring this companion table is
51+
* still the right thing to do here, but don't complain too loudly when
52+
* this happens.
53+
*/
54+
if (tbl->desc_size < sizeof(efi_memory_desc_t) ||
55+
tbl->desc_size > efi.memmap.desc_size) {
56+
pr_warn("Unexpected EFI Memory Attributes descriptor size %u (expected: %lu)\n",
57+
tbl->desc_size, efi.memmap.desc_size);
58+
goto unmap;
59+
}
4360

4461
/*
45-
* Sanity check: the Memory Attributes Table contains up to 3 entries
46-
* for each entry of type EfiRuntimeServicesCode in the EFI memory map.
47-
* So if the size of the table exceeds 3x the size of the entire EFI
48-
* memory map, there is clearly something wrong, and the table should
49-
* just be ignored altogether.
62+
* Sanity check: the Memory Attributes Table contains multiple entries
63+
* for each EFI runtime services code or data region in the EFI memory
64+
* map, each with the permission attributes that may be applied when
65+
* mapping the region. There is no upper bound for the number of
66+
* entries, as it could conceivably contain more entries than the EFI
67+
* memory map itself. So pick an arbitrary limit of 64k, which is
68+
* ludicrously high. This prevents a corrupted table from eating all
69+
* system RAM.
5070
*/
51-
size = tbl->num_entries * tbl->desc_size;
52-
if (size > 3 * efi.memmap.nr_map * efi.memmap.desc_size) {
71+
if (tbl->num_entries > SZ_64K) {
5372
pr_warn(FW_BUG "Corrupted EFI Memory Attributes Table detected! (version == %u, desc_size == %u, num_entries == %u)\n",
5473
tbl->version, tbl->desc_size, tbl->num_entries);
5574
goto unmap;
5675
}
5776

58-
tbl_size = sizeof(*tbl) + size;
77+
tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
5978
memblock_reserve(efi_mem_attr_table, tbl_size);
6079
set_bit(EFI_MEM_ATTR, &efi.flags);
6180

include/linux/efi.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -832,27 +832,6 @@ extern int __init parse_efi_signature_list(
832832
const void *data, size_t size,
833833
efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));
834834

835-
/**
836-
* efi_range_is_wc - check the WC bit on an address range
837-
* @start: starting kvirt address
838-
* @len: length of range
839-
*
840-
* Consult the EFI memory map and make sure it's ok to set this range WC.
841-
* Returns true or false.
842-
*/
843-
static inline int efi_range_is_wc(unsigned long start, unsigned long len)
844-
{
845-
unsigned long i;
846-
847-
for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) {
848-
unsigned long paddr = __pa(start + i);
849-
if (!(efi_mem_attributes(paddr) & EFI_MEMORY_WC))
850-
return 0;
851-
}
852-
/* The range checked out */
853-
return 1;
854-
}
855-
856835
/*
857836
* We play games with efi_enabled so that the compiler will, if
858837
* possible, remove EFI-related code altogether.

include/linux/memblock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
155155
int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
156156
int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
157157
int memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t size);
158+
int memblock_reserved_mark_kern(phys_addr_t base, phys_addr_t size);
158159
int memblock_mark_kho_scratch(phys_addr_t base, phys_addr_t size);
159160
int memblock_clear_kho_scratch(phys_addr_t base, phys_addr_t size);
160161

mm/memblock.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,21 @@ int __init_memblock memblock_reserved_mark_noinit(phys_addr_t base, phys_addr_t
11151115
MEMBLOCK_RSRV_NOINIT);
11161116
}
11171117

1118+
/**
1119+
* memblock_reserved_mark_kern - Mark a reserved memory region with flag
1120+
* MEMBLOCK_RSRV_KERN
1121+
*
1122+
* @base: the base phys addr of the region
1123+
* @size: the size of the region
1124+
*
1125+
* Return: 0 on success, -errno on failure.
1126+
*/
1127+
int __init_memblock memblock_reserved_mark_kern(phys_addr_t base, phys_addr_t size)
1128+
{
1129+
return memblock_setclr_flag(&memblock.reserved, base, size, 1,
1130+
MEMBLOCK_RSRV_KERN);
1131+
}
1132+
11181133
/**
11191134
* memblock_mark_kho_scratch - Mark a memory region as MEMBLOCK_KHO_SCRATCH.
11201135
* @base: the base phys addr of the region

0 commit comments

Comments
 (0)