Search code examples
memoryosdevuefi

UEFI-booted kernel: static physical memory layout


As part of my OS course I will need to write my own tiny OS kernel run under QEMU with UEFI (OSVF). The UEFI spec seems to be pretty complex, and one thing that is slipping away from me is if it is possible to have a static (compile-time defined) physical memory layout, so that my kernel has a reasonable amount of physical memory available while also preserving the UEFI-used areas.

Let me clarify using xv6 as an example. It has a simple hand-made bootloader run by legacy BIOS. According to the xv6 book, this OS allocates physical memory as follows:

+------------------+ 
|    Free Space    |
+------------------+ 0x00500000
|      Kernel      |
+------------------+ 0x00100000
|   BIOS and I/O   | <------------ Bootloader code is loaded here
+------------------+ 0x00000000

The reason why such a simple layout is possible is that all the "magic" memory used by devices and BIOS is located within the physical range [0x00000000; 0x000FFFFF]. In particular, the bootloader is loaded within this range and is then free to choose any memory region to load the kernel into. The free space starting at 0x00500000 can be allocated for userspace programs' needs.

I would like to have a similarly simple memory layout in UEFI-booted kernel; however, it doesn't seem to be a straightforward thing to do. The problems are:

  1. It looks like there is no way to define an address for the UEFI firmware to load my kernel at - instead, the firmware chooses an address at runtime;
  2. It seems there is no reasonably small physical address range that is guaranteed to contain all the UEFI-used memory, so that I could assume the rest of the RAM to be free for the kernel to use.

One of the ways these problems could be solved is using the UEFI-provided memory map via GetMemoryMap(). The map describes all the regions of memory used by the firmware. However, figuring out the memory layout at runtime complicates things as opposed to static memory layout, like the one utilized by xv6. I am willing to sacrifice some RAM space for the sake of simplicity.

So is there a way to achieve a static physical memory layout in my UEFI-booted kernel?


Solution

  • So is there a way to achieve a static physical memory layout in my UEFI-booted kernel?

    No. You can try to statically allocate an area of physical memory that happens to work for one computer (the memory manager built into UEFI does have an "allocate page/s at this specific physical address" functionality), but there's no guarantee that the range of physical addresses won't be reserved by UEFI on any other computer; and it makes no difference which physical address range it is.

    Instead, before your boot code enables paging it can happily use pages allocated from UEFI's memory manager and/or memory pre-allocated in your boot loader's ".bss" section without caring about what the physical addresses are; and after your boot code enables paging the physical addresses become irrelevant for almost everything (and you can use your virtual address spaces however you like, including statically allocating virtual address ranges in kernel space if you don't like security/KASLR).

    Mostly, for UEFI, if it was possible/supported there'd be no benefit to statically allocated physical addresses and it wouldn't make anything simpler.