refactor(kernel): move old c/cpp code into archive folder@@ -101,6 +101,6 @@ void kmain(void) {
/* Idle loop */
while (1) {
- asm volatile ("hlt");
+ asm volatile ("hlt");
}
}
@@ -4,7 +4,8 @@
/* Minimal ISR handlers for linking */
isr_handler_common:
- ret
+ ret
irq_handler_common:
- ret
+ jmp irq_common_entry
+ ret
@@ -2,35 +2,24 @@ lib KernelShim
fun outb(port : UInt16, value : UInt8) : Void
end
-module PS2
+module IRQ
IRQ_COUNT = 16
HANDLERS = StaticArray(Proc(UInt8, Void)?, IRQ_COUNT).new()
def self.init
- self.register_keyboard
- puts "PS/2 initialized!\n"
- end
-
- private def self.register_keyboard
- # todo: handle keyboard events
- register(1, # IRQ 1 = keyboard
- ->(scan_code : UInt8) {
- if scan_code == 0x1C
- puts "Enter\n"
- end
- # do smth
- puts "keyboard event\n"
- })
+ puts "IRQ initialized!\n"
end
def self.register(irq : Int32, handler : Proc(UInt8, Void)) : Proc(UInt8, Void)?
return nil if irq < 0 || irq >= IRQ_COUNT
prev = HANDLERS[irq]
HANDLERS[irq] = handler
+ puts "irq handler registered\n"
prev
end
def self.dispatcher(irq : UInt32)
+ puts "irq dispatcher called ...\n"
i = irq.to_u8
if handler = HANDLERS[i]
handler.call(i)
@@ -40,7 +29,7 @@ end
fun irq_dispatcher_c(irq : UInt32)
puts "irq_dispatcher_c\n"
- PS2.dispatcher(irq)
+ IRQ.dispatcher(irq)
end
fun pic_send_eoi(irq : UInt32)
@@ -1,6 +1,7 @@
require "./vga.cr"
require "./tiny_alloc_i386.cr"
-require "./ps2.cr"
+require "./irq.cr"
+require "./timer.cr"
# require "./pmm.cr"
lib LibBootstrap
@@ -24,9 +25,15 @@ fun kmain
)
# PMM.init # Physical Memory Init
TinyAllocI386.init
- PS2.init
- puts("weeeeeeee\n")
+ IRQ.init
+ Timer.init
+ # Net.init
+ # PS2.init
+ # Audio.init
+ # Display.init
+ # WM.init
+ puts("weeeeeeee\n")
VGA.puts("Can print on multiple lines\n", color: VGA::Colors::BLACK_ON_LIME)
VGA.puts("\nWe still don't have a heap, but now the puts stores the last row and col so it can call the putchar method with the \x1b[32mright\x1b[0m col / row instead of overlaying subsequent calls on-top one of another (this is super long line to test word wrap).\n")
VGA.puts "\nFeatures:\n"
@@ -39,6 +46,22 @@ fun kmain
VGA.puts("\tCan use custom colors", VGA::Colors::RED_ON_BLACK)
VGA.puts("\tCan use another custom color\n", VGA::Colors::GREEN_ON_BLACK)
VGA.puts("\tCan use lot of custom color\n", VGA::Colors::CYAN_ON_BLACK)
+
+ puts "\nPress [enter] to boot into graphical mode\n\n"
+
+ IRQ.register(0, ->(data : UInt8) {
+ puts "timer handler called ...\n"
+ Timer.irq_handler(data)
+ return
+ })
+
+ IRQ.register(1, ->(scan_code : UInt8) {
+ puts "keyboard handler called ...\n"
+ if scan_code == 0x1C
+ puts "Enter\n"
+ end
+ return
+ })
# VGA.set_cursor(0, 5)
# VGA.hide_cursor
@@ -1,18 +1,32 @@
require "./vga.cr"
+lib KernelShim
+ # External assembly ISR for timer
+ fun timer_isr_common : Void
+ fun outb(port : UInt16, value: UInt8) : Void
+end
+
# Timer module - System timer
module Timer
TIMER_FREQ = 1000_u32
-
- # External assembly ISR for timer
- fun timer_isr_common : Void
+
+ @@tick_count : UInt64 = 0
+ class_property tick_count
def self.init : Nil
+ # PIT channel 0, mode 3 (square wave), lobyte/hibyte access
+ KernelShim.outb(0x43, 0x36)
+ # Frequency: 1193182 Hz / divisor = desired frequency (e.g., 100 Hz)
+ divisor = 11931 # 1193182 / 100 ≈ 11931
+ KernelShim.outb(0x40, divisor & 0xFF)
+ KernelShim.outb(0x40, (divisor >> 8) & 0xFF)
+
# Set up PIT or HPET here (placeholder)
- VGA.puts("Timer initialized\n")
+ VGA.puts("Timer initialized!\n")
end
-
- def self.enable : Nil
- # Enable timer IRQ
+
+ def self.irq_handler(data : UInt8)
+ @@tick_count += 1
+ # Could print a dot or update something; for now just increment.
end
-end
+end
@@ -23,9 +23,7 @@ require "./prelude/crystal_core/range"
require "./prelude/crystal_core/string"
require "./prelude/crystal_core/reference"
require "./prelude/crystal_core/static_array"
-
-# needs support for pmm first
-# require "./prelude/crystal_core/array"
+require "./prelude/crystal_core/array"
# crystal api
require "./prelude/puts"
@@ -1,30 +1,23 @@
#!/bin/bash
-# Flags
-
-CC_FLAGS="-ffreestanding -nostdinc -nostdinc++ \
- -Wall -Wextra \
- -o ./bin/kernel.bin -target i386-pc-none-elf \
- -I ./kernel/"
-LD_FLAGS="-nostdlib -Wl,--oformat=binary,-T./kernel/linker.ld"
-CPP_FILES="./kernel/unityBuild.cpp ./build/kernelEntryPoint.o"
-
# Build
mkdir {bin,build} 2> /dev/null
-echo -e "Cleaning..."
+echo -e "Cleaning artifacts..."
rm *.bin *.img *.iso *.o *.vmdk 2> /dev/null
-echo -e "\nBuilding..."
+echo -e "Building bootloader (asm)..."
nasm ./boot/bootloader.asm -I ./boot/ -o ./bin/bootloader.bin || exit 1
+
+echo -e "Building kernel (asm)..."
nasm -felf32 ./kernel/entry.asm -I ./kernel/ -o ./build/kernelEntryPoint.o || exit 1
use_crystal_kernel=${USE_CRYSTAL_KERNEL:-true}
-
if [ "$use_crystal_kernel" = true ]
then
# Build crystal kernel without stdlib, using the custom prelude, and targeting i386-unknown-linux-elf
+ echo -e "Building kernel (crystal)..."
crystal build \
--no-debug \
--cross-compile \
@@ -34,6 +27,7 @@ then
-o ./build/kernel ./kernel/kernel.cr || exit 1
# Link the kernel into an ELF executable, then convert it to a flat binary for the bootloader.
+ echo -e "Linking kernel.elf (ld)..."
ld \
-m elf_i386 \
-nostdlib \
@@ -41,18 +35,27 @@ then
-o ./bin/kernel.elf ./build/kernelEntryPoint.o ./build/kernel.o || exit 1
# Copy kernel.elf to kernel.bin properly.
+ echo -e "Building kernel.bin (objcopy)..."
objcopy \
-O binary ./bin/kernel.elf ./bin/kernel.bin || exit 1
else
+ # Flags
+ CC_FLAGS="-ffreestanding -nostdinc -nostdinc++ -Wall -Wextra -o ./bin/kernel.bin -target i386-pc-none-elf -I ./kernel/archive/cpp/"
+ LD_FLAGS="-nostdlib -Wl,--oformat=binary,-T./kernel/linker.ld"
+ CPP_FILES="./kernel/archive/cpp/unityBuild.cpp ./build/kernelEntryPoint.o"
+
# Build c++ kernel without stdlib, using the custom prelude, and targeting i386-unknown-linux-elf
+ echo -e "Building kernel (cpp)..."
clang++ -v \
$CC_FLAGS \
$LD_FLAGS \
$CPP_FILES || exit 1
fi
+echo -e "Copy kernel.bin into iso/boot/"
cp ./bin/kernel.bin ./iso/boot/kernel.bin || exit 1
+echo -e "Make bootable crystalos.img (genVDisk)..."
./tools/genVDisk \
--output "crystalos" \
--floppy \
@@ -61,10 +64,9 @@ cp ./bin/kernel.bin ./iso/boot/kernel.bin || exit 1
# Run
-echo -e "\nRunning..."
+echo -e "Booting into crystalos.img (qemu)..."
use_vnc=${USE_VNC:-false}
-
if [ "$use_vnc" = true ]
then
qemu-system-i386 -drive if=floppy,index=0,format=raw,file=crystalos.img || exit 1