I followed some tutorials regarding writing a bootloader that will load my kernel. When I try to run it in bochs, I get the following error: LOCK prefix unallowed (op1=0x53, attr=0x0, mod=0x0, nnn=0)
In high level, I have a bootloader located at the first sector of the disk, and after that a 10 sector kernel made up of two files (start.s and kernel.c). The bootloader tries to load the kernel to memory while in real-mode, enter protected mode and jump to the loaded kernel. I am currently stuck when trying to read the sectors to 0x0:0x100000 (which is the value I got from one of the tutorials).
Note: If I change the address from 0x100000 to 0x2000 (in all places, linker script, etc) then the bootloader finishes loading the sectors but it fails to make the jump and bochs restarts and does the whole thing over again.
My entire project is listed below. I would appreciate some help
Thanks,
Yoav.
makefile:
Code: Select all
clean:
rm boot.img
rm build/*
all:
# build bootloader
nasm -o build/bootloader.o bootloader2.s
# build kernel
nasm -f elf -o build/start.o start.s
gcc -o build/kernel.o -O -c kernel.c -Wall -Werror -nostdlib -nostartfiles -nodefaultlibs
# link kernel
ld -T linker.ld -o build/kernel.bin build/start.o build/kernel.o
# create the bootable image
cat build/bootloader.o build/kernel.bin > boot.img
Code: Select all
ENTRY (start)
SECTIONS{
. = 0x00100000;
.text :{
*(.text)
}
.rodata ALIGN (0x1000) : {
*(.rodata)
}
.data ALIGN (0x1000) : {
*(.data)
}
.bss : {
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
}
Code: Select all
[BITS 16] ; We need 16-bit intructions for Real mode
[ORG 0x7C00] ; The BIOS loads the boot sector into memory location 0x7C00
load_kernel:
; print "0" to indicate kernel is starting to load
mov ah,0x0E
mov al,48
mov bl,0x07
mov bh,0x00
int 0x10
; Load the kernel to physical addresss 0x0:0x00100000
mov bx,0x0
mov es,bx
mov bx,0x00100000
; Configure readscector BIOS function
mov ah,0x02 ; read sector function code
mov al,0x01 ; read 1 sector at a time
mov ch,0x00 ; read from track 0
mov dl,0x00 ; read from drive 0 (floopy)
mov dh,0x00 ; read from head 0
mov cl,0x02 ; sector counter - start from the second sector (first sector is bootloader)
readsector:
; call the BIOS and handle errros
int 0x13
jc error
; if read enough sector, finish (10 sectors)
cmp cl,0x0B
je kernel_loaded
; if need to read more sectors, advance buffer and iterate
add bx,WORD 0x200
inc cl
jmp readsector
kernel_loaded:
; Print "D" to indicate that we're done with reading the kernel
mov ah,0x0E
mov bh,0x00
mov bl,0x07
mov al,68
int 0x10
cli ; Disable interrupts, we want to be alone
xor ax, ax
mov ds, ax ; Set DS-register to 0 - used by lgdt
lgdt [gdt_desc] ; Load the GDT descriptor
mov eax, cr0 ; Copy the contents of CR0 into EAX
or al, 1 ; Set bit 0
mov cr0, eax ; Copy the contents of EAX into CR0
jmp 08h:clear_pipe ; Jump to code segment, offset clear_pipe
error:
; Print "E" to the screen to indicate an error has occurred
mov ah,0x0E
mov bh,0x00
mov bl,0x07
mov al,69
int 0x10
; Loop endlessly
jmp $
[BITS 32] ; We now need 32-bit instructions
clear_pipe:
sti
mov ax, 10h ; Save data segment identifyer
mov ds, ax ; Move a valid data segment into the data segment register
mov ss, ax ; Move a valid data segment into the stack segment register
mov esp, 090000h ; Move the stack pointer to 090000h
mov byte [ds:0B8002h], 'P' ; Move the ASCII-code of 'P' into first video memory
mov byte [ds:0B8003h], 1Bh ; Assign a color code
jmp 08h:0x00100000 ; Jump to the kernel
; Address for the GDT
gdt:
gdt_null: ; Null Segment
dd 0
dd 0
gdt_code: ; Code segment, read/execute, nonconforming
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data: ; Data segment, read/write, expand down
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end: ; Used to calculate the size of the GDT
gdt_desc: ; The GDT descriptor
dw gdt_end - gdt - 1 ; Limit (size)
dd gdt ; Address of the GDT
times 510-($-$$) db 0 ; Fill up the file with zeros
dw 0AA55h ; Boot sector identifyer
Code: Select all
[BITS 32]
global start ; making entry point visible to linker
extern kmain ; kmain is defined elsewhere
start:
call kmain ; call kernel
hlt ; halt machine should kernel return
Code: Select all
void kmain()
{
// Print "K" to the screen at position 0,0
//unsigned short *video = (unsigned short *)0XB8000;
//video[0] = 75;
//video[1] = 0x07;
for(;;);
}
Code: Select all
boot: floppy
floppya: 1_44="boot.img", status=inserted
clock: sync=realtime, time0=local