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' YELLOW='\033[1;33m'
NC='\033[0m' 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) # Step 1: Assemble Stage 1 bootloader (MBR - 512 bytes)
echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..." 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) # Step 2: Assemble Stage 2 bootloader (extended loader)
echo -e "${BLUE}[2/6]${NC} Assembling Stage 2 bootloader..." 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 # Step 3: Assemble kernel entry point
echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..." 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 # Step 4: Compile kernel C code
echo -e "${BLUE}[4/6]${NC} Compiling kernel..." 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 # Step 5: Link kernel
echo -e "${BLUE}[5/6]${NC} Linking 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 # Step 6: Create OS image
echo -e "${BLUE}[6/6]${NC} Creating 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) # 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 ""
echo -e "${GREEN}✓ Build complete!${NC}" echo -e "${GREEN}✓ Build complete!${NC}"
@ -55,17 +63,18 @@ echo ""
echo "File Sizes:" echo "File Sizes:"
printf "%-15s %10s\n" "File" "Size" printf "%-15s %10s\n" "File" "Size"
printf "%-15s %10s\n" "----" "----" 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" "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 elevator.bin 2>/dev/null || stat -c%s stage2.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 kernel.bin 2>/dev/null || stat -c%s kernel.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-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" "os.bin" $(stat -f%z os.bin 2>/dev/null || stat -c%s os.bin 2>/dev/null)
echo "" echo ""
echo -e "${YELLOW}Running QEMU...${NC}" echo -e "${YELLOW}Running QEMU...${NC}"
echo "===================================" echo "==================================="
echo "Press Ctrl+C to exit QEMU" echo "Press Ctrl+C to exit QEMU"
echo "" 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}" echo -e "${GREEN}Done!${NC}"

View File

@ -2,12 +2,12 @@
; Stage 2 Bootloader - No size limit! ; Stage 2 Bootloader - No size limit!
; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel ; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel
[org 0x7e00] [org 0x7e00]
[bits 16] [bits 16]
KERNEL_OFFSET equ 0x10000 ; Load kernel at 64KB (safer than 0x1000) KERNEL_OFFSET equ 0x10000 ; Load kernel at 64KB (safer than 0x1000)
BOOT_DRIVE: db 0 ; Store boot drive number BOOT_DRIVE: db 0 ; Store boot drive number
ERROR_CODE: db 0 ; Store error code from disk read
stage2_start: stage2_start:
; Print stage 2 message ; Print stage 2 message
@ -36,12 +36,32 @@ stage2_start:
call print_string call print_string
pop ax pop ax
push ax
call print_hex_word ; Print the word we read 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 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 mov si, msg_kernel_ok
call print_string call print_string
@ -67,6 +87,44 @@ load_kernel:
push bx push bx
push cx push cx
push dx 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 ; Reset disk system first
mov ah, 0x00 mov ah, 0x00
@ -74,32 +132,51 @@ load_kernel:
int 0x13 int 0x13
; Set up ES:BX for the destination ; Set up ES:BX for the destination
; KERNEL_OFFSET is 0x10000, so we need ES=0x1000, BX=0x0000
mov ax, 0x1000 mov ax, 0x1000
mov es, ax 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 ah, 0x02 ; Read function
mov al, 10 ; Number of sectors mov al, 10 ; Number of sectors
mov ch, 0 ; Cylinder 0 mov ch, 0 ; Cylinder 0
mov cl, 7 ; Start at sector 7 mov cl, 7 ; Sector 7
mov dh, 0 ; Head 0 mov dh, 0 ; Head 0
mov dl, [BOOT_DRIVE] ; Drive number mov dl, [BOOT_DRIVE] ; Drive number
int 0x13 int 0x13
jc kernel_error 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 ; Restore ES to 0
xor ax, ax xor ax, ax
mov es, ax mov es, ax
pop si
pop dx pop dx
pop cx pop cx
pop bx pop bx
pop ax pop ax
ret 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: kernel_error:
; Restore ES ; Restore ES
xor ax, ax xor ax, ax
@ -131,10 +208,73 @@ kernel_load_failed:
xor ax, ax xor ax, ax
mov es, 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 mov si, msg_verify_failed
call print_string 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 $ 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) ; PRINT STRING (16-bit)
; ============================================================ ; ============================================================
@ -195,11 +335,23 @@ print_hex_word:
msg_stage2: db '[STAGE2] Extended bootloader loaded', 0x0D, 0x0A, 0 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_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_error: db '[ERROR] Kernel load failed!', 0x0D, 0x0A, 0
msg_kernel_check: db '[STAGE2] Verifying kernel load: Read word = 0x', 0 msg_error_code: db ' Error code: ', 0
msg_kernel_ok: db '[STAGE2] Kernel load verified.', 0x0D, 0x0A, 0 msg_drive: db ' Drive: ', 0
msg_verify_failed: db '[ERROR] Kernel verification failed!', 0x0D, 0x0A, 0 msg_loading_kernel: db '[STAGE2] Loading kernel from disk...', 0x0D, 0x0A, 0
msg_error_code: db ' Error code: 0x', 0 msg_using_lba: db '[STAGE2] Using LBA mode for disk access', 0x0D, 0x0A, 0
msg_drive: db ' Drive number: 0x', 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 ; GDT - Global Descriptor Table
@ -488,3 +640,6 @@ print_64:
lm_msg: db '[64-BIT] Long mode active...', 0 lm_msg: db '[64-BIT] Long mode active...', 0
before_kernel_msg: db '[64-BIT] Calling kernel...', 0 before_kernel_msg: db '[64-BIT] Calling kernel...', 0
kernel_return_msg: db '[KERNEL] Returned unexpectedly!', 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 messages
write_string(10, 30, "SORA OS KERNEL", 0x0A); // Green write_string(10, 30, "SORA OS KERNEL", 0x0A); // Green
write_string(12, 25, "64-bit kernel running!", 0x0F); // White 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 // Infinite loop
while (1) { while (1) {