Why GRUB memory map doesn't want to be used?

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
marks
Posts: 5
Joined: Thu Oct 18, 2018 6:19 am

Why GRUB memory map doesn't want to be used?

Post by marks »

I'm currently receiving the multiboot_info_t *mbd, but when I use the structure as

Code: Select all

multiboot_memory_map_t* mmap = mbd->mmap_addr;
or in the while as

Code: Select all

while (mmap <  mbd->mmap_addr + mbd->mmap_length) {
        ...        
        mmap = (multiboot_memory_map_t *)(mmap + mmap->size + sizeof(mmap->size));
}
Qemu just restart.
The magic number is passed right and mbd is 0x10000 (64kb). I can't understand why. Can you give me some help?
User avatar
thomtl
Member
Member
Posts: 66
Joined: Mon Sep 03, 2018 2:25 am

Re: Why GRUB memory map doesn't want to be used?

Post by thomtl »

Are you using Paging?
marks
Posts: 5
Joined: Thu Oct 18, 2018 6:19 am

Re: Why GRUB memory map doesn't want to be used?

Post by marks »

thomtl wrote:Are you using Paging?
Yes, I am. I've enabled paging in the bootloader to load the kernel at 0xC0000000
User avatar
thomtl
Member
Member
Posts: 66
Joined: Mon Sep 03, 2018 2:25 am

Re: Why GRUB memory map doesn't want to be used?

Post by thomtl »

You are not using Identity mapping so you can't use physical addresses, you need the Memory mapped in somewhere, Luckily you probably have it mapped, but in the higher half. so you need to increase that pointer with 0xC0000000 but just += ing it won't working since it is a pointer.
klange
Member
Member
Posts: 679
Joined: Wed Mar 30, 2011 12:31 am
Libera.chat IRC: klange
Discord: klange

Re: Why GRUB memory map doesn't want to be used?

Post by klange »

marks wrote:

Code: Select all

multiboot_memory_map_t* mmap = mbd->mmap_addr;
...
        mmap = (multiboot_memory_map_t *)(mmap + mmap->size + sizeof(mmap->size));
You are falling victim to pointer arithmetic here. You are trying to add mmap->size + sizeof(mmap->size) to mmap, which as a pointer to multiboot_memory_map_t adds sizeof(multiboot_memory_map_t) * (mmap->size * sizeof(mmap->size)) to its integral value.
marks
Posts: 5
Joined: Thu Oct 18, 2018 6:19 am

Re: Why GRUB memory map doesn't want to be used?

Post by marks »

I've added the offset and now it should work, but when I print the structure it comes with:

mmap->size = 20
mmap->baseAddrLow = 3221225472
mmap->baseAddrHigh = 3221225472
mmap->lengthLow = 654336
mmap->lengthHigh = 0
mmap->type = 1

Not usable RAM.
Not usable RAM.

mmap->size = 20
mmap->baseAddrLow = 3222274048
mmap->baseAddrHigh = 3221225472
mmap->lengthLow = 133038080
mmap->lengthHigh = 0
mmap->type = 1

Not usable RAM.
Not usable RAM.

"Not usable RAM." are the areas with type != 1. I don't think this is an healthy multiboot structure mostly because of the lengthHigh property.
What could I get wrong?
This is my multibootMemoryMap_t:

Code: Select all

typedef struct multiboot_memory_map {
    unsigned int size;
    unsigned int baseAddrLow, baseAddrHigh;
    unsigned int lengthLow, lengthHigh;
    unsigned int type;
} multibootMemoryMap_t;
and this is how i'm "parsing" it:

Code: Select all

void setupPaging(multiboot_info_t* mbd, unsigned int magic) {
    // Address of the memory map    
    multiboot_info_t* mbt = (unsigned int)mbd + 0xC0000000;
    multibootMemoryMap_t* mmap = (unsigned int)mbt->mmap_addr + 0xC0000000;
    
    while (mmap < (((mbt->mmap_addr) + 0xC0000000) + mbt->mmap_length)) {
        if(mmap->type == 1) {
            printf_str("mmap->size = "); printf_int(mmap->size); printf_str("\n");
            
            printf_str("mmap->baseAddrLow = "); printf_int((mmap->baseAddrLow) + 0xC0000000); printf_str("\n");
            printf_str("mmap->baseAddrHigh = "); printf_int((mmap->baseAddrHigh) + 0xC0000000); printf_str("\n");
            
            printf_str("mmap->lengthLow = "); printf_int(mmap->lengthLow); printf_str("\n");
            printf_str("mmap->lengthHigh = "); printf_int(mmap->lengthHigh); printf_str("\n");
            
            printf_str("mmap->type = "); printf_int(mmap->type); printf_str("\n\n\n");
        } else
            printf_str("Not usable RAM.\n");

        mmap = (multibootMemoryMap_t *) ((unsigned int)mmap + mmap->size + sizeof(mmap->size));
    }
}
I know my printf are raw so please don't look at them :D .Thanks all.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Why GRUB memory map doesn't want to be used?

