OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 20, 2021 6:04 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Parsing multiboot memory map.
PostPosted: Tue Apr 06, 2021 11:35 am 
Offline
Member
Member

Joined: Sun May 24, 2020 9:11 am
Posts: 42
Location: /dev/null
According to documentation memory map entry looks like this:
Code:
        +-------------------+
-4      | size              |
        +-------------------+
0       | base_addr         |
8       | length            |
16      | type              |
        +-------------------+


It only specifies four values for type:
Code:
..., 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.


In qemu, however, this field has different values, for example 20. Anyone know what this means?


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Tue Apr 06, 2021 12:39 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 670
In the case of Grub, the values for type match the ones from the E820 memory map. This is likely true here is well.

Unfortunately I cannot seem to find what memory type 20 is. Linux doesn't seem to know (or care) either:

https://elixir.bootlin.com/linux/latest ... 20/types.h

It could have something to do with SMBIOS:

https://seabios.seabios.narkive.com/KlM ... es-in-qemu

Here it says it iss indeed something to do with SMBIOS:

Quote:
/* SMBIOS type 20 - Memory Device Mapped Address */

https://android.googlesource.com/platfo ... 4dc308a08/

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Tue Apr 06, 2021 4:26 pm 
Offline
Member
Member
User avatar

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 656
How are you parsing your memory map? If you are not parsing it right, you might be getting invalid results.

_________________
Currently working on the Nexware project, an attempt to make a less bloated version of GNU. All repos for it can be found at https://github.com/Nexware-Project.


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Wed Apr 07, 2021 1:04 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 937
For reference (and because that offset of -4 threw me off), this is my code for that. Hope it helps:
Code:
struct mbinfo {
    uint32_t flags,
             mem_lower,
             mem_upper,
             boot_device,
             cmdline,
             mods_count,
             mods_addr,
             syms[4],
             mmap_length,
             mmap_addr,
             drives_length,
             drives_addr,
             config_table,
             bootloader_name,
             apm_table,
             vbe_control_info,
             vbe_mode_info;
    uint16_t vbe_mode,
             vbe_interface_seg,
             vbe_interface_off,
             vbe_interface_len;
    uint64_t framebuffer_addr;
    uint32_t framebuffer_pitch,
             framebuffer_width,
             framebuffer_height;
    uint8_t  framebuffer_bpp,
             framebuffer_type,
             color_info[6];

};

struct mbmmap {
    uint32_t size;
    uint32_t addr[2], len[2];
    uint8_t type;
};

static void print_mem_info(unsigned len_mmap, const struct mbmmap *mmap, uint64_t *maxram)
{
    const unsigned char *const start = (void*)mmap;
    uint64_t mr = 0;
    while ((const unsigned char*)mmap - start < len_mmap)
    {
        uint64_t addr, len;
        addr = (uint64_t)mmap->addr[1] << 32 | mmap->addr[0];
        len = (uint64_t)mmap->len[1] << 32 | mmap->len[0];
        if (mmap->type == 1 && addr + len > mr)
            mr = addr + len;
        dbg_printf("%8X-%8X type %d\n", addr, addr + len, mmap->type);
        if (addr < 0x100000000)
        {
            if (addr + len > 0x100000000)
                len = 0x100000000 - addr;

            if (mmap->type == 1)
                add_avail_range(addr, len);
            else
                add_reserved_range(addr, len);
        }

        mmap = (const void*)((const unsigned char*)mmap + mmap->size + 4);
    }
    *maxram = mr;
}

void mbmain(uint32_t mbmagic, const struct mbinfo *bootinfo)
{
    [...]
        if (bootinfo->flags & 64)
            print_mem_info(bootinfo->mmap_length, (const void*)bootinfo->mmap_addr, &maxram);
}
So the "mmap_addr" in the multiboot info points immediately to a length. And afterwards all memory maps are offset by a further four bytes. And since now everything is misaligned, I have to break the 64-bit members down into two 32-bit members, else the compiler would insert padding. Yes, I am aware of __attribute__((packed)) and I choose not to use such a crutch. And so far it is working out.

_________________
Thou hast outraged, not insulted me, sir; but for that I ask thee not to beware of Starbuck; thou wouldst but laugh; but let Ahab beware of Ahab; beware of thyself, old man.


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Sun Apr 18, 2021 5:50 am 
Offline
Member
Member

Joined: Sun May 24, 2020 9:11 am
Posts: 42
Location: /dev/null
What is the purpose of GRUB's map?

It for example lists following regions as available in qemu:
Code:
0x0 - 0x9fc00
0x100000 - 0x7fe0000
0x0 - 0x1b00000000


Of course, this list makes no sense if its entries are not disjoint.
Moreover, in qemu's emulated memory, definitely, there is not address 0x1b000000000000. I don't even have that much memory in my PC :).

So what's the matter?
Are those these BIOS errors that bootboot fixes?


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Sun Apr 18, 2021 8:10 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 937
antoni wrote:
Moreover, in qemu's emulated memory, definitely, there is not address 0x1b000000000000. I don't even have that much memory in my PC :).
That's a hint that you are not parsing the entries correctly. Which is curious, because the first two look alright. But they make no sense without the actual memory type. I figured out the format of the region by hexdumping all of it; maybe that helps you out.

In general, there are no guarantees about the memory map. You might have multiple entries for the same address, they might not be sorted and you must deal with that. In general, assume the worst. If the same address is given as both RAM and something else, assume it is something else.

_________________
Thou hast outraged, not insulted me, sir; but for that I ask thee not to beware of Starbuck; thou wouldst but laugh; but let Ahab beware of Ahab; beware of thyself, old man.


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Sun Apr 18, 2021 8:22 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4165
Location: Chichester, UK
antoni wrote:
What is the purpose of GRUB's map?
So what's the matter?

If you are using the default amount of RAM in QEMU, the highest address will be 0x8000000. Which is suspiciously close to the second range you list (allowing for the fact that some of that address space is not useable). I'd guess that your third range is reading rubbish from beyond the end of the GRUM memory map.

It is my experience that the GRUB memory map reports the correct ranges in qemu.


Top
 Profile  
 
 Post subject: Re: Parsing multiboot memory map.
PostPosted: Sun Apr 18, 2021 9:39 am 
Offline
Member
Member

Joined: Sun May 24, 2020 9:11 am
Posts: 42
Location: /dev/null
You're right,
I miscalculated length of the array because I thought one variable is (uint8_t*) but it was pointer to larger type. In correct array there are only two entries.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group