Parse multiboot information
This commit is contained in:
parent
d0b946f327
commit
49f7738be2
@ -13,6 +13,9 @@ BootStack:
|
|||||||
_start:
|
_start:
|
||||||
cli
|
cli
|
||||||
|
|
||||||
|
mov edi, eax
|
||||||
|
mov esi, ebx
|
||||||
|
|
||||||
//; Set up a known stack
|
//; Set up a known stack
|
||||||
mov esp, offset V2P(BootStack)
|
mov esp, offset V2P(BootStack)
|
||||||
|
|
||||||
|
@ -2,18 +2,20 @@
|
|||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
#include <vga.h>
|
#include <vga.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
void kmain()
|
void kmain(uint64_t multiboot_magic, void *multiboot_data)
|
||||||
{
|
{
|
||||||
serial_init(PORT_COM1);
|
serial_init(PORT_COM1);
|
||||||
vga_init();
|
vga_init();
|
||||||
|
debug_printf("kernel loaded\n");
|
||||||
|
|
||||||
debug("Hello from debug printing function!\n");
|
|
||||||
debug("A number:%d\n", 12345);
|
parse_multiboot(multiboot_magic, P2V(multiboot_data));
|
||||||
debug_info("Here's some info\n");
|
|
||||||
debug_ok("This thing worked well!\n");
|
debug_printf("Hello from debug printing function!\n");
|
||||||
debug_warning("Careful!\n");
|
debug_printf("A number:%d\n", 12345);
|
||||||
debug_error("Something went wrong!\n");
|
debug_printf("Multiboot data: %x, magic: %x\n", multiboot_data, multiboot_magic);
|
||||||
|
|
||||||
PANIC("Reached end of kernel main function\n");
|
PANIC("Reached end of kernel main function\n");
|
||||||
for(;;);
|
for(;;);
|
||||||
|
42
src/kernel/boot/multiboot.c
Normal file
42
src/kernel/boot/multiboot.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <multiboot.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#define MBOOT_REPLY 0x36D76289
|
||||||
|
|
||||||
|
struct kernel_boot_data_st kernel_boot_data;
|
||||||
|
|
||||||
|
int parse_multiboot2(struct mboot2_taglist *tags)
|
||||||
|
{
|
||||||
|
struct mboot2_tag *tag = incptr(tags, sizeof(struct mboot2_taglist));
|
||||||
|
while(tag->type)
|
||||||
|
{
|
||||||
|
switch(tag->type)
|
||||||
|
{
|
||||||
|
case MBOOT2_BOOTLOADER:
|
||||||
|
kernel_boot_data.bootloader = (char *)tag->data;
|
||||||
|
break;
|
||||||
|
case MBOOT2_COMMANDLINE:
|
||||||
|
kernel_boot_data.commandline = (char *)tag->data;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug("[info] Unknown multiboot tag type:%d \n", tag->type);
|
||||||
|
}
|
||||||
|
int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0);
|
||||||
|
tag = incptr(tag, padded_size);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_multiboot(uint64_t magic, void *mboot_info)
|
||||||
|
{
|
||||||
|
if(magic == MBOOT_REPLY)
|
||||||
|
{
|
||||||
|
kernel_boot_data.multiboot_version = 2;
|
||||||
|
parse_multiboot2(mboot_info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
144
src/kernel/boot/multiboot.tt
Normal file
144
src/kernel/boot/multiboot.tt
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// vim: ft=c
|
||||||
|
#include <ttest.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#undef debug
|
||||||
|
#define debug(...)
|
||||||
|
#undef P2V
|
||||||
|
#define P2V(addr) (void *)((uintptr_t)(addr))
|
||||||
|
#include "multiboot.c"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define MAGIC 0x36D76289
|
||||||
|
|
||||||
|
struct mboot2_tag *generate_tag(uint32_t type, void *data, uint32_t data_size)
|
||||||
|
{
|
||||||
|
struct mboot2_tag *tag = calloc(1, sizeof(struct mboot2_tag) + data_size);
|
||||||
|
tag->type = type;
|
||||||
|
tag->size = sizeof(struct mboot2_tag) + data_size;
|
||||||
|
if(data_size)
|
||||||
|
memcpy(tag->data, data, data_size);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define padded_size(tag) (tag->size + ((tag->size%8)?(8-(tag->size%8)):0))
|
||||||
|
|
||||||
|
struct mboot2_taglist *generate_taglist(int num, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, num);
|
||||||
|
uint32_t total_size = sizeof(struct mboot2_taglist);
|
||||||
|
struct mboot2_tag **tags = calloc(num, sizeof(struct mboot2_tag *));
|
||||||
|
for(int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
tags[i] = va_arg(args, struct mboot2_tag *);
|
||||||
|
total_size += padded_size(tags[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mboot2_taglist *taglist = calloc(1, total_size);
|
||||||
|
taglist->total_size = total_size;
|
||||||
|
|
||||||
|
int pos = 8;
|
||||||
|
uint8_t *p = (uint8_t *)taglist;
|
||||||
|
for(int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
memcpy(&p[pos], tags[i], tags[i]->size);
|
||||||
|
pos += padded_size(tags[i]);
|
||||||
|
free(tags[i]);
|
||||||
|
}
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return taglist;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(correctly_identifies_multiboot2_magic)
|
||||||
|
{
|
||||||
|
uint32_t tags[] = {16, 0, 0, 8};
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_INT(kernel_boot_data.multiboot_version, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(reads_boot_loader_name)
|
||||||
|
{
|
||||||
|
char *name = "ttest";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(2,
|
||||||
|
generate_tag(2, name, strlen(name) + 1),
|
||||||
|
generate_tag(0,0,0));
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name));
|
||||||
|
free(tags);
|
||||||
|
}
|
||||||
|
TEST(reads_kernel_commandline)
|
||||||
|
{
|
||||||
|
char *cmd = "mittos64-kern boot";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(2,
|
||||||
|
generate_tag(1, cmd, strlen(cmd) + 1),
|
||||||
|
generate_tag(0,0,0));
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd));
|
||||||
|
free(tags);
|
||||||
|
}
|
||||||
|
// Here are four very simmilar tests
|
||||||
|
// The difference is what values are checked and the order of the tags
|
||||||
|
// Their existence is based on experience - helped me actually find a bug
|
||||||
|
TEST(reads_multiple_tags_1)
|
||||||
|
{
|
||||||
|
char *cmd = "mittos64-kern boot";
|
||||||
|
char *name = "ttest";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(3,
|
||||||
|
generate_tag(1, cmd, strlen(cmd) + 1),
|
||||||
|
generate_tag(2, name, strlen(name) + 1),
|
||||||
|
generate_tag(0,0,0)
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd));
|
||||||
|
free(tags);
|
||||||
|
}
|
||||||
|
TEST(reads_multiple_tags_2)
|
||||||
|
{
|
||||||
|
char *cmd = "mittos64-kern boot";
|
||||||
|
char *name = "ttest";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(3,
|
||||||
|
generate_tag(1, cmd, strlen(cmd) + 1),
|
||||||
|
generate_tag(2, name, strlen(name) + 1),
|
||||||
|
generate_tag(0,0,0)
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name));
|
||||||
|
free(tags);
|
||||||
|
}
|
||||||
|
TEST(reads_multiple_tags_3)
|
||||||
|
{
|
||||||
|
char *cmd = "mittos64-kern boot";
|
||||||
|
char *name = "ttest";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(3,
|
||||||
|
generate_tag(2, name, strlen(name) + 1),
|
||||||
|
generate_tag(1, cmd, strlen(cmd) + 1),
|
||||||
|
generate_tag(0,0,0)
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.commandline, cmd, strlen(cmd));
|
||||||
|
free(tags);
|
||||||
|
}
|
||||||
|
TEST(reads_multiple_tags_4)
|
||||||
|
{
|
||||||
|
char *cmd = "mittos64-kern boot";
|
||||||
|
char *name = "ttest";
|
||||||
|
struct mboot2_taglist *tags = generate_taglist(3,
|
||||||
|
generate_tag(2, name, strlen(name) + 1),
|
||||||
|
generate_tag(1, cmd, strlen(cmd) + 1),
|
||||||
|
generate_tag(0,0,0)
|
||||||
|
);
|
||||||
|
|
||||||
|
parse_multiboot(MAGIC, tags);
|
||||||
|
ASSERT_EQ_STR(kernel_boot_data.bootloader, name, strlen(name));
|
||||||
|
free(tags);
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define V2P(a) ((uintptr_t)(a) & ~KERNEL_OFFSET)
|
#define V2P(a) ((uintptr_t)(a) & ~KERNEL_OFFSET)
|
||||||
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
||||||
|
#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define P1_OFFSET(a) (((a)>>12) & 0x1FF)
|
#define P1_OFFSET(a) (((a)>>12) & 0x1FF)
|
||||||
|
25
src/kernel/include/multiboot.h
Normal file
25
src/kernel/include/multiboot.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
struct kernel_boot_data_st
|
||||||
|
{
|
||||||
|
int multiboot_version;
|
||||||
|
char *bootloader;
|
||||||
|
char *commandline;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kernel_boot_data_st kernel_boot_data;
|
||||||
|
|
||||||
|
struct mboot2_taglist{
|
||||||
|
uint32_t total_size;
|
||||||
|
uint32_t reserved;
|
||||||
|
}__attribute__((packed));
|
||||||
|
struct mboot2_tag {
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t data[];
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
#define MBOOT2_COMMANDLINE 1
|
||||||
|
#define MBOOT2_BOOTLOADER 2
|
||||||
|
|
||||||
|
int parse_multiboot(uint64_t magic, void *mboot_info);
|
Loading…
x
Reference in New Issue
Block a user