Post by MichaelPetch »

You should not be adding 0xC0000000 to baseAddrLow or baseAddrHigh. If you stop doing that and convert the values to hex things look right. unsigned int baseAddrLow, baseAddrHigh and unsigned int lengthLow, lengthHigh; both form 64-bit values. Base Address is a physical address to the start of the memory region being described and length is the 64-bit value representing the length of the memory region.
marks
Posts: 5
Joined: Thu Oct 18, 2018 6:19 am

Re: Why GRUB memory map doesn't want to be used?

Post by marks »

I guess 32-bit considering that the os is 32-bit but I understood, I'll try. Thank you
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Why GRUB memory map doesn't want to be used?

Post by MichaelPetch »

It is possible for a 32-bit system to have more than 4GB of physical memory. For example a 32-bit processor that supported PAE (physical address extensions) could support up to 64GB of physical memory (paging allowed you to access the memory above 4GB). If you are on a 64-bit system the amount of memory may be significantly more. Thus, the the memory map that is returned by GRUB may report memory above 4GB, but that depends on the environment. Your 32-bit OS may only be able to access part of it.
marks
Posts: 5
Joined: Thu Oct 18, 2018 6:19 am

Re: Why GRUB memory map doesn't want to be used?

Post by marks »

So this looks sane?

mmap->size = 20
mmap->baseAddrLow = 0
mmap->baseAddrHigh = 0
mmap->lengthLow = 654336
mmap->lengthHigh = 0
mmap->type = 1

Not usable RAM.
Not usable RAM.

mmap->size = 20
mmap->baseAddrLow = 1048576
mmap->baseAddrHigh = 0
mmap->lengthLow = 133038080
mmap->lengthHigh = 0
mmap->type = 1

Not usable RAM.
Not usable RAM.

I don’t think so. The type is either 1 or 2, no other type is specified. Another problem could be that mmap->baseAddrHigh and mmap->lengthHigh are never used.
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Why GRUB memory map doesn't want to be used?

Post by MichaelPetch »

It looks sane to me. If you convert the values to hex it is a lot easier to see.

mmap->lengthLow = 654336
mmap->lengthHigh = 0
mmap->baseAddrLow = 0
mmap->baseAddrHigh = 0

BaseAddr in hex as a 64-bit value is 0x0000000000000000
Length in hex as a 64-bit value is 0x000000000009FC00

This makes sense since memory address 0x0 to 0x9FC00 represents the usable memory under 1MB. Video memory and BIOS starts from 0xA0000 to 0x100000. The area between 0x9FC00 and 0xA0000 is unusable because it is the Extended BIOS Data Area. That looks reasonable.

mmap->baseAddrLow = 1048576
mmap->baseAddrHigh = 0
mmap->lengthLow = 133038080
mmap->lengthHigh = 0

BaseAddr in hex as a 64-bit value is 0x0000000000100000
Length in hex as a 64-bit value is 0x0000000007EE0000

This means usable memory between 0x100000 and 7FE0000 (0x7EE0000+0x100000)

This looks reasonable for a system that probably has 128MB ram.

The multiboot spec says this about the memory map entries:
+-------------------+
-4 | size |
+-------------------+
0 | base_addr |
8 | length |
16 | type |
+-------------------+

where ‘size’ is the size of the associated structure in bytes, which can be greater than the minimum of 20 bytes. ‘base_addr’ is the starting address. ‘length’ is the size of the memory region in bytes. ‘type’ is the variety of address range represented, where a value of 1 indicates available ram, value of 3 indicates usable memory holding ACPI information, value of 4 indicates reserved memory which needs to be preserved on hibernation, value of 5 indicates a memory which is occupied by defective RAM modules and all other values currently indicated a reserved area.
Post Reply