Page 1 of 1
int 15h E820h problems
Posted: Mon Feb 16, 2009 1:54 pm
by Richy
So I've tried to create a memory map using a function similar to
the one in the wiki. The map is fine. The problem is that, while it correctly lists seven regions, the value in the bp pointer is of several thousands. I don't get it. It's incremented in the code at the same place where we move the di pointer, and that one is ok... What's going on here?
Code: Select all
GetMemoryMap:
pushad
xor ebx, ebx
xor bp, bp ; number of entries stored here
mov edx, 'PAMS' ; 'SMAP'
mov eax, 0xe820
mov ecx, 24 ; memory map entry struct is 24 bytes
int 0x15 ; get first entry
jc .error
cmp eax, 'PAMS' ; bios returns SMAP in eax
jne .error
test ebx, ebx ; if ebx=0 then list is one entry long; bail out
je .error
jmp .start
.next_entry:
mov edx, 'PAMS' ; some bios's trash this register
mov ecx, 24 ; entry is 24 bytes
mov eax, 0xe820
int 0x15 ; get next entry
.start:
jcxz .skip_entry ; if actual returned bytes is 0, skip entry
.notext:
mov ecx, [es:di + MemoryMapEntry.length] ; get length (low dword)
test ecx, ecx ; if length is 0 skip it
jne short .good_entry
mov ecx, [es:di + MemoryMapEntry.length + 4]; get length (upper dword)
jecxz .skip_entry ; if length is 0 skip it
.good_entry:
inc bp ; increment entry count
add di, 24 ; point di to next entry in buffer
.skip_entry:
cmp ebx, 0 ; if ebx return is 0, list is done
jne .next_entry ; get next entry
jmp .done
.error:
stc
.done:
popad
ret
Re: int 15h E820h problems
Posted: Mon Feb 16, 2009 11:06 pm
by bewing
The code looks good. Are you trying to run this in an emulator, or on real hardware? Do you have singlestep debugging capability?
How are you checking the "final" value of bp? You do not show that you are saving the value, or printing it from this function.
If you are trying to check it outside this function, the fact that you did the PUSHA/POPA will trash bp. The only other possibilities are that bp is getting trashed by the E820 function, or that you are getting thousands of "length = 0" entries before ebx returns as 0.
Re: int 15h E820h problems
Posted: Tue Feb 17, 2009 1:46 am
by egos
Try this:
And use checking code every time when calling int 15h:
Code: Select all
jc .error
cmp eax, "PAMS"
jne .error
cmp ecx, 20
jne .error
Re: int 15h E820h problems
Posted: Tue Feb 17, 2009 10:02 am
by Richy
bewing wrote:The code looks good. Are you trying to run this in an emulator, or on real hardware? Do you have singlestep debugging capability?
How are you checking the "final" value of bp? You do not show that you are saving the value, or printing it from this function.
If you are trying to check it outside this function, the fact that you did the PUSHA/POPA will trash bp. The only other possibilities are that bp is getting trashed by the E820 function, or that you are getting thousands of "length = 0" entries before ebx returns as 0.
I'm running it on a Microsoft Virtual PC. No debugging
In fact, I've tried checking the value of BP multiple ways. The short answer is, I'm copying it into the bootinfo structure and passing it to the kernel, which then displays it:
Code: Select all
mov word [boot_info+multiboot_info.mmap_length], bp
I've tried copying it after exiting the function, and I've tried copying it inside the function, as the first line of the ".done:" section before "popad". I've also tried skipping BP entirely and incrementing [boot_info+multiboot_info.mmap_length] directly. In all cases, I got results in the thousands.
I then figured that maybe BP was ok, but getting trashed when being passed to the kernel. So I added a simple display routine: I copied the value of BP in CX, and looped a single-character display with INT 10h. It displayed thousands of characters. So the value is being passed correctly to the kernel, it's being computed incorrectly by the function.
Re: int 15h E820h problems
Posted: Tue Feb 17, 2009 10:04 am
by Richy
egos wrote:Try this:
And use checking code every time when calling int 15h:
Code: Select all
jc .error
cmp eax, "PAMS"
jne .error
cmp ecx, 20
jne .error
20 byte entries instead of 24? Why?
Re: int 15h E820h problems
Posted: Tue Feb 17, 2009 10:28 am
by quok
egos wrote:Try this:
And use checking code every time when calling int 15h:
Code: Select all
jc .error
cmp eax, "PAMS"
jne .error
cmp ecx, 20
jne .error
ACPI 3.0 extends the structure that the E820 function returns from 20 to 24 bytes. ACPI 3.0, and previous versions, all say that if the size of the buffer passed to E820 is greater than the amount supported by E820, then E820 will ignore the extra bytes. This way, on machines that support ACPI 3.0, the same code will work, and you'll get the extra information provided. On ACPI 2.0 machines, that extra information will be empty (provided you clear the buffer before you pass it in). So checking to make sure that E820 returned the same amount of bytes you asked for isn't a good idea, unless you have separate E820 functions for each version of the E820 function as defined in the ACPI specifications.
Regardless, if you are passing in a 24 byte structure, you must always increment the pointer to the buffer/structure by 24 bytes even if E820 only supports 20 bytes. Or you could do like I do, and use the same buffer for each call to E820. After the call, I translate the E820 map into something of my own format, so the kernel's memory map will have the same format on any architecture I port to.