-AS = yasm # choose yasm or nasm here
-ASFLAGS = -f bin # compile a raw binary
+AS = yasm
+LD = i686-elf-ld
+CC = i686-elf-gcc
-boot: boot.s print.s
- $(AS) $(ASFLAGS) -o $@ boot.s
+all: boot.img
-clean:
- -rm boot
+boot.img: boot kernel/kernel.bin
+ cat boot kernel/kernel.bin > $@
+ truncate -s1440K $@
+
+boot: boot.s
+ $(AS) -f bin boot.s -o $@
+
+kernel/kernel.bin: kernel/entry.o kernel/kernel.o
+ $(LD) -o $@ -Ttext 0x1000 kernel/entry.o kernel/kernel.o --oformat=binary
-run:
- qemu-system-i386 boot
+kernel/entry.o: kernel/entry.s
+ $(AS) -f elf kernel/entry.s -o $@
-help:
- @echo "Run 'make' to compile."
- @echo "Run 'make clean' to delete compiled objects."
- @echo "Run 'make run' to run the compiled object. Must have qemu-system-i386 (but x86_64 should work too)."
+kernel/kernel.o: kernel/kernel.c
+ $(CC) -o $@ -ffreestanding -c kernel/kernel.c
+
+clean:
+ rm boot kernel/kernel.bin kernel/entry.o kernel/kernel.o boot.img
-.PHONY = clean run help
+.PHONY: all clean
- bits 16 ; boot sectors run in real mode
- org 7c00h ; boot sector is loaded at 0x7c00
+ bits 16
+ org 7C00h
-_start
- mov di, printing_numbers
- call print
+KERNEL_OFFSET equ 1000h
- or bl, 1
- mov dx, 0DEADh ; number to print
- call print_word
+ mov [BOOT_DRIVE], dl
+
+ mov bp, 9000h
+ mov sp, bp
+
+ mov di, 0
+
+ xor ax, ax
+ int 13h
+ jc reset_error
+
+ mov ah, 2
+ mov al, 10
+ xor ch, ch
+ mov cl, 2
+ xor dh, dh
+ xor bx, bx
+ mov es, bx
+ mov bx, KERNEL_OFFSET
+ int 13h
+ jc read_error
+ cmp al, 10
+ jl read_error
+ jmp switch_to_pm
+
+reset_error
+ mov bx, 0B800h
+ mov es, bx
+ mov byte [es:di], '1'
+ jmp halt
+
+read_error
+ mov bx, 0B800h
+ mov es, bx
+ mov byte [es:di], '2'
+ jmp halt
+
+ call switch_to_pm
+
+halt
+ jmp $
+
+switch_to_pm
+ mov bx, 0B800h
+ mov es, bx
+ mov byte [es:0], 'L'
+
+ cli
+ xor ax, ax
+ mov ds, ax
+ lgdt [gdt_desc]
- mov di, space
- call print
+ mov eax, cr0
+ or eax, 1
+ mov cr0, eax
+ jmp CODE_SEG:protected
+
+ bits 32
+protected
+ mov ax, DATA_SEG
+ mov ds, ax
+ mov ss, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
- xor bl, bl
- mov dx, 0BEEFh
- call print_word
+ mov ebp, 090000h
+ mov esp, ebp
- mov di, waiting
- call print
+ mov ebx, pm_success
+ call pmprint
- mov di, keystroke
- mov bl, 1
+ call KERNEL_OFFSET
-.loop
- mov ah, 0
- int 16h
- cmp ah, 1Ch
- je .enterpressed
- jmp .continue
- cmp ah, 0Eh
- je .backspace
- jmp .continue
-.enterpressed
+ jmp $
+
+pmprint
pusha
- mov ah, 0Eh
- mov al, 0Dh
- int 10h
- mov al, 0Ah
- int 10h
- popa
+ mov edx, video_memory
+
+.loop
+ mov al, [ebx]
+ mov ah, 0Fh
+
+ cmp al, 0
+ je .done
+
+ mov [edx], al
+ mov [edx+1], ah
+
+ inc ebx
+ add edx, 2
+
jmp .loop
-.backspace
- pusha
- mov ah, 03h
- mov bh, 0
- int 10h
- dec dl
- mov ah, 02h
- int 10h
- mov ah, 0Eh
- mov al, ' '
- int 10h
- mov ah, 02h
- int 10h
+
+.done
popa
- jmp .loop
-.continue
- mov [keystroke], al
- call print
- jmp .loop
+ ret
+
+pm_success db "Now in protected mode", 0
+video_memory equ 0B8000h
-printing_numbers db "Printing some random hex numbers", 0
-waiting db "I await keystrokes", 0
-keystroke db "$", 0
-space db " ", 0
+gdt_start
+null_seg
+ dq 0
+code_seg
+ dw 0FFFFh
+ dw 0
+ db 0
+ db 10011010b
+ db 11001111b
+ db 0
+data_seg
+ dw 0FFFFh
+ dw 0
+ db 0
+ db 10010010b
+ db 11001111b
+ db 0
+gdt_end
+gdt_desc
+ dw gdt_end - gdt_start - 1
+ dd gdt_start
+CODE_SEG equ code_seg - gdt_start
+DATA_SEG equ data_seg - gdt_start
-%include "print.s"
+BOOT_DRIVE db 0
- times 510-($-$$) db 0 ; fill with 0 until 0x1fc is reached
- dw 0AA55h ; BIOS MBR signature
+ times 510-($-$$) db 0
+ dw 0AA55h
+++ /dev/null
-%define CURRENT_ADDR cs:di
-
-; Prints a null terminated string of your choice.
-; Arguments:
-; CS:DI - pointer to the string you want to print
-; BL - 0 prints newline, otherwise no
-print
- pusha
- mov ah, 0Eh ; teletype print
-.write2
- mov al, [CURRENT_ADDR] ; get current char and put it in al
- cmp al, 0 ; check if al is null (string terminator)
- je .newline ; if it is, start a new line
- int 10h ; otherwise write the char
- inc di ; increment pointer to string
- jmp .write2 ; jump back to this section
-.newline
- cmp bl, 1
- je .done
- mov al, 0Dh ; carriage return
- int 10h
- mov al, 0Ah ; line feed
- int 10h
-.done
- popa
- ret ; return
-
-; Prints a word (16-bit value) in hex format.
-; Arguments:
-; DX - word to print
-; BL - 0 will print a newline, 1 won't
-print_word
- pusha ; push all regs to stack
- mov di, HEX_OUT+5 ; set destination index to last char in HEX_OUT
- mov ax, dx ; copy argument to accumulator
- and al, 00001111b ; extract the low nibble of the low half of the accumulator
- call .compare ; fill in the string with correct value
- dec di ; decrement string pointer
- mov ax, dx ; copy argument to accumulator
- and al, 11110000b ; extract high nibble of low half of accumulator
- shr al, 4 ; shift high nibble to low nibble
- call .compare ; fill in string with correct value
- dec di
- mov al, ah ; copy high portion of accumulator to low
- and al, 00001111b ;
- call .compare
- dec di
- mov al, ah
- and al, 11110000b
- shr al, 4
- call .compare
- mov di, HEX_OUT
- call print ; write string
- popa
- ret
-
-.compare
- cmp al, 0 ; compare al with 0
- jne .one ; if not equal, compare with 1
- mov byte [CURRENT_ADDR], '0' ; set character to ASCII 0
- ret ; return
-.one
- cmp al, 1
- jne .two
- mov byte [CURRENT_ADDR], '1'
- ret
-.two
- cmp al, 2
- jne .three
- mov byte [CURRENT_ADDR], '2'
- ret
-.three
- cmp al, 3
- jne .four
- mov byte [CURRENT_ADDR], '3'
- ret
-.four
- cmp al, 4
- jne .five
- mov byte [CURRENT_ADDR], '4'
- ret
-.five
- cmp al, 5
- jne .six
- mov byte [CURRENT_ADDR], '5'
- ret
-.six
- cmp al, 6
- jne .seven
- mov byte [CURRENT_ADDR], '6'
- ret
-.seven
- cmp al, 7
- jne .eight
- mov byte [CURRENT_ADDR], '7'
- ret
-.eight
- cmp al, 8
- jne .nine
- mov byte [CURRENT_ADDR], '8'
- ret
-.nine
- cmp al, 9
- jne .ten
- mov byte [CURRENT_ADDR], '9'
- ret
-.ten
- cmp al, 0Ah
- jne .eleven
- mov byte [CURRENT_ADDR], 'A'
- ret
-.eleven
- cmp al, 0Bh
- jne .twelve
- mov byte [CURRENT_ADDR], 'B'
- ret
-.twelve
- cmp al, 0Ch
- jne .thirteen
- mov byte [CURRENT_ADDR], 'C'
- ret
-.thirteen
- cmp al, 0Dh
- jne .fourteen
- mov byte [CURRENT_ADDR], 'D'
- ret
-.fourteen
- cmp al, 0Eh
- jne .fifteen
- mov byte [CURRENT_ADDR], 'E'
- ret
-.fifteen
- mov byte [CURRENT_ADDR], 'F'
- ret
-
-HEX_OUT db "0x0000", 0