From 4f714b0bc308ad0c46ba2462c7df27d3362c105d Mon Sep 17 00:00:00 2001 From: Aren Elchinyan Date: Sun, 12 Jan 2025 17:52:36 +0300 Subject: [PATCH] Add some stuff (printf) --- kernel/include/khal.h | 1 + kernel/include/kstdint.h | 2 + kernel/kernel.c | 18 ++----- kernel/klibc/printf.c | 80 +++++++++++++++++++++++++++++ kernel/multiboot2.c | 106 ++++++++++++++++++++++++++++++++------- 5 files changed, 176 insertions(+), 31 deletions(-) create mode 100644 kernel/klibc/printf.c diff --git a/kernel/include/khal.h b/kernel/include/khal.h index c1837b6..ac45d20 100644 --- a/kernel/include/khal.h +++ b/kernel/include/khal.h @@ -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" diff --git a/kernel/include/kstdint.h b/kernel/include/kstdint.h index b71c842..dff5238 100644 --- a/kernel/include/kstdint.h +++ b/kernel/include/kstdint.h @@ -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 \ No newline at end of file diff --git a/kernel/kernel.c b/kernel/kernel.c index d585088..46ba5d0 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -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 (;;) {} } \ No newline at end of file diff --git a/kernel/klibc/printf.c b/kernel/klibc/printf.c new file mode 100644 index 0000000..315c149 --- /dev/null +++ b/kernel/klibc/printf.c @@ -0,0 +1,80 @@ +#include +#include +#include + +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); +} \ No newline at end of file diff --git a/kernel/multiboot2.c b/kernel/multiboot2.c index 1641b43..ac2d7dc 100644 --- a/kernel/multiboot2.c +++ b/kernel/multiboot2.c @@ -4,28 +4,98 @@ #include #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; } - uint64_t size = *addr; - IGNORE_UNUSED(size); - IGNORE_UNUSED(tag); + if (mbi_addr & 7) { + serial_printf("Unaligned mbi: 0x%x\n", mbi_addr); + return -2; + } - printf ("Announced mbi size 0x%x\n", size); + uint64_t size = *addr; + serial_printf("Announced mbi size 0x%x\n", size); - serial_write_byte('1' + __COUNTER__); - return 1; + 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); + } + + 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); +} + +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); +} + +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); + } } \ No newline at end of file