Bootloader halts on interrupt that should load the kernel

48 Views Asked by At

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"
0

There are 0 best solutions below