Read memory map tags from multiboot

This commit is contained in:
Thomas Lovén 2017-12-19 22:51:11 +01:00
parent 0b3648de7c
commit 80cc165957
4 changed files with 113 additions and 14 deletions

View File

@ -6,13 +6,6 @@
#include <cpu.h> #include <cpu.h>
#include <interrupts.h> #include <interrupts.h>
registers *divbyzero(registers *r)
{
debug_error("Divide by zero error!\n");
debug_print_registers(r);
for(;;);
}
void kmain(uint64_t multiboot_magic, void *multiboot_data) void kmain(uint64_t multiboot_magic, void *multiboot_data)
{ {
serial_init(PORT_COM1); serial_init(PORT_COM1);
@ -26,13 +19,10 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
cpu_init(); cpu_init();
// Force and catch a divide by zero exception uintptr_t start, end;
// ISR 0 uint32_t type, i=0;
bind_interrupt(0, divbyzero); while(!multiboot_get_memory_area(i++, &start, &end, &type))
int a = 5, b = 0; debug_printf("Mem %d 0x%x-0x%x\n", type, start, end);
int c = a/b;
debug("a: %d b:%d c:%d\n", a,b,c);
debug_ok("Boot \"Complete\"\n"); debug_ok("Boot \"Complete\"\n");

View File

@ -15,14 +15,29 @@ struct tag {
uint8_t data[]; uint8_t data[];
}__attribute__((packed)); }__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));
#define MBOOT2_COMMANDLINE 1 #define MBOOT2_COMMANDLINE 1
#define MBOOT2_BOOTLOADER 2 #define MBOOT2_BOOTLOADER 2
#define MBOOT2_MMAP 6
struct kernel_boot_data_st kernel_boot_data; struct kernel_boot_data_st kernel_boot_data;
int parse_multiboot2(struct taglist *tags) int parse_multiboot2(struct taglist *tags)
{ {
struct tag *tag = incptr(tags, sizeof(struct taglist)); struct tag *tag = incptr(tags, sizeof(struct taglist));
struct mmap *mmap;
while(tag->type) while(tag->type)
{ {
switch(tag->type) switch(tag->type)
@ -33,6 +48,10 @@ int parse_multiboot2(struct taglist *tags)
case MBOOT2_COMMANDLINE: case MBOOT2_COMMANDLINE:
kernel_boot_data.commandline = (char *)tag->data; kernel_boot_data.commandline = (char *)tag->data;
break; break;
case MBOOT2_MMAP:
mmap = kernel_boot_data.mmap = (void *)tag->data;
kernel_boot_data.mmap_size = (tag->size - 8)/mmap->entry_size;
break;
default: default:
debug_warning("Unknown multiboot tag type:%d \n", tag->type); debug_warning("Unknown multiboot tag type:%d \n", tag->type);
} }
@ -54,3 +73,17 @@ int multiboot_init(uint64_t magic, void *mboot_info)
return 0; return 0;
} }
int multiboot_get_memory_area(size_t count, uintptr_t *start, uintptr_t *end, uint32_t *type)
{
if(count >= kernel_boot_data.mmap_size) return 1;
struct mmap *mmap = kernel_boot_data.mmap;
struct mmap_entry *entry = mmap->entries;
entry = incptr(entry, count*mmap->entry_size);
*start = entry->base;
*end = entry->base + entry->len;
*type = entry->type;
return 0;
}

View File

@ -149,3 +149,75 @@ TEST(reads_multiple_tags_4)
ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name)); ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name));
free(tags); free(tags);
} }
TEST(reads_mmap_tag)
{
uint32_t mmap[] = {24, 0,
0x90ABCDEF, 0x12345678, 0x00010000, 0x00000000, 0x1, 0x0
};
void *tags = generate_taglist(2,
generate_tag(6, mmap, 32),
generate_tag(0,0,0)
);
multiboot_init(MAGIC, tags);
ASSERT_EQ_INT(kernel_boot_data.mmap_size, 1);
free(tags);
}
void setup_memory_areas()
{
uint32_t mmap[] = {24, 0,
0x90ABCDEF, 0x12345678, 0x00010000, 0x00000000, 0x1, 0x0,
0x0ABCDEF1, 0x23456789, 0x00010000, 0x00000000, 0x1, 0x0
};
void *tags = generate_taglist(2,
generate_tag(6, mmap, 56),
generate_tag(0,0,0)
);
multiboot_init(MAGIC, tags);
}
TEST(reads_multiple_mmap_tags)
{
setup_memory_areas();
ASSERT_EQ_INT(kernel_boot_data.mmap_size, 2);
}
TEST(returns_memory_area_start)
{
setup_memory_areas();
uintptr_t start, end;
uint32_t type;
multiboot_get_memory_area(0, &start, &end, &type);
ASSERT_EQ_PTR(start, 0x1234567890ABCDEF);
}
TEST(returns_memory_area_end)
{
setup_memory_areas();
uintptr_t start, end;
uint32_t type;
multiboot_get_memory_area(0, &start, &end, &type);
ASSERT_EQ_PTR(end, 0x1234567890ACCDEF);
}
TEST(returns_memory_area_type)
{
setup_memory_areas();
uintptr_t start, end;
uint32_t type;
multiboot_get_memory_area(0, &start, &end, &type);
ASSERT_EQ_INT(type, 1);
}
TEST(returns_second_memory_area_start)
{
setup_memory_areas();
uintptr_t start, end;
uint32_t type;
multiboot_get_memory_area(1, &start, &end, &type);
ASSERT_EQ_PTR(start, 0x234567890ABCDEF1);
}
TEST(does_not_return_too_many_areas)
{
setup_memory_areas();
uintptr_t start, end;
uint32_t type;
int retval = multiboot_get_memory_area(2, &start, &end, &type);
ASSERT_NEQ_INT(retval, 0);
}

View File

@ -1,12 +1,16 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
struct kernel_boot_data_st struct kernel_boot_data_st
{ {
int multiboot_version; int multiboot_version;
char *bootloader; char *bootloader;
char *commandline; char *commandline;
size_t mmap_size;
void *mmap;
}; };
extern struct kernel_boot_data_st kernel_boot_data; extern struct kernel_boot_data_st kernel_boot_data;
int multiboot_init(uint64_t magic, void *mboot_info); int multiboot_init(uint64_t magic, void *mboot_info);
int multiboot_get_memory_area(size_t count, uintptr_t *start, uintptr_t *end, uint32_t *type);