Feat: Kernel up and running.

This commit is contained in:
AfonsoCMSousa 2025-11-19 20:11:50 +00:00
parent 9e4224793b
commit 3bd026ca7a
3 changed files with 189 additions and 25 deletions

View File

@ -13,32 +13,40 @@ BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Prepare build environment
echo -e "Preparing build environment...${NC}"
echo -e "Creating Folders${NC}"
mkdir -p bin obj boot include
echo -e "${GREEN}${NC}Folders created.${NC}"
# Step 1: Assemble Stage 1 bootloader (MBR - 512 bytes)
echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..."
nasm -f bin boot.asm -o boot.bin
nasm -f bin ./boot/boot.asm -o ./bin/boot.bin
# Step 2: Assemble Stage 2 bootloader (extended loader)
echo -e "${BLUE}[2/6]${NC} Assembling Stage 2 bootloader..."
nasm -f bin elevator.asm -o elevator.bin
nasm -f bin ./boot/elevator.asm -o ./bin/elevator.bin
# Step 3: Assemble kernel entry point
echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..."
nasm -f elf64 kernel.asm -o kernel.asm.o
nasm -f elf64 kernel.asm -o ./obj/kernel.asm.o
# Step 4: Compile kernel C code
echo -e "${BLUE}[4/6]${NC} Compiling kernel..."
gcc -ffreestanding -c kernel.c -o kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64
gcc -ffreestanding -c kernel.c -o ./obj/kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64
# Step 5: Link kernel
echo -e "${BLUE}[5/6]${NC} Linking kernel..."
ld -T linker.ld -o kernel.bin kernel.asm.o kernel.c.o --oformat binary
ld -T linker.ld -o ./bin/kernel.bin ./obj/kernel.asm.o ./obj/kernel.c.o --oformat binary --nostdlib
# Step 6: Create OS image
echo -e "${BLUE}[6/6]${NC} Creating OS image..."
cat boot.bin elevator.bin kernel.bin > os-image.bin
cat ./bin/boot.bin ./bin/elevator.bin ./bin/kernel.bin > os.bin
# Pad to floppy size (1.44MB)
truncate -s 1440K os-image.bin
# FIX: Uncomment the line below if you want to ensure the image is exactly 1.44MB
#
# truncate -s 1440K os-image.bin
echo ""
echo -e "${GREEN}✓ Build complete!${NC}"
@ -55,17 +63,18 @@ echo ""
echo "File Sizes:"
printf "%-15s %10s\n" "File" "Size"
printf "%-15s %10s\n" "----" "----"
printf "%-15s %10d bytes\n" "boot.bin" $(stat -f%z boot.bin 2>/dev/null || stat -c%s stage1.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "elevator.bin" $(stat -f%z elevator.bin 2>/dev/null || stat -c%s stage2.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "kernel.bin" $(stat -f%z kernel.bin 2>/dev/null || stat -c%s kernel.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "os-image.bin" $(stat -f%z os-image.bin 2>/dev/null || stat -c%s os-image.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "boot.bin" $(stat -f%z ./bin/boot.bin 2>/dev/null || stat -c%s ./bin/boot.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "elevator.bin" $(stat -f%z ./bin/elevator.bin 2>/dev/null || stat -c%s ./bin/elevator.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "kernel.bin" $(stat -f%z ./bin/kernel.bin 2>/dev/null || stat -c%s ./bin/kernel.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "os.bin" $(stat -f%z os.bin 2>/dev/null || stat -c%s os.bin 2>/dev/null)
echo ""
echo -e "${YELLOW}Running QEMU...${NC}"
echo "==================================="
echo "Press Ctrl+C to exit QEMU"
echo ""
qemu-system-x86_64 -drive format=raw,file=os-image.bin -no-reboot -d cpu_reset
qemu-system-x86_64 -drive format=raw,file=os.bin -no-reboot
echo -e "${GREEN}Done!${NC}"

View File

@ -2,12 +2,12 @@
; Stage 2 Bootloader - No size limit!
; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel
[org 0x7e00]
[bits 16]
KERNEL_OFFSET equ 0x10000 ; Load kernel at 64KB (safer than 0x1000)
BOOT_DRIVE: db 0 ; Store boot drive number
ERROR_CODE: db 0 ; Store error code from disk read
stage2_start:
; Print stage 2 message
@ -36,12 +36,32 @@ stage2_start:
call print_string
pop ax
push ax
call print_hex_word ; Print the word we read
; If it's 0x0000, kernel didn't load
; Also check bytes 2-3
mov ax, 0x1000
mov es, ax
mov bx, 2
mov ax, [es:bx]
xor bx, bx
mov es, bx
mov si, msg_space
call print_string
call print_hex_word
; Check if first word is non-zero
pop ax
test ax, ax
jz kernel_load_failed
jnz .kernel_found
; Kernel is zeros - try reading from different LBA offsets
mov si, msg_searching
call print_string
jmp kernel_load_failed
.kernel_found:
mov si, msg_kernel_ok
call print_string
@ -67,6 +87,44 @@ load_kernel:
push bx
push cx
push dx
push si
; Show what we're about to do
mov si, msg_loading_kernel
call print_string
; Check if LBA is available
mov ah, 0x41
mov bx, 0x55AA
mov dl, [BOOT_DRIVE]
int 0x13
jc .use_chs ; If carry set, LBA not supported
; Use LBA mode
mov si, msg_using_lba
call print_string
; Set up DAP (Disk Address Packet)
mov word [dap_size], 0x10
mov word [dap_sectors], 10
mov word [dap_offset], 0x0000
mov word [dap_segment], 0x1000
mov dword [dap_lba_low], 6 ; LBA 6 = bytes 3072+ (sector 7 in CHS)
mov dword [dap_lba_high], 0
; Read using LBA
mov ah, 0x42
mov dl, [BOOT_DRIVE]
mov si, dap
int 0x13
jc kernel_error
jmp .read_done
.use_chs:
; Fall back to CHS mode
mov si, msg_using_chs
call print_string
; Reset disk system first
mov ah, 0x00
@ -74,32 +132,51 @@ load_kernel:
int 0x13
; Set up ES:BX for the destination
; KERNEL_OFFSET is 0x10000, so we need ES=0x1000, BX=0x0000
mov ax, 0x1000
mov es, ax
xor bx, bx ; BX = 0, so ES:BX = 0x1000:0x0000 = 0x10000
xor bx, bx
; Now try loading kernel
; Read using CHS
mov ah, 0x02 ; Read function
mov al, 10 ; Number of sectors
mov ch, 0 ; Cylinder 0
mov cl, 7 ; Start at sector 7
mov cl, 7 ; Sector 7
mov dh, 0 ; Head 0
mov dl, [BOOT_DRIVE] ; Drive number
int 0x13
jc kernel_error
.read_done:
; Print success
mov si, msg_sectors_read
call print_string
mov si, msg_newline
call print_string
; Restore ES to 0
xor ax, ax
mov es, ax
pop si
pop dx
pop cx
pop bx
pop ax
ret
; Disk Address Packet for LBA
align 4
dap:
dap_size: db 0x10
dap_reserved: db 0
dap_sectors: dw 0
dap_offset: dw 0
dap_segment: dw 0
dap_lba_low: dd 0
dap_lba_high: dd 0
kernel_error:
; Restore ES
xor ax, ax
@ -131,10 +208,73 @@ kernel_load_failed:
xor ax, ax
mov es, ax
; Kernel is zeros at expected location
; Let's try reading from different LBA sectors to find it
mov si, msg_verify_failed
call print_string
; Try LBA 5
mov si, msg_try_lba5
call print_string
mov word [dap_lba_low], 5
call try_read_kernel
; Try LBA 7
mov si, msg_try_lba7
call print_string
mov word [dap_lba_low], 7
call try_read_kernel
; Try LBA 8
mov si, msg_try_lba8
call print_string
mov word [dap_lba_low], 8
call try_read_kernel
jmp $
try_read_kernel:
push si
; Read to 0x10000
mov ax, 0x1000
mov es, ax
mov word [dap_segment], ax
mov ah, 0x42
mov dl, [BOOT_DRIVE]
mov si, dap
int 0x13
; Check what we got
xor bx, bx
mov ax, [es:bx]
xor cx, cx
mov es, cx
call print_hex_word
mov si, msg_newline
call print_string
; If non-zero, we found it!
test ax, ax
jz .not_found
mov si, msg_found
call print_string
; Jump directly to protected mode!
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp 0x08:protected_mode
.not_found:
pop si
ret
; ============================================================
; PRINT STRING (16-bit)
; ============================================================
@ -195,11 +335,23 @@ print_hex_word:
msg_stage2: db '[STAGE2] Extended bootloader loaded', 0x0D, 0x0A, 0
msg_kernel_loaded: db '[STAGE2] Kernel loaded, switching to Protected Mode...', 0x0D, 0x0A, 0
msg_kernel_error: db '[ERROR] Kernel load failed!', 0x0D, 0x0A, 0
msg_kernel_check: db '[STAGE2] Verifying kernel load: Read word = 0x', 0
msg_kernel_ok: db '[STAGE2] Kernel load verified.', 0x0D, 0x0A, 0
msg_verify_failed: db '[ERROR] Kernel verification failed!', 0x0D, 0x0A, 0
msg_error_code: db ' Error code: 0x', 0
msg_drive: db ' Drive number: 0x', 0
msg_error_code: db ' Error code: ', 0
msg_drive: db ' Drive: ', 0
msg_loading_kernel: db '[STAGE2] Loading kernel from disk...', 0x0D, 0x0A, 0
msg_using_lba: db '[STAGE2] Using LBA mode for disk access', 0x0D, 0x0A, 0
msg_using_chs: db '[STAGE2] Using CHS mode for disk access', 0x0D, 0x0A, 0
msg_sectors_read: db '[STAGE2] Sectors read successfully', 0
msg_newline: db 0x0D, 0x0A, 0
msg_kernel_check: db '[STAGE2] Verifying kernel load: Read words: ', 0
msg_space: db ' ', 0
msg_searching: db '[STAGE2] Kernel not found, searching alternative sectors...', 0x0D, 0x0A, 0
msg_kernel_ok: db '[STAGE2] Kernel verification successful!', 0x0D, 0x0A, 0
msg_verify_failed: db '[STAGE2] Kernel verification failed.', 0x0D, 0x0A, 0
msg_try_lba5: db '[STAGE2] Trying LBA 5...', 0x0D, 0x0A, 0
msg_try_lba7: db '[STAGE2] Trying LBA 7...', 0x0D, 0x0A, 0
msg_try_lba8: db '[STAGE2] Trying LBA 8...', 0x0D, 0x0A, 0
msg_found: db '[STAGE2] Kernel found!', 0x0D, 0x0A, 0
ERROR_CODE: db 0
; ============================================================
; GDT - Global Descriptor Table
@ -488,3 +640,6 @@ print_64:
lm_msg: db '[64-BIT] Long mode active...', 0
before_kernel_msg: db '[64-BIT] Calling kernel...', 0
kernel_return_msg: db '[KERNEL] Returned unexpectedly!', 0
; Add pading to make the elevator 2560 bytes.
times 2560 - ($ - $$) db 0

View File

@ -33,7 +33,7 @@ void kmain(void) {
// Write messages
write_string(10, 30, "SORA OS KERNEL", 0x0A); // Green
write_string(12, 25, "64-bit kernel running!", 0x0F); // White
write_string(14, 28, "System Initialized", 0x0E); // Yellow
write_string(14, 28, "System Initialized", 0x0E); // Yellow
// Infinite loop
while (1) {