Add some stuff (printf)

This commit is contained in:
Aren Elchinyan 2025-01-12 17:52:36 +03:00
parent b00d5ed2a5
commit 4f714b0bc3
5 changed files with 176 additions and 31 deletions

View File

@ -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"

View File

@ -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

View File

@ -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
kernel/klibc/printf.c Normal file
View File

@ -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);
}

View File

@ -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;
}
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);
}
}