Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kernel/include/khal.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extern uint64_t paging_main[3][512] __attribute__((aligned(4096)));

void serial_write_byte(uint8_t byte);
int serial_init( );
void serial_printf(const char *fmt, ...) ;

#else
#error "Only AMD64 is supported"
Expand Down
2 changes: 2 additions & 0 deletions kernel/include/kstdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;

typedef uint64_t uintptr_t;

#endif
18 changes: 5 additions & 13 deletions kernel/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ int multiboot2_init(uint64_t *addr, uint32_t magic);

void kernel_main64(uint64_t *multiboot2, uint32_t magic, void *esp, uint64_t base) {
serial_init( );
serial_write_byte(':');
serial_write_byte('D');
serial_write_byte('\n');
serial_printf(":D\n");

int status = multiboot2_init(multiboot2, magic);
serial_write_byte('\n');

if (status) {
serial_write_byte('[');
serial_write_byte('O');
serial_write_byte('K');
serial_write_byte(']');
serial_printf("[OK]\n");
} else {
serial_write_byte('[');
serial_write_byte('E');
serial_write_byte('R');
serial_write_byte('R');
serial_write_byte(']');
serial_printf("[ERR]\n");
}

for (;;) {}
}
80 changes: 80 additions & 0 deletions kernel/klibc/printf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <stdarg.h>
#include <kstdint.h>
#include <khal.h>

static char *itoa(uint64_t value, char *buf, uint8_t base) {
char *ptr = buf;
uint64_t temp = value;
do {
uint64_t digit = temp % base;
if (digit < 10)
*ptr = '0' + digit;
else
*ptr = 'A' + (digit - 10);
ptr++;
temp /= base;
} while (temp);
*ptr = '\0';
// Reverse the string
char *start = buf;
char *end = ptr - 1;
while (start < end) {
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
return buf;
}

void serial_printf(const char *fmt, ...) {
char buf[32];
va_list args;
va_start(args, fmt);
while (*fmt) {
if (*fmt == '%') {
fmt++;
switch (*fmt) {
case 's':
{
char *str = va_arg(args, char *);
while (*str)
serial_write_byte(*str++);
}
break;
case 'd':
{
int64_t num = va_arg(args, int64_t);
itoa(num, buf, 10);
serial_printf("%s", buf);
}
break;
case 'u':
{
uint64_t num = va_arg(args, uint64_t);
itoa(num, buf, 10);
serial_printf("%s", buf);
}
break;
case 'x':
{
uint64_t num = va_arg(args, uint64_t);
itoa(num, buf, 16);
serial_printf("%s", buf);
}
break;
case 'c':
serial_write_byte(va_arg(args, int));
break;
default:
serial_write_byte(*fmt);
break;
}
fmt++;
} else {
serial_write_byte(*fmt++);
}
}
va_end(args);
}
106 changes: 88 additions & 18 deletions kernel/multiboot2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,98 @@
#include <kstdlib.h>

#define CHECK_FLAG(flags, bit) ((flags) & (1 << (bit)))
#define printf(...)

void handle_cmdline_tag(struct multiboot_tag *tag);
void handle_module_tag(struct multiboot_tag *tag);
void handle_basic_load_base_addr(struct multiboot_tag *tag);
void handle_basic_meminfo_tag(struct multiboot_tag *tag);
void handle_mmap_tag(struct multiboot_tag *tag);

int multiboot2_init(uint64_t *addr, uint32_t magic) {
serial_write_byte('1' + __COUNTER__);
struct multiboot_tag *tag;

if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
printf("Invalid magic number: 0x%x\n", (unsigned)magic);
return -1;
}

if ((uint64_t)addr & 7) {
printf ("Unaligned mbi: 0x%x\n", addr);
return -2;
struct multiboot_tag *tag;
uint64_t mbi_addr = (uint64_t)addr;

if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
serial_printf("Invalid magic number: 0x%x\n", (unsigned)magic);
return -1;
}

if (mbi_addr & 7) {
serial_printf("Unaligned mbi: 0x%x\n", mbi_addr);
return -2;
}

uint64_t size = *addr;
serial_printf("Announced mbi size 0x%x\n", size);

tag = (struct multiboot_tag *)(mbi_addr + sizeof(uint64_t));

while (tag->type != MULTIBOOT_TAG_TYPE_END) {
if ((uintptr_t)tag % MULTIBOOT_TAG_ALIGN != 0) {
serial_printf("Tag at 0x%x is not aligned correctly\n", (uintptr_t)tag);
break;
}

switch (tag->type) {
case MULTIBOOT_TAG_TYPE_CMDLINE:
handle_cmdline_tag(tag);
break;
case MULTIBOOT_TAG_TYPE_MODULE:
handle_module_tag(tag);
break;
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
handle_basic_meminfo_tag(tag);
break;
case MULTIBOOT_TAG_TYPE_MMAP:
handle_mmap_tag(tag);
break;
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
handle_basic_load_base_addr(tag);
break;
default:
serial_printf("Tag at 0x%x | %d\n", (uintptr_t)tag, tag->type);
break;
}

// Move to the next tag
tag = (struct multiboot_tag *)((uintptr_t)tag) + ((tag->size + 7) & ~7);
}

uint64_t size = *addr;
IGNORE_UNUSED(size);
IGNORE_UNUSED(tag);
return 1;
}

void handle_cmdline_tag(struct multiboot_tag *tag) {
struct multiboot_tag_string *cmdline = (struct multiboot_tag_string *)tag;
serial_printf("Command line: %s\n", cmdline->string);
}

void handle_module_tag(struct multiboot_tag *tag) {
struct multiboot_tag_module *module = (struct multiboot_tag_module *)tag;
serial_printf("Module at 0x%x - 0x%x\n", module->mod_start, module->mod_end);
serial_printf("Module cmdline: %s\n", module->cmdline);
}

printf ("Announced mbi size 0x%x\n", size);
void handle_basic_meminfo_tag(struct multiboot_tag *tag) {
struct multiboot_tag_basic_meminfo *meminfo = (struct multiboot_tag_basic_meminfo *)tag;
serial_printf("Memory lower: %u KB\n", meminfo->mem_lower);
serial_printf("Memory upper: %u KB\n", meminfo->mem_upper);
}

serial_write_byte('1' + __COUNTER__);
return 1;
void handle_basic_load_base_addr(struct multiboot_tag *tag) {
struct multiboot_tag_load_base_addr *base_addr = (struct multiboot_tag_load_base_addr *)tag;
serial_printf("load_base_size: %u\n", base_addr->size);
serial_printf("load_base_addr: 0x%x\n", base_addr->load_base_addr);
}

void handle_mmap_tag(struct multiboot_tag *tag) {
struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
struct multiboot_mmap_entry *entry;
uint64_t entry_size = mmap->entry_size;
uint64_t entry_count = (mmap->size - sizeof(struct multiboot_tag_mmap)) / entry_size;

serial_printf("Memory map:\n");
for (uint64_t i = 0; i < entry_count; i++) {
entry = (struct multiboot_mmap_entry *)((uintptr_t)mmap + sizeof(struct multiboot_tag_mmap) + i * entry_size);
serial_printf(" 0x%x - 0x%x: type %u\n", entry->addr, entry->addr + entry->len, entry->type);
}
}
Loading