I tried to write a bootloader but the bootloader just stops at interrupt 0x13 and then nothing happens. When I rearrange the code, we either get a successful load but somehow can't jump to the kernel, nothing happens, or we get an error saying the kernel can't be loaded. Please help me
Bootloader.asm:
[BITS 16]
[ORG 0x7c00]
BOOT_DRIVE equ 0x00
mov [BOOT_DRIVE], dl
;; first step is to activate the A20 line
mov ax, 0x2401
int 0x15
;; next step is to correctly setup the stack
mov ax, 0x9000
mov ss, ax
mov sp, 0xffff
;; now we can jump to the actual bootloader
jmp bentry
;; here we could define variables for the bentry function
WELCOME_MSG db "Welcome to the bootloader!", 0x0a, 0x0d, 0x00
LOADING_MSG db "Loading kernel...", 0x0a, 0x0d, 0x00
DISK_ERROR_INT13 db "Error while performing int 0x13", 0x0a, 0x0d, 0x00
DISK_ERROR_LOAD db "Error while loading kernel", 0x0a, 0x0d, 0x00
FINISHED_MSG db "Kernel loaded!", 0x0a, 0x0d, 0x00
FAILED_TO_LOAD_GDT db "Failed to load GDT", 0x0a, 0x0d, 0x00
DEBUG_MSG db "Debug message", 0x0a, 0x0d, 0x00
SECTORS db 0x10 ; 16 sectors
CYLINDER db 0x00 ; cylinder 0
HEAD db 0x00 ; head 0
;; Informations about the kernel
TARGET_KERNEL_ADDR dd 0x10000
KERNEL_SIZE equ 0x2000
bentry:
mov si, WELCOME_MSG
call print
jmp .load_kernel
jmp .stop
.load_kernel:
mov si, LOADING_MSG
call print
call load_kernel
mov si, FINISHED_MSG
call print
;jmp .setupVideoMode
jmp .enterProtectedMode
.setupVideoMode:
mov ax, 0x4F02 ; VESA set mode function
mov bx, 0x101 ; Mode number for 640x480x256
int 0x10 ; Call BIOS
jmp .enterProtectedMode
.enterProtectedMode:
call switch_to_pm
jmp halt
.stop:
call halt
;;;;; Protected Mode ;;;;
GDT_start:
GDT_null:
dd 0x0
dd 0x0
GDT_code:
dw 0xffff
dw 0x0
db 0x0
db 0b10011010
db 0b11001111
db 0x0
GDT_data:
dw 0xffff
dw 0x0
db 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_end:
CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start
GDT_DESC:
dw GDT_end - GDT_start - 1
dd GDT_start
switch_to_pm:
cli
lgdt [GDT_DESC]
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:init_pm
;;;;; DISK FUNCTIONS ;;;
;; function to load the kernel
load_kernel:
mov ah, 0x02
mov al, [SECTORS]
mov ch, [CYLINDER]
mov cl, 0x02
mov dh, [HEAD]
mov dl, [BOOT_DRIVE]
mov bx, TARGET_KERNEL_ADDR
mov si, DISK_ERROR_INT13
int 0x13
jc .error
jmp .done
.error:
mov si, DISK_ERROR_LOAD
call print
jmp halt
.done:
ret
;;;;; UTILITY FUNCTIONS ;;;
;; utility function to print a string
print:
pusha
mov ah, 0x0e
.loop:
lodsb
cmp al, 0
je .done
int 0x10
jmp .loop
.done:
popa
ret
;; utility function to halt the system
halt:
hlt
jmp halt
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
mov ebp, esp
; jump to the kernel address
jmp 0x10000
;; bootloader padding
times 510-($-$$) db 0
dw 0xaa55
makefile of the bootloader:
### Author: @fabbboy
### Project: Makefile for a bootloader
### Goal: This is the makefile to compile the V-OS bootloader. This bootloader should setup the hardware
### then switch to video mode and protected or even long mode. It should then load the kernel and
### jump to it.
### Notes: The bootloader must be compiled to a 512 bytes raw binary file. It must be loaded at 0x7C00
### src: Currently we only have the boot.S file.
### dest: The bootloader is compiled to binary and placed into ./bin/boot.bin or ./bin/boot.img that is designed to be a floppy disk image.
### debug: we print as many echos as possible to describe what is happening.
CASM=nasm
CASMFLAGS=-f bin
CASMOUTPUT=bin/boot.bin
CASMINPUT=boot.S
LINKER=ld
LINKERFLAGS= --oformat binary
IMAGE=bin/boot.img
all: clean boot.bin image
boot.bin: boot.S
@echo "Compiling bootloader..."
@$(CASM) $(CASMFLAGS) $(CASMINPUT) -o $(CASMOUTPUT)
@echo "Done."
clean:
@echo "Cleaning..."
@rm -f $(CASMOUTPUT)
@echo "Done."
image:
@echo "Creating floppy image..."
@dd if=/dev/zero of=$(IMAGE) bs=1024 count=1440
@dd if=$(CASMOUTPUT) of=$(IMAGE) conv=notrunc
@echo "Done."
run:
@echo "Running..."
@qemu-system-i386 -fda $(IMAGE)
@echo "Done."
.PHONY: all clean image run
if you need it here is the linker.ld of the kernel:
/* Linker Script for a 32-bit Kernel */
ENTRY(start)
OUTPUT_FORMAT("binary")
SECTIONS
{
/* Code Segment */
.text 0x10000 :
{
code = .;
*(.text)
. = ALIGN(4096);
}
/* Data Segment */
.data :
{
data = .;
*(.data)
. = ALIGN(4096);
}
/* BSS Segment */
.bss :
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
/* End of Kernel */
end = .;
}
and makefile:
# Makefile for V-OS Kernel
# Author: @fabbboy
# Target architecture
# Compiler and Assembler setup
TARGET_CC := /home/ubuntu/i386-elf/bin/i386-elf-gcc
TARGET_ASM := nasm
TARGET_LD := /home/ubuntu/i386-elf/bin/i386-elf-ld
# Flags for different file types
TARGET_ASMFLAGS := -felf
TARGET_CFLAGS := -ffreestanding -m32 -g -nostdlib -I.
TARGET_LIBS := -L/usr/lib/gcc
TARGET_LINKFLAGS := -T linker.ld -nostdlib --oformat binary
# Directories
BUILD_DIR := ./bin
OBJ_DIR_C := $(BUILD_DIR)/object/c
OBJ_DIR_ASM := $(BUILD_DIR)/object/asm
# File finding
SOURCES_C := $(shell find ./ -type f -name '*.c')
SOURCES_ASM := $(shell find ./ -type f -name '*.S')
OBJECTS_C := $(patsubst %.c, $(OBJ_DIR_C)/%.o, $(SOURCES_C))
OBJECTS_ASM := $(patsubst %.S, $(OBJ_DIR_ASM)/%.o, $(SOURCES_ASM))
# Phony targets
.PHONY: all kernel clean
# Default target
all: kernel
# Kernel target
kernel: $(BUILD_DIR)/kernel.bin
# Kernel binary
$(BUILD_DIR)/kernel.bin: $(OBJECTS_ASM) $(OBJECTS_C)
@mkdir -p $(BUILD_DIR)
@$(TARGET_LD) $(TARGET_LINKFLAGS) --Map $(BUILD_DIR)/kernel.map -o $@ $^ $(TARGET_LIBS)
@echo "--> Created: kernel.bin"
# Compile C files
$(OBJ_DIR_C)/%.o: %.c
@mkdir -p $(@D)
@$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
@echo "--> Compiled: " $<
# Compile ASM files
$(OBJ_DIR_ASM)/%.o: %.S
@mkdir -p $(@D)
@$(TARGET_ASM) $(TARGET_ASMFLAGS) -o $@ $<
@echo "--> Compiled: " $<
# Clean target
clean:
@rm -rf $(BUILD_DIR)/*.bin $(OBJ_DIR_C)/*.o $(OBJ_DIR_ASM)/*.o
@echo "--> Cleaned"