116 lines
3.3 KiB
C
116 lines
3.3 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <multiboot.h>
|
|
#include <memory.h>
|
|
#include <debug.h>
|
|
|
|
// 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;
|
|
} |