Memory Area Detection
Memory Area Detection
Hi, what are my options for detecting unreserved memory areas. Is interrupt 15h AX=0E820h my only option? And is it reliable on older systems? Is there a efficent way to do this without BIOS services? The interrupt is a pain at times as some system returns reserved areas rather then whats available.
Re:Memory Area Detection
Hi,
Cheers,
Brendan
BIOS functions are your only reliable/practical option. If the computer is too old to support interrupt 15h eax=0E820h you can fall back on older functions (int 15 ax = 0xE881, int 15 ax = 0xE801, int 15 ah = 0xC7, int 15 ah = 0x88, etc) and then try CMOS locations (0x17/0x18, 0x30/0x31, 0x34/0x35).Ryu wrote:Hi, what are my options for detecting unreserved memory areas. Is interrupt 15h AX=0E820h my only option? And is it reliable on older systems?
Int 15h eax=0E820h should be reliable (but some systems have bugs that can be worked around - see Ralph Brown's Interrupt List), and should always return reserved areas and usable RAM areas. All you'd do is check the "type" field that is returned to see if it's RAM or not.Ryu wrote:Is there a efficent way to do this without BIOS services? The interrupt is a pain at times as some system returns reserved areas rather then whats available.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Memory Area Detection
Hmm I don't know if this is correct but Bochs gives me only whats unused. The service also does not return BIOS data area or the extended data area so I suppose that I would have to assume that those areas are reserved. But yes from a real system the interrupt returns both reserved and unused areas, and so its left me with an unease feeling. (Or this could be another of my stupid bugs)
Heres a picture, where the mapped areas were returned by the service and the last Unmapped part is done manually for kernel space. (This link is temperary)
http://69.194.132.189/boot.gif
Anyways thanks for the reply I'll check on the ralph's list about it.
Heres a picture, where the mapped areas were returned by the service and the last Unmapped part is done manually for kernel space. (This link is temperary)
http://69.194.132.189/boot.gif
Anyways thanks for the reply I'll check on the ralph's list about it.
Re:Memory Area Detection
Hi,
Qemu developers patched their version of the Bochs BIOS on the 3rd of May, but I don't think Bochs developers noticed.
If you boot from floppy and don't use much of the BIOS, you might be interested in using this BIOS with Bochs instead. It's "under development", but everything that has been implemented is far better than the normal Bochs BIOS, especially if you're trying to do hyper-threading/multi-core/multi-CPU or NUMA support (even if I do say so myself)... ::)
Cheers,
Brendan
This is a problem with the standard Bochs BIOS - it's "eax = 0xE820" function is wrong.Ryu wrote:Hmm I don't know if this is correct but Bochs gives me only whats unused. The service also does not return BIOS data area or the extended data area so I suppose that I would have to assume that those areas are reserved. But yes from a real system the interrupt returns both reserved and unused areas, and so its left me with an unease feeling. (Or this could be another of my stupid bugs)
Qemu developers patched their version of the Bochs BIOS on the 3rd of May, but I don't think Bochs developers noticed.
If you boot from floppy and don't use much of the BIOS, you might be interested in using this BIOS with Bochs instead. It's "under development", but everything that has been implemented is far better than the normal Bochs BIOS, especially if you're trying to do hyper-threading/multi-core/multi-CPU or NUMA support (even if I do say so myself)... ::)
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Memory Area Detection
Perhaps the FAQ page of How do I determine the amount of RAM is of help.
Every good solution is obvious once you've found it.
Re:Memory Area Detection
Greetings,
Brendan:
Ahh so its Bochs that screwed up. I've tried your BIOS out however have ran into problems with INT 15h EAX=E820h, and I've noticed a minor bug..
In the source .\common\int15.asm (line 421):
And what was disassembled by IDA:
As you probably already guessed, lea eax, [ebx+ebx-7E0Ch] is not intention. When you get this fixed up and reassembled I'll be using this over the default Bochs BIOS, thanks for sharing
Solar:
Aye yes the info helps, thanks for the reply.
Brendan:
Ahh so its Bochs that screwed up. I've tried your BIOS out however have ran into problems with INT 15h EAX=E820h, and I've noticed a minor bug..
In the source .\common\int15.asm (line 421):
Code: Select all
.sE820_generic:
push edx
lea eax,[.sE820_table+ebx*2]
inc ebx ;ebx = next continuation value
and eax,0xFFFF
call [cs:eax] ;Get the details for this entry
mov [es:di],edx ;Set base address of region (low dword)
mov dword [es:di+4],0 ;Set base address of region (high dword)
mov [es:di+8],ecx ;Set size of region (low dword)
mov dword [es:di+12],0 ;Set size of region (high dword)
mov [es:di+16],eax ;Set type of region
mov ecx,20 ;ecx = returned size
pop edx
pop ds
mov eax,edx
and word [bp+6],~FLAG_carry ;Clear the carry flag (on the stack)
pop bp
iret
Code: Select all
seg000:81AB loc_81AB:
seg000:81AB push edx
seg000:81AD lea eax, [ebx+ebx-7E0Ch]
seg000:81B6 inc ebx
seg000:81B8 and eax, 0FFFFh
seg000:81BE call word ptr cs:[eax]
seg000:81C2 mov es:[di], edx
seg000:81C6 mov dword ptr es:[di+4], 0
seg000:81CF mov es:[di+8], ecx
seg000:81D4 mov dword ptr es:[di+0Ch], 0
seg000:81DD mov es:[di+10h], eax
seg000:81E2 mov ecx, 14h
seg000:81E8 pop edx
seg000:81EA pop ds
seg000:81EB mov eax, edx
seg000:81EE and word ptr [bp+6], 0FFFEh
seg000:81F2 pop bp
seg000:81F3 iret
Solar:
Aye yes the info helps, thanks for the reply.
Re:Memory Area Detection
Hi,
The reason is that the source code mixes 32 bit assembly, unreal mode and real mode, and half of it (the POST code) operates at 0xFFFF0000 while the other half operates at 0x000F0000 (or 0xF000:0000).
The instruction itself is "lea eax, [ebx * 2 + 0xFFFF8140]", where "0xFFFF8140" is the 32 bit address of ".sE820_table" for the copy of the BIOS at 0xFFFF0000. This is because I need to use 32 bit addresses for the 32 bit code - for the 16 bit code doing something like "mov ax,.sE820_table" works perfectly because the upper bits are truncated (even though I'm using "org 0xFFFF0000").
What I really wanted to do here is "lea ax, [bx * 2 + .sE820_table]", but the CPU doesn't support this addressing mode for 16 bit instructions.
The next best option is "lea eax, [ebx*2 + (.sE820_table & 0xFFFF) ]", but NASM won't allow that - it can't do mathmatical operations on labels because it doesn't know the address that the label would end up at. Instead you get "error: `&' operator may only be applied to scalar values".
Therefore, to avoid the limitations of the CPU and the limitations of the assembler, I did it in 2 seperate instructions:
Another alternative would be to do it like this:
As long as those extra upper 16 bits are truncated somehow you end up with the correct value in EAX at the end. I have changed it to this second version though - it'd be easier to follow a disassembly that way....
The other alternative would be to assemble the 32 bit code and the 16 bit code seperately, with "org 0x0000" for the 16 bit code and "org 0xFFFF0000" for the 32 bit code. Unfortunately that creates a lot of problems elsewhere because it's impossible to use the addresses of labels defined in one binary from another binary.
I hope this makes sense...
Cheers,
Brendan
I know it looks unusual, but it actually is intentional...Ryu wrote:As you probably already guessed, lea eax, [ebx+ebx-7E0Ch] is not intention.
The reason is that the source code mixes 32 bit assembly, unreal mode and real mode, and half of it (the POST code) operates at 0xFFFF0000 while the other half operates at 0x000F0000 (or 0xF000:0000).
The instruction itself is "lea eax, [ebx * 2 + 0xFFFF8140]", where "0xFFFF8140" is the 32 bit address of ".sE820_table" for the copy of the BIOS at 0xFFFF0000. This is because I need to use 32 bit addresses for the 32 bit code - for the 16 bit code doing something like "mov ax,.sE820_table" works perfectly because the upper bits are truncated (even though I'm using "org 0xFFFF0000").
What I really wanted to do here is "lea ax, [bx * 2 + .sE820_table]", but the CPU doesn't support this addressing mode for 16 bit instructions.
The next best option is "lea eax, [ebx*2 + (.sE820_table & 0xFFFF) ]", but NASM won't allow that - it can't do mathmatical operations on labels because it doesn't know the address that the label would end up at. Instead you get "error: `&' operator may only be applied to scalar values".
Therefore, to avoid the limitations of the CPU and the limitations of the assembler, I did it in 2 seperate instructions:
Code: Select all
lea eax,[.sE820_table+ebx*2]
and eax,0xFFFF
Code: Select all
lea eax,[ebx*2]
add ax,.sE820_table
The other alternative would be to assemble the 32 bit code and the 16 bit code seperately, with "org 0x0000" for the 16 bit code and "org 0xFFFF0000" for the 32 bit code. Unfortunately that creates a lot of problems elsewhere because it's impossible to use the addresses of labels defined in one binary from another binary.
I hope this makes sense...
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Memory Area Detection
Oh so it works out.. (7E0Ch ^ 0FFFFh) + 1 = 81F4h. ??? Hmm if that is not the problem, I'm still left with a Bochs error:
00973049880i[BIOS ] Starting boot sector
00977297054i[CPU0 ] LOCK prefix unallowed (op1=0xf8, attr=0x0, mod=0x0, nnn=0)
00977297389i[BIOS ] Unimplemented BIOS function called (Int 0xFF, EAX=0x00000000)
00977297404i[CPU0 ] LOCK prefix unallowed (op1=0xf8, attr=0x0, mod=0x0, nnn=0)
Where the last contigiously was written in bochsout.txt and my bootloader never made pass the interrupt 15h. What was particular when I ran my investigation on the matter was, if I have set ecx=20 or higher the interrupt never returns and I end up with that output in Bochs, however a zero value in ECX returns and continues my execution. So.. I was really suspicious with that instruction. The simplified code I used was:
Any ideas why? Just a guess maybe using a 32bit offset in a 16bit enviroment have anything to do with it? -> call cs:[eax]. Unfortunitly I don't use Nasm so I don't get to play around with the source hehe.
00973049880i[BIOS ] Starting boot sector
00977297054i[CPU0 ] LOCK prefix unallowed (op1=0xf8, attr=0x0, mod=0x0, nnn=0)
00977297389i[BIOS ] Unimplemented BIOS function called (Int 0xFF, EAX=0x00000000)
00977297404i[CPU0 ] LOCK prefix unallowed (op1=0xf8, attr=0x0, mod=0x0, nnn=0)
Where the last contigiously was written in bochsout.txt and my bootloader never made pass the interrupt 15h. What was particular when I ran my investigation on the matter was, if I have set ecx=20 or higher the interrupt never returns and I end up with that output in Bochs, however a zero value in ECX returns and continues my execution. So.. I was really suspicious with that instruction. The simplified code I used was:
Code: Select all
???push ss
???pop??????es
???mov??????edi, 800h - 14h
???mov??????eax, 0E820h
???mov??????edx, "SMAP"
???xor??????ebx, ebx
???mov??????ecx, 14h??????; 20 bytes
???int??????15h????????????;BIOS INT 15h AX=0E820h
Re:Memory Area Detection
@brendan
Maybe you have a look at fasm. It has some features nasm doesn?t have (like mathematical operations on labels).
Maybe you have a look at fasm. It has some features nasm doesn?t have (like mathematical operations on labels).