Page 1 of 2

int 0x15/e820 Memory Map

Posted: Fri Aug 22, 2003 9:50 pm
by SFX
Hi,

I am currently writing a function to probe the memory map, I am using the Ralph Brown Interrupt List and just have a question about something it says
this function will return base memory and ISA/PCI memory contiguous
    with base memory as normal memory ranges; it will indicate
    chipset-defined address holes which are not in use and motherboard
    memory-mapped devices, and all occurrences of the system BIOS as
    reserved; standard PC address ranges will not be reported
Ok, I understand all this except the last statement
standard PC address ranges will not be reported
How can I determine how much memory is installed if normal PC ranges are not being reported, or are these ranges things like the first MB and stuff that is assumed to be in all PC's, however I thought that this function provided a memory map for the entire addressable memory.

Also, when I get the memory map, two ranges are returned that are 'NOT DEFINED RANGE TYPES' the docs say to assume this is reserved, but is there a way to determine what they are being used for.

And lastly, what is an NVS session, some ranges can be of this type, does anyone know where I can get some docs for this.

thanks.

I decided to include the entire info for this interrupt so that it might be easier to understand what I am talking about.
INT 15 - newer BIOSes - GET SYSTEM MEMORY MAP
   AX = E820h
   EAX = 0000E820h
   EDX = 534D4150h ('SMAP')
   EBX = continuation value or 00000000h to start at beginning of map
   ECX = size of buffer for result, in bytes (should be >= 20 bytes)
   ES:DI -> buffer for result (see #00581)
Return: CF clear if successful
    EAX = 534D4150h ('SMAP')
    ES:DI buffer filled
    EBX = next offset from which to copy or 00000000h if all done
    ECX = actual length returned in bytes
   CF set on error
    AH = error code (86h) (see #00496 at INT 15/AH=80h)
Notes:   originally introduced with the Phoenix BIOS v4.0, this function is
    now supported by most newer BIOSes, since various versions of Windows
    call it to find out about the system memory
   a maximum of 20 bytes will be transferred at one time, even if ECX is
    higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the
    value of ECX on entry, and always copy 20 bytes
   some BIOSes expect the high word of EAX to be clear on entry, i.e.
    EAX=0000E820h
   if this function is not supported, an application should fall back
    to AX=E802h, AX=E801h, and then AH=88h
   the BIOS is permitted to return a nonzero continuation value in EBX
    and indicate that the end of the list has already been reached by
    returning with CF set on the next iteration
   this function will return base memory and ISA/PCI memory contiguous
    with base memory as normal memory ranges; it will indicate
    chipset-defined address holes which are not in use and motherboard
    memory-mapped devices, and all occurrences of the system BIOS as
    reserved; standard PC address ranges will not be reported
SeeAlso: AH=C7h,AX=E801h"Phoenix",AX=E881h,MEM xxxxh:xxx0h"ACPI"

Format of Phoenix BIOS system memory map address range descriptor:
Offset   Size   Description   (Table 00580)
00h   QWORD   base address
08h   QWORD   length in bytes
10h   DWORD   type of address range (see #00581)

(Table 00581)
Values for System Memory Map address type:
01h   memory, available to OS
02h   reserved, not available (e.g. system ROM, memory-mapped device)
03h   ACPI Reclaim Memory (usable by OS after reading ACPI tables)
04h   ACPI NVS Memory (OS is required to save this memory between NVS
    sessions)
other   not defined yet -- treat as Reserved
SeeAlso: #00580

Re:int 0x15/e820 Memory Map

Posted: Fri Aug 22, 2003 10:17 pm
by K.J.
standard PC address ranges will not be reported
IIRC, that means that all the little chunks of reserved and free memory below 1MB isn't reported totally. That's not much of a problem though, just get a map of the memory below 1MB here(this never changes):
http://my.execpc.com/~geezer/osd/ram/index.htm

K.J.

Re:int 0x15/e820 Memory Map

Posted: Sat Aug 23, 2003 3:15 am
by SFX
Hi again,

thanks for the link K.J that is a good reference to have.

throughout this post there are some questions, so if you think you know the answers please fell free to let me know here.

ok, I slapped together a simple number printing routine so I could check out the ranges that this interrupt returned on my pc, here is a list of them and their types:

Type | Base | Length
------|--------------|------------------------
0x02 | 0x9FC00 | 0x400
0x02 | 0xF0000 | 0x10000
0x02 | 0xFFFF0000 | 0x10000
0x01 | 0x100000 | 0x11EF0000
N/A | 0x11FF3000 | 0xD000
N/A | 0x11FF0000 | 0x3000

This is the exact order in which they came out, I would have thought that they would come out in order of the base address but they didn't.

The first range in list is from below 1MB, according to the reference provided by K.J this is the EBDA, I have read elsewhere that this area can be overwritten after being read, but my BIOS is telling me to never overwrite this because it returned it as 'reserved, not available' is this normal behaviour??

The second range is also from below 1MB and again according to the reference provided by K.J this is the motherboard BIOS, so no worries there, but obviously there are a couple of ranges from below the 1MB area returned by this interrupt.

The third range is interesting, it is the very last MB of the 4GB address range, however I don't have this much physical memory in my pc, so how does this area get used?? My video card swipes 64MB of RAM to use for itself (set by me) and it is excluded from the total amount available to the OS, however the range it uses is not returned by the function as none of the ranges are 64MB in length. So it could be somehow mapped using this memory.

The fourth range is the free memory for the OS to use, it is just about the same as the amount windows tells me that I have minus about 500KB which I assume is from below the 1MB mark.

Now the last two ranges are interesting, I read in another post here that the sound card can be set to use 32KB or 64KB, or something to that effect so I first thought that this area (adding up to exactly 64KB) might be used for the sound card, but there are two ranges the first consisting of 52KB and the second of 12KB, so if anyone has any ideas, please, I would be happy to hear them.

As a final question, is it safe to assume that the free memory for the OS will alway's be contiguous memory or is this not alway's the case?

anyway, thanks to everyone who might have some answers for me, they are greatly appreciated.

Re:int 0x15/e820 Memory Map

Posted: Sat Aug 23, 2003 10:14 am
by Curufir
[pre]
Type | Base | Length
------|--------------|------------------------
0x02 | 0x9FC00 | 0x400
0x02 | 0xF0000 | 0x10000
0x02 | 0xFFFF0000 | 0x10000
0x01 | 0x100000 | 0x11EF0000
N/A | 0x11FF3000 | 0xD000
N/A | 0x11FF0000 | 0x3000
[/pre]

First one represents BIOS reserved space, pretty much all you'll find there is the Extended BIOS Data Area

Second one is the System BIOS

Third one is where the BIOS is remapped to the top of the 4gb address space.

Fourth one is the memory above 1Mb that contains physical memory available to the OS. In general this will be contiguous as PCI etc will be mapped high in the address space to avoid clashing with it.

Fifth and Sixth look like the ACPI memory ranges, types 3 and 4.

It actually looks like you're missing an entry here, which should be an OS available section from 0x0->0x9FC00 (Ie the low 639k of the first 1M). Haven't seen a BIOS not report this before so you might want to check your code.

**

Address space means the range of addresses the PC can generate (0->4Gb in a normal situation). Now on x86 your physical RAM will be represented as an address range from 0->size of RAM within that address space. However the motherboard is setup so that when you use certain addresses within the address space the actual RAM being addressed is contained on a separate device, or register of a device. These are called memory mapped devices.

Probably easiest to explain this with an example.

Let's say I try to place a character onscreen. The sequence goes like this (For example). I move a word value (Character + Attribute data) to 0xA8000. The CPU generates the address 0xA8000 on it's address lines. Now the motherboard has things set up so that whenever it sees an address in the range 0xA8000->0xB7FFF on the address lines what is operated on is the RAM on the video card not physical RAM. So I can read/write directly to video RAM using simple memory references, thanks to the video RAM being mapped into the address space at 0xA8000, instead of having to go through lengthy port I/O operations (Which are themselves an example of memory mapping on an x86 system).

Now in that example you actually lose the 64k of physical RAM that should be there because you can't access it, all accesses in this range go to the video RAM instead.

In the case of the 3rd entry, the remapped System BIOS, conceptually exactly the same mechanism is used. When you access that range at the top of the 4Gb address space the motherboard redirects the request to the BIOS chip. However since no physical RAM actually exists at this address, unless you happen to have 4gb of RAM lying around, you don't lose any physical RAM to addressing issues. Which is why the top of the address range is used for memory mapped operations.

Hope that clears it up.

Re:int 0x15/e820 Memory Map

Posted: Sat Aug 23, 2003 5:33 pm
by SFX
thanks that did help quite a bit, however in the interrupt docs it said it would not report any of the standard address ranges, which K.J thought was below the 1MB mark, if it does then it should also mark the IVT as reserved, I will check my code however to make sure.

With the last two ranges they came out with types higher that the predefined 0x01 - 0x04, I will run another test and print up the hex values of their types and that might help.

I understood how the memory mapping works when it comes to video memory and stuff, I just didn't realise that the processor would still use areas that do not have physical RAM.

When you say that the BIOS is remapped to the high end of the address space, does this mean there is an exact copy of the BIOS there or does this area just interact with the BIOS below 1MB, I have read that the BIOS should be left intact, but if there is a mapping to the chipset, then why do we need to keep it in physical RAM?

I might be confused here, but thanks for the info anyway, it did help quite a bit.

Re:int 0x15/e820 Memory Map

Posted: Tue Aug 26, 2003 8:34 am
by SFX
Hi all,

I have been racking my brain and testing code for days, is this true?
<>
It actually looks like you're missing an entry here, which should be an OS available section from 0x0->0x9FC00 (Ie the low 639k of the first 1M). Haven't seen a BIOS not report this before so you might want to check your code.
K.J seemed to think that the small chunks under 1MB are not reported, I have checked my code and cannot seem to find a problem. So should I get this range reported or not?

thanks guys.

Re:int 0x15/e820 Memory Map

Posted: Tue Aug 26, 2003 9:51 am
by HOS
i have been working with this function also, and found that i was actually missing the last entry returned from the bios. i had my routine stop saving entries to es:di when either the carry flag was set or ebx was returned with 0. i kept a counter to see how many 20-byte chunks were returned (how many times i called int 0x15) but i was incrementing the counter AFTER i called the interrupt, and i was not incrementing the counter when the carry flag was set or when ebx was returned with 0. now i increment the counter then also, as the last call was valid and did leave a valid range in es:di even though it returned ebx as 0 or CF set to indicate that it was done. i do not know if you are doing something similar or not, it is worth checking.

i have a question also though - why are quadwords used to hold the base and limits? is there ever a situation where the upper dword (high 4 bytes) would not be 0? and is there a data type in C to hold an 8 byte integer, or a good type of struct to hold a qword?

thanks

Re:int 0x15/e820 Memory Map

Posted: Tue Aug 26, 2003 10:12 am
by Curufir
SFX wrote: K.J seemed to think that the small chunks under 1MB are not reported, I have checked my code and cannot seem to find a problem. So should I get this range reported or not?
Sorry about that, didn't intend it to sound quite as arbitrary as it did. All I meant is that I've thrown my own e820 routine at a number of BIOS and they've all come back with 2 references below 1M. One is a range 0-639k that is available to the OS (I'd expect this one to always be there), the other is a 1k range 639k-640k that's reserved for the BIOS (Which I'd expect to be missing depending on the BIOS, it's the EBDA). Not having them doesn't mean your code is definitely wrong, it could just be that you've got an odd BIOS, or all the ones I've checked so far simply return those entries. For further info that 0-639k entry always seemed to be the first one returned, so have you zeroed ebx before the first call to e820? Or more importantly, have you increased edi to point at the next entry before calling e820 again. I'd imagine you have, so I'm as confused as you are.

***
HOS wrote: i have a question also though - why are quadwords used to hold the base and limits? is there ever a situation where the upper dword (high 4 bytes) would not be 0?
I think this is a combination of future proofing, and currently availalable systems. It's possible to dump more than 4Gb of memory into a PC, it's just unlikely any here has a motherboard capable of taking such an amount. The extended 32Gb address space gives you plenty of opportunity to go above this, and that would require the second word for some ranges I guess.
and is there a data type in C to hold an 8 byte integer, or a good type of struct to hold a qword?
Once again my C is likely to let me down, but isn't there a none-standard 'long long' 64-bit integer type defined in some compilers? If not then why not just store it in a string?

Re:int 0x15/e820 Memory Map

Posted: Tue Aug 26, 2003 10:12 pm
by SFX
Hi,

Curufir:
After reading your last post I was preparing the code I am using, to post it here, and while I was doing that I found the error.

After the initial call to 0x15/e820 I was entering the loop to get the remaining descriptors without first adding 20 to di, I was going straight to the second call and adding 20 to di after the second call at the end of the loop, which meant that the second call overwrote the first so hence the first entry was lost, I haven't tested yet but I am pretty sure I have solved the problem.

thanks for your help I would have still been going over it had you not helped me.

Re:int 0x15/e820 Memory Map

Posted: Wed Aug 27, 2003 12:49 am
by SFX
Hi,

HOS:
According to the documentation
the BIOS is permitted to return a nonzero continuation value in EBX and indicate that the end of the list has already been reached by returning with CF set on the next iteration
It is my understanding that this means that if the BIOS returns cf = 1 then the end of map was reached on the last call, so there would not be a valid descriptor in es:di however if ebx = 0 and cf = 0 then there would be a valid descriptor put into es:di, so you should increment your counter after you test cf = 1 but before you check for ebx = 0 inside your loop.

If this is wrong please let me know, but this is how I understand what Ralph Brown's Int List says.

cheers.

Re:int 0x15/e820 Memory Map

Posted: Wed Aug 27, 2003 6:18 am
by HOS
hmmm... i think you may be right, i am currently rewriting all my printing functions, when i am done with this i will be able to print out a list of all the entries returned, so as of right now i dont even know (other than debugging in bochs which doesn't help much) what entries are being put there, so i do not know if my code is bad or not. but from what you said it probably is, so thank you and i will change it to increment the counter only if ebx is 0 and not if CF is set.

Re:int 0x15/e820 Memory Map

Posted: Sun Sep 07, 2003 4:22 am
by Perica
..

Re:int 0x15/e820 Memory Map

Posted: Wed Sep 10, 2003 7:19 pm
by mr. xsism
How can you even call this interrupt in Rmode? I HOPE you can! :'(

If not i wull use E801

Regards,
mr. xsism

Re:int 0x15/e820 Memory Map

Posted: Thu Sep 11, 2003 1:18 am
by Perica
..

Re:int 0x15/e820 Memory Map

Posted: Thu Sep 11, 2003 8:17 am
by mr. xsism
but rmode isn't 32bit. How can you pass info via 32bit registers like eax,ebx,etc?

Regards,
mr. xsism