Page 1 of 1
Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 6:30 am
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?
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 6:47 am
by thomtl
Are you using Paging?
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 6:48 am
by marks
thomtl wrote:Are you using Paging?
Yes, I am. I've enabled paging in the bootloader to load the kernel at 0xC0000000
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 7:03 am
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.
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 7:30 am
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.
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 2:14 pm
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
.Thanks all.
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 3:51 pm
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.
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 10:58 pm
by marks
I guess 32-bit considering that the os is 32-bit but I understood, I'll try. Thank you
Re: Why GRUB memory map doesn't want to be used?
Posted: Thu Oct 18, 2018 11:58 pm
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.
Re: Why GRUB memory map doesn't want to be used?
Posted: Fri Oct 19, 2018 4:18 am
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.
Re: Why GRUB memory map doesn't want to be used?
Posted: Fri Oct 19, 2018 4:36 am
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.