Page 1 of 1

Question about UEFI's GetMemoryMap

Posted: Wed Jun 12, 2024 6:06 am
by papabearx
Hello everyone,

There's something I don't quite understand about the results returned from the UEFI's GetMemoryMap function. One of the descriptors contains the following data:

Type 7 (EfiConventionalMemory)
Physical Start: 0x0000000100000000
End: 0x000000021effffff
Number of Pages: 0x11f000 (decimal: 1,175,552 pages)

However, the machine only has 8GB of physical RAM installed. As far as I know, the last physically addressable byte should be at (physical) memory address 0x1FFFFFFFF. But this descriptor is describing a block of memory that goes beyond that.

The first thing that came to mind was that this descriptor is describing a contiguous block in virtual memory and that it doesn't necessarily have to be a contiguous block in physical memory. However, on page 28 in the UEFI specs 2.10 (aug29) document it says this:

"Paging mode is enabled and any memory space defined by the UEFI memory map is identity mapped (virtual address equals physical address)"

But if that were true, then virtual address 0x000000021effffff would point to a physical address that's not there.

Or am I misinterpreting the UEFI documentation and these 1 million pages are scattered as page frames in physical memory? That doesn't sound right to me though. Can anybody explain what's going on?

Re: Question about UEFI's GetMemoryMap

Posted: Wed Jun 12, 2024 9:24 am
by nullplan
A lot of PCI hardware requires I/O memory to work, and I/O memory must be in addresses not in use otherwise. And a lot of that hardware can only deal with 32-bit physical addresses. For that reason, a lot of chipsets include ways to program in an I/O memory hole below the 4GB mark. Unlike the old real-mode memory hole from 640kB to 1MB, or the somewhat newer hole from 15 to 16MB, this one is typically quite substantial. In your case, it is just under 1/2 GB. That's why the RAM there is not simply lost, but remapped to the other end of address space.

That's why the highest address is beyond the size of RAM.

Re: Question about UEFI's GetMemoryMap

Posted: Wed Jun 12, 2024 5:07 pm
by zaval
yes, you are misinterpreting the spec. UEFI Memory Map describes physical (system address) space and not virtual (even if there is also a field for virtual addresses in the descriptor). I only add, that the descriptor, you showed describes
4592MB of contiguous memory, starting at the byte number 0x100000000 in the system address space and there is nothing wrong with it. UEFI is pretty clear about it. For example, there is a type, called EFI_PHYSICAL_ADDRESS and the descriptor calls its field quite unambiguously: PhysicalStart.

Re: Question about UEFI's GetMemoryMap

Posted: Wed Jun 12, 2024 9:12 pm
by Octocontrabass
RAM can be located anywhere in the CPU's physical address space. Sure, most chipsets try to place RAM at the lowest possible physical addresses (leaving gaps for things like 32-bit PCI MMIO), but there's nothing saying they have to do that.

Re: Question about UEFI's GetMemoryMap

Posted: Thu Jun 13, 2024 1:17 am
by papabearx
Ok, so I have rearranged the descriptors and put them in order and carefully went through every single one of them to see if the physical starting address of one entry matched the ending address of its previous entry. And indeed you are right, nullplan, there are holes in the memory map. There's one hole from 640k to 1MB (0xA0000 - 0x100000), another one (~400MB) just below the 4GB mark (0xDF000000 - 0xF8000000) and a few minor ones after each MMIO entry.

So that explains why the highest address is beyond the size of physical RAM. Thanks for that.

Now, let's assume I wanted to use this contiguous block of memory - the 1,175,552 pages mentioned in my previous post - for my own use using my own page tables. It seems to me that I'd need to create a page table entry for the first 4K page and set its physical address field to what's been provided by the EUFI memory map, in this case 0x100000000. Then create a second page table entry for the second page and set its physical address field to 0x100001000, and so on and so on... But what physical address do I need to put into the page table entry for page number 1,048,576? Surely it can't be 0x200000000 on a machine with only 8GB of RAM.

