mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2026-08-26 21:27:15 -05:00
aarch64: fix SMBIOS parsing crash when loaded via shim
map startup-only regions as Normal memory
This commit is contained in:
+14
-8
@@ -8,7 +8,8 @@
|
||||
// regions described by the BIOS/EFI memory map, so all mapping functions
|
||||
// simply return the physical address unchanged. RAM is mapped as Normal
|
||||
// write-back cacheable memory, the frame buffer as Normal non-cacheable
|
||||
// memory, and anything else mapped on demand (MMIO) as Device-nGnRnE.
|
||||
// memory, and anything else mapped on demand either as Normal write-back
|
||||
// (RAM-resident firmware tables) or as Device-nGnRnE (MMIO).
|
||||
//
|
||||
// The tables use the 4KB granule with a 48-bit input address range and
|
||||
// are built from 1GB and 2MB block descriptors only. paging_init() is
|
||||
@@ -66,6 +67,7 @@
|
||||
typedef struct {
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
uint64_t attrs;
|
||||
} device_region_t;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -287,13 +289,13 @@ void paging_init(void)
|
||||
paging_incomplete |= !map_range(cmd_line_start, cmd_line_end, PTE_ATTR_NORMAL);
|
||||
}
|
||||
|
||||
// Replay the device mappings made via map_region.
|
||||
// Replay the mappings made via map_region.
|
||||
for (int i = 0; i < num_device_regions; i++) {
|
||||
paging_incomplete |= !map_range(device_regions[i].start, device_regions[i].end, PTE_ATTR_DEVICE);
|
||||
paging_incomplete |= !map_range(device_regions[i].start, device_regions[i].end, device_regions[i].attrs);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __attribute__((unused)))
|
||||
uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup)
|
||||
{
|
||||
if (size == 0) {
|
||||
size = 1;
|
||||
@@ -304,6 +306,12 @@ uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __a
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Startup-only regions are RAM-resident firmware tables (ACPI, SMBIOS,
|
||||
// ...) and must be mapped as Normal memory: their parsers do unaligned
|
||||
// accesses, which fault on Device memory. Everything else is assumed
|
||||
// to be MMIO. Regions mapped earlier keep their original attributes.
|
||||
uint64_t attrs = only_for_startup ? (PTE_ATTR_NORMAL | PTE_PXN) : PTE_ATTR_DEVICE;
|
||||
|
||||
// Record the region (at block granularity) so the mapping can be
|
||||
// replayed when the page tables are rebuilt after relocation.
|
||||
uint64_t start = base_addr & ~(BLOCK_2M - 1);
|
||||
@@ -320,13 +328,11 @@ uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup __a
|
||||
}
|
||||
device_regions[num_device_regions].start = start;
|
||||
device_regions[num_device_regions].end = end;
|
||||
device_regions[num_device_regions].attrs = attrs;
|
||||
num_device_regions++;
|
||||
}
|
||||
|
||||
// Anything not already mapped is assumed to be MMIO and gets a Device
|
||||
// mapping. Regions mapped earlier (e.g. RAM, the frame buffer) keep
|
||||
// their original attributes.
|
||||
if (!map_range(base_addr, base_addr + size, PTE_ATTR_DEVICE)) {
|
||||
if (!map_range(base_addr, base_addr + size, attrs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user