Search code examples
memorykernelosdevgrubgrub2

GRUB memory map gives me weird values


I am trying to use grub in order to get the memory map, instead of going through the bios route. The problem is that grub seems to be giving me very weird values for some reason. Can anyone help with this?

Relevant code:

This is how I parse the mmap

void mm_init(mmap_entry_t *mmap_addr, uint32_t length)
{
    mmap = mmap_addr;
    /* Loop through mmap */
    printk("-- Scanning memory map --");
    for (size_t i = 0; mmap < (mmap_addr + length); i++) {
        /* RAM is available! */
        if (mmap->type == 1) {
            uint64_t starting_addr = (((uint64_t) mmap->base_addr_high) << 32) | ((uint64_t) mmap->base_addr_low);
            uint64_t length = (((uint64_t) mmap->length_high) << 32) | ((uint64_t) mmap->length_low);
            printk("Found segment starting from 0x%x, with a length of %i", starting_addr, length);
        }
        /* Next entry */
        mmap = (mmap_entry_t *) ((uint32_t) mmap + mmap->size + sizeof(mmap->size));
    }
}

This is my mmap_entry_t struct (not the one in multiboot.h):

struct mmap_entry {
    uint32_t size;
    uint32_t base_addr_low, base_addr_high;
    uint32_t length_low, length_high;
    uint8_t type;
}  __attribute__((packed));

typedef struct mmap_entry mmap_entry_t;

And this is how I call mm_init()

/* Kernel main function */
void kmain(multiboot_info_t *info)
{
    /* Check if grub can give us a memory map */
    /* TODO: Detect manually */
    if (!(info->flags & (1<<6))) {
        panic("couldn't get memory map!");
    }

    /* Init mm */
    mm_init((mmap_entry_t *) info->mmap_addr, info->mmap_length);

    for(;;);
}

This is the output I get on qemu:

-- Scanning memory map --
Found segment starting from 0x0, with a length of 0
Found segment starting from 0x100000, with a length of 0

And yes, I am pushing eax and ebx before calling kmain. Any ideas on what is going wrong here?


Solution

  • It turns out that the bit masking stuff was the problem. If we drop that, we can still have 32-bit addresses and the memory map works just fine.