Page 1 of 2
Memory detection - Int 0x15, ax = 0xE802
Posted: Sun Jul 29, 2007 1:24 pm
by Brendan
Hi,
I'm currently doing a revision of my memory detection code, and have found several places saying that "int 0x15, ax = 0xE802" should be used if "int 0x15, eax = 0xE820" isn't supported (including Ralph Brown's Interrupt List, the
OS Dev Wiki page and a few other places).
Does anyone have a description of this BIOS function?
The
information for this function from Ralph Brown's Interrupt list says:
Compaq Contura - GET ???
EAX = E802h
Return:
CF clear AX = 0000h BX = ??? CX = 0000h
Obviously this isn't very descriptive, and I haven't been able to find anything else that says anything about this BIOS function....
Thanks,
Brendan
Posted: Sun Jul 29, 2007 3:11 pm
by jnc100
edit: shorter link
http://lkml.org/lkml/1998/11/18/48
These are the only other references I found. From the sounds of both, e802 is really rare. The first one also mentions that some of the int 15h functions can crash the system if they are used and the bios doesn't support it, although it doesn't say whether e802 is one that would.
I don't have any experience using it (I've used e820 in my own bootloader and nowadays just rely on grub) so can't really advise you. I wonder if its worth the hassle as I understand the contura is a 486 notebook. Obviously if you plan to support 486s then you may want to look into it, but if you compile for i586 and above for other reasons then I guess the argument is redundant.
I suppose you could do a linux type way and accept a ram= kernel command line to override anything found by e820, e801, e881 et al, and maybe also accept the option ram=e802 which would use the e802 test but only if the user asks for it (or automate its use with the installer option: Do you have a Compaq Contura?).
Regards,
John.
Posted: Sun Jul 29, 2007 3:45 pm
by B.E
I had a quick look, and found nothing extra. From what I can see, it's a bios specific interrupt. I did however search though the source code of grub & grub2 and Freebsd's bootloader and couldn't find any reference to the use of the interrupt.
If it's really needed I would reverse engineer(i.e call the interrupt and see what it returns). Otherwise I would just use the E801 interrupt.
@jnc100: Fix up you links (i.e make them shorter).
Posted: Sun Jul 29, 2007 4:10 pm
by jnc100
B.E wrote:@jnc100: Fix up you links (i.e make them shorter).
Happy now?
Blame google if you must. Besides, they fit the screen perfectly on my shiny new widescreen laptop.
Posted: Sun Jul 29, 2007 4:35 pm
by Brendan
Hi,
Thanks - at least I know which computers use this (badly documented) BIOS function now..
jnc100 wrote:These are the only other references I found. From the sounds of both, e802 is really rare. The first one also mentions that some of the int 15h functions can crash the system if they are used and the bios doesn't support it, although it doesn't say whether e802 is one that would.
The BIOS functions themselves shouldn't crash - they may set the carry flag, return "ah=0x86 (unsupported function)", return "ah = 0x80 (invalid command)" or (for seriously buggy BIOSs) return with nothing changed.
An OS that uses these BIOS functions and doesn't detect misleading return values can crash though. For an example, Int 0x15, AH=0x88 is meant to return the number of KB above 1 MB in AX, but if it's not supported it could return "ah = 0x86". A badly written OS might think this means there's more than 34 MB (more than 0x8600 KB of RAM above 1 MB), and then crash when it tries to use the "RAM"...
For Int 0x15, ah = 0xC7 there's another function that you need to use to determine if Int 0x15, ah = 0xC7 is supported. See
Int 0x15, ah = 0xC0 (feature byte #2, bit 4), or alternatively, see
my old code memory detection code for Int 0x15, ah = 0xC7.
jnc100 wrote:I suppose you could do a linux type way and accept a ram= kernel command line to override anything found by e820, e801, e881 et al, and maybe also accept the option ram=e802 which would use the e802 test but only if the user asks for it (or automate its use with the installer option: Do you have a Compaq Contura?).
In my exaggerated opinion, the Linux/GRUB way is to do a half-assed job and then expect the user to fix things when it goes wrong...
My way is to do as much as I possibly can to ensure code does work right, and then expect the user to let me know when things don't work right so I can fix the problem (for them and everyone else). This means doing everything I can to avoid the need for a "mem=" kernel option, and then not providing any "mem=" option.
BTW I do support 80486 - there's lots of people with old/obsolete computers that aren't "good enough" for newer operating systems (including me).
Thanks,
Brendan
Posted: Sun Jul 29, 2007 5:23 pm
by Brendan
Hi,
B.E wrote:I had a quick look, and found nothing extra. From what I can see, it's a bios specific interrupt. I did however search though the source code of grub & grub2 and Freebsd's bootloader and couldn't find any reference to the use of the interrupt.
I tried that too - checked GRUB, Linux, Plan9, etc. Most seem to use Int 0x15 eax = 0xE820, Int 0x15 eax = 0xE801, Int 0x15 eax = 0x88, CMOS locations, and nothing else.
B.E wrote:If it's really needed I would reverse engineer(i.e call the interrupt and see what it returns). Otherwise I would just use the E801 interrupt.
Unfortunately (AFAIK) none of my computers support the interrupt - they just return "ah = 0x86 (unsupported function)"....
Cheers,
Brendan
Posted: Sun Jul 29, 2007 5:41 pm
by B.E
Brendan wrote:Unfortunately (AFAIK) none of my computers support the interrupt - they just return "ah = 0x86 (unsupported function)"
I have to ask the question, is it worth worrying about if only a little percent of the users have the interrupt, when you can get the same information from a more portable source. Although it's not recommended to do so, I would just use standard calls and when someone actually need the call, than worry about it.
Posted: Sun Jul 29, 2007 7:05 pm
by Brendan
Hi,
B.E wrote:Brendan wrote:Unfortunately (AFAIK) none of my computers support the interrupt - they just return "ah = 0x86 (unsupported function)"
I have to ask the question, is it worth worrying about if only a little percent of the users have the interrupt, when you can get the same information from a more portable source. Although it's not recommended to do so, I would just use standard calls and when someone actually need the call, than worry about it.
Can I get the same information from a more portable source?
My OS currently tries 5 different BIOS functions and then tries CMOS locations. You'd think that'd be enough, but I've still got an 80486 machine here where all of that fails and the OS does manual probing.
Part of the problem is that if better BIOS functions aren't present, my OS falls back to worse BIOS functions, and can then reject the data returned due to BIOS limitations. For example, for "Int 0x15 AH = 0x88" my OS rejects the returned data if the BIOS says there's 65535 KB above 1 MB (the most this function can return) or if the BIOS says there's 15 MB above 1 MB (a value often returned when there's more that 16 MB of RAM).
I don't want end-users running the OS on 16 MB (or 64 MB) when there's more RAM present, I don't want a "mem=" kernel option, and I don't want to do manual probing. I guess you could say I'm fussy....
Still, it seems I have no choice - without information about "int 0x15, ax = 0xE802" I can't use it, and will have to forget about it (again).
Cheers,
Brendan
Posted: Sun Jul 29, 2007 8:10 pm
by Brynet-Inc
If you are unable to detect the memory on that 486 with all the conventional methods, perhaps the fault is in the system..
Posted: Mon Jul 30, 2007 7:18 am
by B.E
Brendan wrote:... but I've still got an 80486 machine here where all of that fails and the OS does manual probing.
Have you tried
int 0x12, also the bios stores the amount of memory at 0x0040:0x0013
Brendan wrote:Part of the problem is that if better BIOS functions aren't present, my OS falls back to worse BIOS functions, and can then reject the data returned due to BIOS limitations. For example, for "Int 0x15 AH = 0x88" my OS rejects the returned data if the BIOS says there's 65535 KB above 1 MB (the most this function can return) or if the BIOS says there's 15 MB above 1 MB (a value often returned when there's more that 16 MB of RAM).
Don't forget, these interrupts were around before the 32-bit processor was 'invented', and as such can only give you a sixteen bit answer.
Brendan wrote:
I don't want end-users running the OS on 16 MB (or 64 MB) when there's more RAM present, I don't want a "mem=" kernel option, and I don't want to do manual probing. I guess you could say I'm fussy....
Still, it seems I have no choice - without information about "int 0x15, ax = 0xE802" I can't use it, and will have to forget about it (again).
These are problems that (if I remember correctly) some OSes in the past have had to overcome (can't remember details of such operating systems {but that my be due to the fact that it's 12 am ATM}).
Posted: Tue Jul 31, 2007 12:46 am
by Brendan
Hi,
Brynet-Inc wrote:If you are unable to detect the memory on that 486 with all the conventional methods, perhaps the fault is in the system..
Hehe, the fault is in the system. Don't you think it's strange that there's at least 5 different BIOS functions to detect RAM to begin with?
IIRC the specific 80486 I mentioned actually does have 16 MB of RAM, and some of the old "get extended memory size" functions probably do say that there's 16 MB of RAM installed. However, my OS can't assume that there's 16 MB of RAM when these BIOS functions say there's 16 MB of RAM because these older BIOS functions are dodgy and say there's 16 MB of RAM installed when there's more.
If the same 80486 had 8 MB of RAM then my OS would detect it with BIOS functions correctly (and wouldn't reject the BIOSs results). If the same 80486 had 32 MB of RAM the BIOS functions would probably still tell me there's 16 MB of RAM like they do now, and I'd have to do manual probing.
It is possible that all computers that don't support better "get extended memory size" functions aren't designed to handle more than 16 MB of RAM and can't have more than 16 MB installed. In this case, if better BIOS functions aren't present I would be able to trust the older BIOS functions when they say 16 MB of RAM is installed (instead of rejecting them).
However this is more complicated than it sounds - the computer might support more than 16 MB of RAM and provide "int 0x15, ax = 0xE802" (or any other BIOS function that the OS doesn't support) or better BIOS functions may be present but may have been rejected by the OS for some reason. There's also no way I can be sure that "better BIOS functions not present" does imply "maximum of 16 MB or less".
Again, I should point out I'm seeking perfection here. My existing code probably does work on 99.9% of all (80486 and later) computers, and is already much better than the memory detection code I've seen in any other OS and GRUB. It's the last 0.1% I'm worried about, because (unlike other OSs) I really do not want to provide kernel options so that users can get that last 0.1% working correctly...
B.E wrote:Have you tried
int 0x12, also the bios stores the amount of memory at 0x0040:0x0013
Yes, but Int 0x12 (and 0x0040:0x0013) only return the amount of usable RAM below 1 MB - even though it always works it can't tell the OS how much memory there is above 1 MB.
B.E wrote:Brendan wrote:Part of the problem is that if better BIOS functions aren't present, my OS falls back to worse BIOS functions, and can then reject the data returned due to BIOS limitations. For example, for "Int 0x15 AH = 0x88" my OS rejects the returned data if the BIOS says there's 65535 KB above 1 MB (the most this function can return) or if the BIOS says there's 15 MB above 1 MB (a value often returned when there's more that 16 MB of RAM).
Don't forget, these interrupts were around before the 32-bit processor was 'invented', and as such can only give you a sixteen bit answer.
It's worse than that. For example, "Int 0x15 ax = 0x88" returns "number of KB above 1 MB" as a 16-bit number. In theory this should work if there's up to 65535 KB at 1 MB. In practice often the BIOS limits this value to 15 MB or 63 MB (depending on the BIOS), and if there's an ISA hole at 0x000F00000 it won't return more than 14 MB regardless of how much more RAM is installed (because it's not contiguous RAM).
Cheers,
Brendan
Posted: Tue Jul 31, 2007 7:36 am
by Brynet-Inc
Just an idea, but like you said.. the older BIOS functions usually have a limit of detecting 16MB..
How about prompting the user? for example.. you know that 486 has 16MB of ram so you could simply "confirm" that's the size of RAM.
If a user is prompted with the "Does your system have 16MB of RAM" message and actually has 32MB, then couldn't manual probing be used?
Just rambling - Sorry.. But I agree.. detecting memory is so flaky..
(
Let's all just support i2c and read the EEPROM information off of SDRAM!! )
Posted: Tue Jul 31, 2007 8:46 am
by SpooK
Personally, I support E820->E881->E801->CMOS in order and that should be more than enough for any modern operating system. You can't save the world.
Posted: Tue Jul 31, 2007 8:55 am
by Brendan
Hi,
Brynet-Inc wrote:How about prompting the user? for example.. you know that 486 has 16MB of ram so you could simply "confirm" that's the size of RAM.
That's difficult for me (the OS supports headless systems with no keyboard present). It's also the sort of thing that horrifies users - would you honestly trust an OS that can't even detect the amount of RAM installed correctly?
Brynet-Inc wrote:If a user is prompted with the "Does your system have 16MB of RAM" message and actually has 32MB, then couldn't manual probing be used?
My current code uses the following methods in order, stopping when one of them works:
- BIOS interrupt 0x15, EAX=0xE820 (ACPI 3.0)
BIOS interrupt 0x15, EAX=0xE820
BIOS interrupt 0x15, AX=0xE881
BIOS interrupt 0x15, AX=0xE801
BIOS interrupt 0x15, AH=0xC7
BIOS interrupt 0x15, AH=0x88
CMOS locations 0x17 and 0x18
Manual probing
So far I've modified the original code so that if "Int 0x15, AH=0x88" or CMOS says there's either 14 MB or 15 MB at 0x00100000 then it'll probe for memory above 0x01000000; and if "Int 0x15, AH=0x88" or CMOS says there's either 64 MB or 65535 KB at 0x00100000 then it'll probe for memory above 0x04000000. The original code would just reject the values and manually probe for all memory starting at 0x00100000 - the newer code still does some probing (it just does less probing)...
I'm also considering removing the "Int 0x15, AH=0xC7" code. I've tried 6 computers so far without finding a machine that supports it, and I'm only guessing which values mean what (Ralph Brown's Interrupt list isn't very specific and I'm having trouble finding better documentation for this BIOS function too). I've still got a more computers to check before I remove this code, but it looks like it'll be gone soon.
Lastly, there's a few other BIOS functions -
"int 0x15, ah = 0x8A" and
"int 0x15, ax = 0xDA88". I might try them to see if they're present on any of my machines (especially that 80486), and add support for them (regardless of whether I can test them or not - they're both simple and unambiguous).
BTW in my testing I plugged that old 80486 in to check some things (half my computers live in a closet with nothing plugged into them), and found out my new code uses CMOS locations 0x17 and 0x18, and that there's actually only 8 MB of RAM installed (and that the CMOS battery has gone flat
).
Brynet-Inc wrote:Just rambling - Sorry.. But I agree.. detecting memory is so flaky..
(
Let's all just support i2c and read the EEPROM information off of SDRAM!! )
Hehe, no - computers that are new enough to have SPD data are also new enough to support decent BIOS functions...
Cheers,
Brendan
Posted: Tue Jul 31, 2007 9:46 am
by inflater
I think AX=E820 with INT 15h should work. I use it borrowed from DexOS, and it works in Bochs, QEMU, MS VPC, VMware Workstation, and my development computer and the testbed (testbed is a pentium-s 120 MHz, 40 MB RAM, and dev PC is pentium 4 1.8 GHz, 256 MB RAM).
Note that detecting memory from CMOS may return strange results if the memory is above 64 MB RAM. So I wouldn't use this. And INT 12h, that's almost 0x280 - 640 kB, except if some MBR protector program, viruses or something other (if running under DOS) is present in RAM. Or you may get a lower value too
, do you have the original IBM PC from 1981 or PCjr in your house somewhere?
inflater