Re: Question about UEFI's GetMemoryMap

Posted: Thu Jun 13, 2024 6:21 am
by JAAman
papabearx wrote: But what physical address do I need to put into the page table entry for page number 1,048,576? Surely it can't be 0x200000000 on a machine with only 8GB of RAM.
why not?

the addresses in the table are the physical addresses you should use
the memory exists at that address, and any time you need the physical address of the memory, that is the address you use

it is completely possible for there to be no memory at all anywhere below 4GB -- or even to have all memory exist above 128GB, no memory at all any lower, and all memory mapped above (just because that hasn't, in the past, been common, doesn't mean it won't become common in the future)

when the CPU wants to access memory, it will look in the page tables to see what address it should put on the address bus.
every device attached to the system (including memory) watches the address bus for a particular address, and responds when it sees it (yes, it is possible, and sometimes even desirable, for multiple devices to respond to the same address -- back in the old days this was used to support shadow memory)

you must tell the CPU in the page tables, what address the memory you are using responds to, otherwise the CPU won't be able to use it. the starting address in the memory map tells you what address that block of memory responds to

Re: Question about UEFI's GetMemoryMap

Posted: Thu Jun 13, 2024 12:16 pm
by papabearx
Ah, I think I'm beginning to understand now. I always thought of the physical address space as one big contiguous block, byte addressable with addresses ALWAYS running contiguously from 0 to whatever the RAM's maximum capacity is minus 1 (e.g. 0xFFFFFFFF for 4GB of RAM or 0x3FFFFFFFF for 16GB of RAM). I thought those were hard limits and didn't think it was possible to use any of the addresses outside of that range, not in physical space anyways.

I feel so stupid for not seeing this earlier. UEFI's memory map makes a lot more sense now. I know now how to proceed.

Thank you nullplan, zaval, Octocontrabass and Jaaman for your help. Truly appreciated.

Re: Question about UEFI's GetMemoryMap

Posted: Thu Jun 13, 2024 1:58 pm
by nullplan
papabearx wrote:I always thought of the physical address space as one big contiguous block, byte addressable with addresses ALWAYS running contiguously from 0 to whatever the RAM's maximum capacity is minus 1 (e.g. 0xFFFFFFFF for 4GB of RAM or 0x3FFFFFFFF for 16GB of RAM). I thought those were hard limits and didn't think it was possible to use any of the addresses outside of that range, not in physical space anyways.
What you're describing is how simple computers worked, including the earliest PCs. In those, the system bus was fixed, so any given address would always talk to the same chip (or the open bus, if there was no chip there), and there was no possibility of an interception. Address 0 would always go to RAM, address 0xA0000 would always go to the video card, and address 0xFFFF0 would always go to the BIOS ROM. But PCs haven't worked this way for a long time now, and ever since the early 90ies or so, the CPU is directly connected only to the Northbridge (Memory Controller). I think that came together with the 486 and the abandonment of the VESA Local Bus. So all memory accesses go to the Northbridge, and then it can decide what to do with the access. (Further advancements in PC architecture have moved the Northbridge into the CPU die, but that is immaterial here. And Intel is now insisting on calling the thing a "Memory Controller Hub", but that is also immaterial). Meaning that the physical addresses you see also end up being remapped by the Northbridge. Because it has to forward the request to whatever hardware is in the system.

That is BTW how the thing can even boot. The boot ROM hasn't been a parallel ROM for a long time now as well. It is almost always a serial ROM. That is only possible because when the CPU asks for an address in the boot ROM, the Northbridge knows to ask the Southbridge for it, and the Southbridge knows what kind of serial ROM it is, and how to ask it for the requested address.
papabearx wrote:I feel so stupid for not seeing this earlier.
Don't. You didn't know something, and now you've learned it. That fact deserves praise, not ridicule.