commit 82084d59718d0cded62a753110d82b3c05f289fc
parent 97ff1cf15e62e17652fbd4b789e7c07f711c155b
Author: evenfri <evenfri256@gmail.com>
Date: Mon, 3 Aug 2026 02:23:28 +0800
add printk, panic, show memory
Diffstat:
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.