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'
|
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}"
|
||||||
|
|||||||
179
elevator.asm
179
elevator.asm
@ -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
|
||||||
|
|||||||
2
kernel.c
2
kernel.c
@ -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) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user