Testing the memory map

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
boXd
Posts: 1
Joined: Thu Aug 30, 2012 12:21 pm

Testing the memory map

Post by boXd »

Hello m'dearies,

I'm building a personal bootloader because, well, because I think it's an interesting project. I'm currently working on getting a memory map from the BIOS, but since I'm still in real mode without a GDT, etc. I'm unsure whether my code worked. It doesn't produce any errors, and I *think* I set up any error-checking correctly, but I'm not quite sure. Is there any way to 'test' this memory map while still in my second-stage bootloader, or would it be more practical to keep going until I get to the kernel part, and then see if passing the table works?

My second question is about where I'm keeping the table and the number of entries in memory. Again, I *think* I've done this properly, but I am admittedly new at designing bootloaders (you have to start somewhere, of course), and the inability to check whether it's working doesn't exactly make things easier. Right now, I'm storing BP at the end of the loop at 0x0000:0x7e00, and I changed ES:DI to 0x0000:0x7e02. BP is 2 bytes long, so that shouldn't pose any problems when trying to pass it to the kernel later, right?

Basically, I'm not seeing anything unexpected happen in my bootloader, but then again I mostly learn by experimenting around, and there's very little indication whether you're doing the right thing(TM) or not when trying to code a bootloader. Any advice would be much appreciated. :)

For those who're interested, the code I'm using to map the memory is pretty much identical to the one found here, so don't expect to find many surprising elements. I posted it below for those who want to look it, just in case. (Don't mind the rambling comments. They're... Ah, well, it gives you some idea of how my mind works while I'm coding.)

Code: Select all

; Try to get a map of the available RAM by using BIOS interrupts. Joy of joys.
memMap:
	; First, we set up the registers. The idea is to store the memory map
	; at 0x7e00, so we set ES:DI to 0x0000:0x7e00. We also have to store
	; a signature, and a stupid value in EAX to get our interrupt to work.
	xor ax, ax
	mov es, ax
	mov bp, ax 
	mov di, 0x7e02
	xor ebx, ebx
	mov edx, 0x0534d4150
	mov eax, 0xe820
	mov [es:di + 20], dword 1
	mov ecx, 24
	int 0x15
	; Some mandatory tests to see if this particular interrupt is supported
	; and works as expected.
	jc .memMap_fail
	mov edx, 0x0534d4150
	cmp eax, edx
	jne .memMap_fail
	test ebx, ebx
	je .memMap_fail
	; Great, now let's jump to the bulk of the work.
	jmp .memMap_jump
; "There once was a loop-y named Ragnar the Red..."
.memMap_loop:
	mov eax, 0xe820
	mov [es:di + 20], dword 1
	mov ecx, 24
	int 0x15
	jc .memMap_end ; CF implies the end of the list has been reached.
	mov edx, 0x0534d4150
.memMap_jump:
	jcxz .memMap_skip
	cmp cl, 20
	jbe .memMap_notext
	test byte [es:di + 20], 1
	je .memMap_skip
.memMap_notext:
	mov ecx, [es:di + 8]
	or ecx, [es:di + 12]
	jz .memMap_skip
	inc bp
	add di, 24
.memMap_skip:
	test ebx, ebx
	jne .memMap_loop
; The end of the memory map procedures. All that's left to do is storing BP at the
; beginning of a free piece of memory, and - how odd! - we happen to have 2 more bytes
; of free RAM at 0x7e00+1. 
.memMap_end:
	mov ax, 0x7e00
	mov di, ax
	mov [es:di], bp
	clc
	mov si, memGoodMsg
	call showMsg
	ret
; Well, clearly *something* went wrong. I can't be bothered to use different error
; messages for all the different ways this may have gone wrong, given that I haven't
; had any errors with memory mapping so far. I might change this later if it turns out
; to become a problem.
.memMap_fail:
	mov si, memFailMsg
	call showMsg
	cli
	jmp $
Hm, it would be useful if we could use spoilers. Can we?
sounds
Member
Member
Posts: 112
Joined: Sat Feb 04, 2012 5:03 pm

Re: Testing the memory map

Post by sounds »

It looks like you've done some homework and understand some x86 assembly. Good.

