Feat: Kernel up and running.
This commit is contained in:
parent
9e4224793b
commit
3bd026ca7a
33
build.sh
33
build.sh
@ -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}"
|
||||
|
||||
179
elevator.asm
179
elevator.asm
@ -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
|
||||
|
||||
2
kernel.c
2
kernel.c
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user