kernel

hobby kernel
git clone git://git.evenfri.duckdns.org/kernel.git
Log | Files | Refs | README | LICENSE

commit 82084d59718d0cded62a753110d82b3c05f289fc
parent 97ff1cf15e62e17652fbd4b789e7c07f711c155b
Author: evenfri <evenfri256@gmail.com>
Date:   Mon,  3 Aug 2026 02:23:28 +0800

add printk, panic, show memory

Diffstat:
M.gitignore | 1+
Mboot.asm | 8--------
Mfns.h | 6++++++
Minit.c | 40+++++++++++++++++++++++++++++-----------
Aiso.sh | 7+++++++
Mmkfile | 4+++-
Apanic.c | 14++++++++++++++
Aprintk.c | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aqemu-iso.sh | 11+++++++++++
Auser/isodir/boot/grub/grub.cfg | 3+++
Auser/isodir/boot/kernel | 0
11 files changed, 223 insertions(+), 20 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ **/*.o **/o.* **/*.a +**/*.iso diff --git a/boot.asm b/boot.asm @@ -20,7 +20,6 @@ stack_top: section .text global _start -extern multiboot extern start_kernel _start: @@ -31,13 +30,6 @@ _start: push ebx push eax - call multiboot - - ; reset arguments - add esp, 8 - xor eax, eax - xor ebx, ebx - ; enter the high-level kernel call start_kernel diff --git a/fns.h b/fns.h @@ -24,6 +24,9 @@ static inline uint8_t inb(uint16_t port) { /* string */ size_t strlen(const char* str); +/* stdio */ +int printk(const char* restrict format, ...); + /* vga */ static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { return fg | bg << 4; @@ -64,4 +67,7 @@ void syscall_init(); void pit_init(uint32_t freq); void pit_sleep(uint32_t ticks_to_wait); +/* panic */ +void kpanic(const char *msg); + #endif /* fns_h */ diff --git a/init.c b/init.c @@ -7,12 +7,31 @@ extern size_t test_syscall_read(); void multiboot(uint32_t magic, multiboot_info_t *mbi) { if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { - return; + kpanic("invalid magic number!"); + } + + if (!(mbi->flags >> 6 & 0x1)) { + kpanic("invalid memory map given by GRUB"); + } + + int i; + for (i = 0; i < mbi->mmap_length; i += sizeof(multiboot_memory_map_t)) { + multiboot_memory_map_t* mmmt = + (multiboot_memory_map_t*) (mbi->mmap_addr + i); + + if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE) { + } + } + if (mbi->flags & 0x1) { + /* mem_lower — ram before 640 KB */ + /* mem_upper — ram > 1024 KB */ + uint32_t total_kb = mbi->mem_lower + mbi->mem_upper; + uint32_t total_mb = total_kb / 1024; + printk("memory: %d kb, %d mb\n", total_kb, total_mb); } - (void)*mbi; } -void init() { +void init(uint32_t magic, multiboot_info_t *mbi) { tty_init(); vfs_write(stdout, "tty initialized\n", 16); @@ -31,6 +50,10 @@ void init() { keyboard_init(); vfs_write(stdout, "keyboard initialized\n", 21); + multiboot(magic, mbi); + vfs_write(stdout, "multiboot initialized\n", 22); + + /* enable interrupts */ asm volatile ("sti"); } @@ -47,17 +70,12 @@ void bin_init_prog() { } } -void start_kernel() { - init(); +void start_kernel(uint32_t magic, multiboot_info_t *mbi) { + init(magic, mbi); bin_init_prog(); while(1) { - tty_clear(); - vfs_write(stdout, "kernel panic!\n", 14); - vfs_write(stdout, " no /bin/init program\n", 23); - - asm volatile("cli"); - asm volatile("hlt"); + kpanic("failed to start /bin/init"); } } diff --git a/iso.sh b/iso.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +iso="./user/os.iso" + +cp "./o.kernel" "./user/isodir/boot/kernel" + +grub-mkrescue -o "$iso" "./user/isodir" diff --git a/mkfile b/mkfile @@ -22,7 +22,9 @@ ofiles = boot.$o \ syscall.$o \ pit.$o \ init.$o \ - strlen.$o + panic.$o \ + strlen.$o \ + printk.$o hfiles = fns.h \ dat.h diff --git a/panic.c b/panic.c @@ -0,0 +1,14 @@ +#include <dat.h> +#include <fns.h> + +void kpanic(const char *msg) { + while (1) { + tty_clear(); + vfs_write(stdout, "kernel panic!\n", 14); + vfs_write(stdout, " ", 2); + vfs_write(stdout, (void*) msg, strlen(msg)); + + asm volatile("cli"); + asm volatile("hlt"); + } +} diff --git a/printk.c b/printk.c @@ -0,0 +1,149 @@ +#include <limits.h> +#include <stdbool.h> +#include <stdarg.h> +#include <dat.h> +#include <fns.h> + +#define EOF (-1) + +static char *utoa_hex(unsigned int num, char *buf, size_t bufsize) { + char *p = buf + bufsize - 1; + *p = '\0'; + do { + int digit = num & 0xF; + *--p = (digit < 10) ? ('0' + digit) : ('a' + digit - 10); + num >>= 4; + } while (num != 0 && p > buf); + return p; +} + +static char *itoa_dec(int num, char *buf, size_t bufsize) { + char *p = buf + bufsize - 1; + *p = '\0'; + unsigned int un; + int sign = 0; + + if (num < 0) { + sign = 1; + un = (unsigned int)(-(long long)num); + } else { + un = (unsigned int)num; + } + + do { + *--p = '0' + (un % 10); + un /= 10; + } while (un != 0 && p > buf); + + if (sign) { + if (p > buf) *--p = '-'; + } + return p; +} + +static bool print(const char* data, size_t length) { + if (vfs_write(stdout, (void*) data, length) == EOF) + return false; + return true; +} + +int printk(const char* restrict format, ...) { + va_list args; + va_start(args, format); + + int count = 0; + const char *p = format; + + while (*p) { + if (*p != '%') { + /* char */ + if (!print(p, 1)) { + va_end(args); + return -1; + } + count++; + p++; + } else { + p++; /* skip '%' */ + if (!*p) break; + + char spec = *p++; + switch (spec) { + case '%': + { + if (!print("%", 1)) { + va_end(args); + return -1; + } + count++; + break; + } + case 'c': + { + char c = (char)va_arg(args, int); + if (!print(&c, 1)) { + va_end(args); + return -1; + } + count++; + break; + } + case 's': + { + char *str = va_arg(args, char*); + if (str == NULL) str = "(null)"; + size_t len = strlen(str); + if (!print(str, len)) { + va_end(args); + return -1; + } + count += len; + break; + } + case 'x': + { + unsigned int num = va_arg(args, unsigned int); + char buf[32]; + char *hex = utoa_hex(num, buf, sizeof(buf)); + size_t len = strlen(hex); + if (!print(hex, len)) { + va_end(args); + return -1; + } + count += len; + break; + } + case 'd': + { + int num = va_arg(args, int); + char buf[32]; + char *dec = itoa_dec(num, buf, sizeof(buf)); + size_t len = strlen(dec); + if (!print(dec, len)) { + va_end(args); + return -1; + } + count += len; + break; + } + default: + { + if (!print("%", 1)) { + va_end(args); + return -1; + } + count++; + if (!print(&spec, 1)) { + va_end(args); + return -1; + } + count++; + break; + } + } + } + } + + va_end(args); + return count; +} diff --git a/qemu-iso.sh b/qemu-iso.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e +iso="./user/os.iso" +mem="4M" + +./iso.sh + +exec qemu-system-i386 \ + -m "$mem" \ + -cdrom "$iso" \ diff --git a/user/isodir/boot/grub/grub.cfg b/user/isodir/boot/grub/grub.cfg @@ -0,0 +1,3 @@ +menuentry "os" { + multiboot /boot/kernel +} diff --git a/user/isodir/boot/kernel b/user/isodir/boot/kernel Binary files differ.