#include #include #include #include #include #include // https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html struct taglist { uint32_t total_size; uint32_t reserved; }__attribute__((packed)); struct tag { uint32_t type; uint32_t size; uint8_t data[]; }__attribute__((packed)); struct mmap_entry { uint64_t base; uint64_t len; uint32_t type; uint32_t reserved; }__attribute__((packed)); struct mmap { uint32_t entry_size; uint32_t entry_version; struct mmap_entry entries[]; }__attribute__((packed)); static int parse_multiboot2(struct taglist *tags) { struct mmap *mmap; struct tag *tag = incptr(tags, sizeof(struct taglist)); kernel_boot_data.mboot_tags = tag; kernel_boot_data.tags_length = tags->total_size; while(tag->type) { switch(tag->type) { case MBOOT2_TAG_BOOTLOADER: kernel_boot_data.bootloader = (char *)tag->data; break; case MBOOT2_TAG_CMDLINE: kernel_boot_data.commandline = (char *)tag->data; break; case MBOOT2_TAG_MMAP: mmap = kernel_boot_data.mmap = (void *)tag->data; kernel_boot_data.mmap_len = (tag->size - 8)/mmap->entry_size; kernel_boot_data.mmap_size = (tag->size - 8); break; case MBOOT2_TAG_FBINFO: kernel_boot_data.fbinfo = (void *)tag->data; break; } // Tags are 8 byte alligned, so make sure we look for the next one in the right place int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0); tag = incptr(tag, padded_size); } return 0; } int multiboot_init(uint64_t magic, void *mboot_info) { if(magic == MBOOT2_REPLY) { kernel_boot_data.multiboot_version = 2; parse_multiboot2(mboot_info); } else return 1; return 0; } int multiboot_get_memory_area(size_t index, uintptr_t *start, uintptr_t *end, uint32_t *type) { if(index >= kernel_boot_data.mmap_len) return 1; struct mmap *mmap = kernel_boot_data.mmap; struct mmap_entry *entry = mmap->entries; entry = incptr(entry, index*mmap->entry_size); *start = entry->base; *end = entry->base + entry->len; *type = entry->type; return 0; } int multiboot_page_used(uintptr_t page) { #define within_page(st, l) (((uintptr_t)st + l) > page && (uintptr_t)st < (page + PAGE_SIZE)) size_t fb_size = 0; uintptr_t fb_start = 0; if(kernel_boot_data.fbinfo) { fb_start = kernel_boot_data.fbinfo->framebuffer_addr; fb_size = kernel_boot_data.fbinfo->framebuffer_pitch*(kernel_boot_data.fbinfo->framebuffer_height + 1); } if( within_page(kernel_boot_data.mboot_tags, kernel_boot_data.tags_length) || within_page(kernel_boot_data.bootloader, strlen(kernel_boot_data.bootloader)) || within_page(kernel_boot_data.commandline, strlen(kernel_boot_data.commandline)) || within_page(kernel_boot_data.mmap, kernel_boot_data.mmap_size) || within_page(fb_start, fb_size) || 0) { debug("Page %x used\n", page); return 1; } return 0; }