Page 1 of 1

Reading the memory map from multiboot

Posted: Thu Sep 29, 2005 4:41 pm
by yukito
Hi!

For starters, I _DID_ read the FAQ on this, so don't start reacting with your guns blazing ;)

I don't see why the code in the faq is supposed to work: it uses int's where they say that there are 4 bytes per field, so a long should be used right? I'm probably just confused so set me straight if I'm wrong.

Other than that, they also add sizeof(unsigned int) to the size of the memory map entry, why is that? To get the base_addr_low at offset 0? won't that mess up the structure and put the base_addr_low in the size field?

The memory_map structure from multiboot.h looks correct though, so why can't I use that one?

However, using:

Code: Select all

      struct memory_map* mmap = (struct memory_map*)mbd->mmap_addr;
      while(mmap < (struct memory_map*) mbd->mmap_addr + mbd->mmap_length) {
         puts("Base address: ");
         puts_longhex(mmap->base_addr_low);
         puts(" - Size: ");
         puts_longdec(mmap->length_low);
         puts("\n");
         mmap = mmap +  mmap->size;
      }
Reads the first entry correctly, but the rest is messed up. What's wrong?

And why are we using 2 longs per address? 64bit address space, for non 32bit systems compatibility? Can I just use the lower 32bits on a 32bit x86?

This is just what pops into mind at 0:44, maybe it's just me being to tired to write an OS right now, but it just looks plain wrong :(

Re:Reading the memory map from multiboot

Posted: Thu Sep 29, 2005 5:43 pm
by Colonel Kernel
yukito wrote:I don't see why the code in the faq is supposed to work: it uses int's where they say that there are 4 bytes per field, so a long should be used right?
When compiling for a 32-bit target, int and long are the same size (i.e. -- 4 bytes). In my code, I use uint32_t (defined in stdint.h) to make things really clear. :)
And why are we using 2 longs per address? 64bit address space, for non 32bit systems compatibility? Can I just use the lower 32bits on a 32bit x86?
Newer x86 processors support Physical Address Space extensions (PAE), which allows for 36-bit physical addresses. x64 processors use PAE for even larger physical address spaces (48-bit IIRC... not sure). If you use only 32 bits and someone's machine has more than 4 GB RAM installed, your code will end up doing weird and unexpected things.

Don't have time to look into the rest of your questions at the moment...

Re:Reading the memory map from multiboot

Posted: Thu Sep 29, 2005 6:06 pm
by AR
The field telling the size of the struct is not accounted for in itself (ie. it says the size is 20 but you actually need to cycle 24bytes [+4 for the "size" field itself which is "sizeof(unsigned int)"]).

The code in the Wiki is broken actually, I fixed it now. The reason it didn't work is that when you do this:

Code: Select all

mmap = mmap +  mmap->size;
The compiler actually sees this:

Code: Select all

mmap = (memory_map_t*) ( (unsigned int)mmap + ( mmap->size * sizeof(memory_map_t) ) )
The correct increment code looks like:

Code: Select all

mmap = (memory_map_t*) ( (unsigned int)mmap + mmap->size + sizeof(unsigned int) );

Re:Reading the memory map from multiboot

Posted: Thu Sep 29, 2005 11:35 pm
by yukito
Why does it need (unsigned int)mmap if long and int are both 32bit anyway? Or is there another difference? Thanks for your help!

Re:Reading the memory map from multiboot

Posted: Fri Sep 30, 2005 12:12 am
by AR
The cast to unsigned int is to convert the pointer to a number so that it can be manipulated as such.

long, int, unsigned and signed all map to 4 byte numbers. A complete list for the x86 is:
char - 1 byte
short - 2 bytes
int - 4 bytes
long - 4 bytes
long long - 8 bytes
A pointer is equivalent to "unsigned long int" which is still 4 bytes anyway. The reason for the use of "sizeof(unsigned int)" instead of just "+ 4" is because when you come back to the code after not having used it for a while, you can see exactly why 4 bytes are being added rather than having to work out what the hell "+ 4" is about.

Re:Reading the memory map from multiboot

Posted: Fri Sep 30, 2005 12:27 am
by Solar
Note that any assumptions about int and long being the same size are valid on the vast majority of platforms, but by no means guaranteed in any way.

Likewise, casting a pointer to some integer and assuming it will fit is compiler-dependent; more exactly, compiler configuration dependent.

If you want to play it safe, use C99 and <stdint.h> (uint32_t, intptr_t etc.)

Re:Reading the memory map from multiboot

Posted: Fri Sep 30, 2005 5:12 pm
by yukito
Yes sorry about that, my C++ book states that an int is 4 bytes, by which they probably meant a short int.

Also, my code outputs the following:

Base address: 0x3064662820202020 - Size: 1701511209 - Type: 6B2F2020

What does this mean/do? The rest of the output is just plain avaible RAM.

Re:Reading the memory map from multiboot

Posted: Fri Sep 30, 2005 7:50 pm
by AR
That looks like you've misread it, AFAIK Hardware won't map itself in PAE memory. If that's from Bochs can you show the whole list and the updated code?

Re:Reading the memory map from multiboot

Posted: Sat Oct 01, 2005 12:01 am
by Brendan
Hi,
yukito wrote: Also, my code outputs the following:

Base address: 0x3064662820202020 - Size: 1701511209 - Type: 6B2F2020
If you convert it all to ASCII, the base address is " (fd0", the size is ")" then a zero then "ke", and the type is " /k". Every byte is valid ASCII.

I think your either reading from the wrong place or the correct data has been overwritten.


Cheers,

Brendan