bootloader
bootloader copied to clipboard
Incorrect memory map being presented to kernel
Currently, the bootloader presents an incorrect memory map to the kernel (potentially invalidating the entire setup and making all mapped regions using that memory map incorrect). Specifically, an example (wrong) memory map is provided by me in this OSDev forum topic. According to replies in that topic, UEFI runtime services (both code and data) should be in the memory map, but none exist. Currently the Bootloader passes raw values for memory map region types. This is (not) a good thing because the UEFI specification does not specify these values, and so they may differ from implementation to implementation. Furthermore, BIOS memory types are also not specified, and so there is no point of reference for these values, and these will (undoubtedly) differ from BIOS implementation to BIOS implementation. This is a big problem. A theoretical situation where things could go (very) wrong is if an OS wants to allocate a page that it considers "free". If an OS uses a page that is (really) PAL code or NVRAM storage, but it is marked as "free" because the values are not specified by the bootloader crate in any safe abstraction, such an allocation (and then operations on such areas of RAM) could be disastrous. PAL code, in particular, could be especially bad because PAL code is specifically for (if I understand correctly) programmable array logic devices. (I don't know of implementations that do expose things like PAL code to UEFI applications or drivers, but since its in the specification, an implementation may choose to do so.) Is there a reason why the bootloader exposes memory types without any standard definition of at least the predefined region types (for UEFI) or something like it for BIOS, if it exists? For reference, the code used to generate this map was this (I needed to do manual reading of the data to get this to work):
info!("firmware-provided memory map:");
for region in boot_info.memory_regions.iter() {
info!(
"[{:X}-{:X}]: {}",
region.start,
region.end,
match region.kind {
MemoryRegionKind::Usable => "free",
MemoryRegionKind::UnknownUefi(kind) => match kind {
0 => "reserved",
1 => "loader code",
2 => "loader data",
3 => "boot services code",
4 => "boot services data",
5 => "runtime services code",
6 => "runtime services data",
8 => "unusable",
9 => "acpi reclaimable",
10 => "acpi non-volatile",
11 => "mmio",
12 => "port mmio",
13 => "pal code",
14 => "free nvm",
_ => "unknown uefi",
},
MemoryRegionKind::UnknownBios(_) => "unknown bios",
MemoryRegionKind::Bootloader => "bootloader",
_ => "Unknown",
}
);
}
Only MemoryType::CONVENTIONAL is marked aa usable in the memory map Everything else is marked as UnknownUefi: https://github.com/rust-osdev/bootloader/blob/bc6c1bd62de697dc090ff8e7131cc36b91a531f4/src/binary/uefi/memory_descriptor.rs#L17-L20
@bjorn3 I know, but that doesn't tell you much. You have to go poking around in the UEFI specification because it doesn't convert the values back into their actual memory type values. And, as the topic I linked to noted, the memory map is wrong--I should be seeing at least runtime services code in there but I'm not.