A bootloader should load something. Write some code that will temporarily be that FOO (borrowing Brendan's term) and will dump out your memory map. Run it in QEMU and tell us what qemu command line you used.

We'll run QEMU too and see if we get the same memory map.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: Testing the memory map

Post by JamesM »

sounds wrote:It looks like you've done some homework and understand some x86 assembly. Good.

A bootloader should load something. Write some code that will temporarily be that FOO (borrowing Brendan's term) and will dump out your memory map. Run it in QEMU and tell us what qemu command line you used.

We'll run QEMU too and see if we get the same memory map.
Please try to answer the question instead of being condescending. Thanks.
halofreak1990
Member
Member
Posts: 41
Joined: Thu Aug 09, 2012 5:10 am

Re: Testing the memory map

Post by halofreak1990 »

I am curious as to why the value 0x0534d4150 is assigned to edx. Correct me if I'm wrong, but I'm counting 36 bits here, instead of 32.
Now, with edx being 32 bits, the top 4 are simply being cut off, but it might be confusing to other people.

and then there is this line:

Code: Select all

cmp		cl, 20					; got a 24 byte ACPI 3.X response?
I'm seeing a conflict here. the comment says 24, but the code only checks for 20 bytes.
Now, since an ACPI 3.X entry is being forced, I can imagine not checking for the last DWORD, but it's still confusing.

And finally, how does the code handle truly valid ACPI 3.X entries?
<PixelToast> but i cant mouse

Porting is good if you want to port, not if you want maximum quality. -- sortie
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Testing the memory map

Post by egos »

boXd wrote:My second question is about where I'm keeping the table and the number of entries in memory.
I use stack and (e)sp:

Code: Select all

        xor ebx,ebx
        ...
        label .HighMemorySize dword at .BaseMemorySizeKB-4
        push ebx ; initialize variable .HighMemorySize
.next:
        ...
        push eax
        push ebp
        sub eax,ebp
        add [.HighMemorySize],eax
        cmp sp,.HighMemorySize-8*MAXMEMREGIONS ; 8 is entry size
        jbe @f
.loop:
        and ebx,ebx
        jnz .next
@@:

Code: Select all

.next:
        pop ebp
        pop eax
        ...
        cmp esp,Startup.HighMemorySize
        jb .next
halofreak1990 wrote:I am curious as to why the value 0x0534d4150 is assigned to edx. Correct me if I'm wrong, but I'm counting 36 bits here, instead of 32.
0x0534d4150 is still 32-bit because high significant digit is 0.
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Testing the memory map

Post by DavidCooper »

boXd wrote:; The end of the memory map procedures. All that's left to do is storing BP at the
; beginning of a free piece of memory, and - how odd! - we happen to have 2 more bytes
; of free RAM at 0x7e00+1.
I don't understand how you know there's something odd happening there. What evidence are you going by?
; Well, clearly *something* went wrong.
My mind must have gone - I can't see anything clear about it.... Or are these just some of the rambling comments we're supposed to ignore? If so, then it isn't clear you have any problem at all. What you need to do is find a way to view the table to see if it looks properly formed. If that can be done by some Qemu trick then do it that way, but if not, start work on your kernel now and begin it with some simple routines to read memory and display the content as hex so that you can see what you're doing. If all turns out to be fine, keep those routines to aid future debugging and start building the real kernel.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
halofreak1990
Member
Member
Posts: 41
Joined: Thu Aug 09, 2012 5:10 am

Re: Testing the memory map

Post by halofreak1990 »

boXd wrote:Right now, I'm storing BP at the end of the loop at 0x0000:0x7e00, and I changed ES:DI to 0x0000:0x7e02. BP is 2 bytes long, so that shouldn't pose any problems when trying to pass it to the kernel later, right?
Not if you keep track of its location, no. But the way you have it now, it's fairly easy to forget where it is, and run the risk of overwriting it.
It might be more helpful--especially if you intend to make a multiboot compatible kernel--to place the value of BP in the multiboot structure.

In my bootloader, I store the value of BP in the mmap_length field of the multiboot structure, which means I don't have to keep track of it afterwards.
<PixelToast> but i cant mouse

Porting is good if you want to port, not if you want maximum quality. -- sortie
Post Reply