int 15h E820h problems

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

int 15h E820h problems

Post 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
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: int 15h E820h problems

Post 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.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: int 15h E820h problems

Post by egos »

Try this:

Code: Select all

  mov ecx, 20
  int 15h
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
If you have seen bad English in my words, tell me what's wrong, please.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: int 15h E820h problems

Post 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.
Richy
Member
Member
Posts: 41
Joined: Wed Nov 19, 2008 10:03 am

Re: int 15h E820h problems

Post by Richy »

egos wrote:Try this:

Code: Select all

  mov ecx, 20
  int 15h
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?
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: int 15h E820h problems

Post by quok »

egos wrote:Try this:

Code: Select all

  mov ecx, 20
  int 15h
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.
Post Reply