Organizing the kernel code.

This commit is contained in:
Nicolás Ortega Froysa
2018-02-23 18:50:05 +01:00
parent 7a2618dd4d
commit 78c1155430
9 changed files with 11 additions and 16 deletions

55
boot/boot_sect.asm Normal file
View File

@ -0,0 +1,55 @@
[org 0x7c00]
KERNEL_OFFSET: equ 0x1000 ; kernel memory offset
mov [BOOT_DRIVE], dl ; store boot drive for later.
mov bp, 0x9000 ; setup the stack
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call load_kernel ; load our kernel from memory
call switch_to_pm ; switch to 32-bit protected mode
jmp $
%include "print.asm"
%include "print32.asm"
%include "disk.asm"
%include "gdt.asm"
%include "switch_prot.asm"
[bits 16]
load_kernel:
mov bx, MSG_LOAD_KERNEL
call print_string
mov bx, KERNEL_OFFSET ; address to load the kernel to
mov dh, 1 ; number of sectors to load
mov dl, [BOOT_DRIVE] ; drive to load from
call disk_load
mov bx, MSG_KERNEL_LOADED
call print_string
ret
[bits 32]
BEGIN_PM:
mov ebx, MSG_PROT_MODE
call print_string_pm
call KERNEL_OFFSET
jmp $
;;;
; Data
BOOT_DRIVE: db 0
MSG_REAL_MODE: db "Started in 16-bit Real Mode",0
MSG_PROT_MODE: db "Successfully landed in 32-bit Protected Mode",0
MSG_LOAD_KERNEL: db "Loading kernel into memory...",0
MSG_KERNEL_LOADED: db "Successfully loaded kernel into memory",0
times 510-($-$$) db 0
dw 0xaa55

43
boot/disk.asm Normal file
View File

@ -0,0 +1,43 @@
;;;
; disk_load
; ---------
; Load disk sectors into memory.
;
; Parameters:
; - dh: number of sectors to read
disk_load:
pusha
push dx ; store `dx' to check if the appropriate number of
; sectors were read later on.
mov ah, 0x02 ; BIOS read routine
mov al, dh ; read `dh' sectors
mov ch, 0x00 ; select cylinder 0
mov dh, 0x00 ; select head 0
mov cl, 0x02 ; start reading from second sector (after the boot
; sector)
int 0x13 ; BIOS interrupt
jc disk_load_error ; if `cf' flag has gone off then a read error has
; occurred
pop dx ; restore `dx'
cmp dh, al ; were the appropriate amount of sectors read?
jne disk_load_unexp ; if not then there was an error
popa
ret
disk_load_error:
mov bx, DISK_READ_ERROR ; print the error
jmp disk_load_print_exit
disk_load_unexp:
mov bx, DISK_READ_UNEXP
disk_load_print_exit:
call print_string
jmp $ ; lock due to failure
DISK_READ_UNEXP:
db "Unexpected amount of sectors read!",0
DISK_READ_ERROR:
db "Disk read error!",0

37
boot/gdt.asm Normal file
View File

@ -0,0 +1,37 @@
; GDT
gdt_start:
gdt_null:
dd 0x0 ; the mandatory null-descriptor
dd 0x0
gdt_code: ; code segment of descriptor
dw 0xFFFF ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23
; 1st flags: (present)1, (privilege)00, (descriptor type)1 -> 1001b
; type flags: (code)1, (conforming)0, (readable)1, (accessed)0 -> 1010b
; 2nd flags: (granularity)1, (32-bit default)1, (64-bit seg)0, (AVL)0 -> 1100b
db 10011010b ; 1st flags and type flags
db 11001111b ; 2nd flags and Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_data:
; type flags: (code)0, (expand down)0, (writable)1, (accessed)0 -> 0010b
dw 0xFFFF ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10010010b ; 1st flags and type flags
db 11001111b ; 2nd flags and Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_end: ; for calculating size of the gdt
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of our GDT, always decrement true size by one
dd gdt_start ; start address of our GDT
;;;
; Constants used for GDT segment offsets
GDT_CODE_SEG: equ gdt_code - gdt_start
GDT_DATA_SEG: equ gdt_data - gdt_start

31
boot/print.asm Normal file
View File

@ -0,0 +1,31 @@
;;;
; print_string
; ------------
; Print a string from memory.
;
; Parameters:
; - bx: pointer to string
;
; Internal Variables:
; - ah: scrolling teletype BIOS routine code
; - al: Byte containing character to print
; - bx: shifting pointer to string
print_string:
pusha ; save the state of all registers to the stack
mov ah, 0x0e ; scrolling teletype BIOS routine code
print_string_start:
mov al, [bx] ; load first letter into `al'
cmp al, 0
je print_string_end ; if null-termination then return
int 0x10 ; print the letter
add bx, 0x1 ; offset to next character
jmp print_string_start ; go back to beginning
print_string_end:
mov al, 0xA
int 0x10
mov al, 0xD
int 0x10
popa ; return the state of all the registers
ret

30
boot/print32.asm Normal file
View File

@ -0,0 +1,30 @@
[bits 32]
VIDEO_MEMORY: equ 0xB8000
WHITE_ON_BLACK: equ 0x0F
;;;
; print_string_pm
; ------------
; Print a string stored in memory.
;
; Parameters:
; - ebx: pointer to string in memory
print_string_pm:
pusha
mov edx, VIDEO_MEMORY ; set `edx' to the start of the video memory
print_string_pm_loop:
mov al, [ebx] ; store the char at `ebx' in `al'
mov ah, WHITE_ON_BLACK ; store the attributes in `ah'
cmp al, 0 ; if null-termination then done
je print_string_pm_done
mov [edx], ax ; store char and attributes
add ebx, 1 ; increment ebx to next char
add edx, 2 ; increment to next char cell in vidmem
jmp print_string_pm_loop
print_string_pm_done:
popa
ret

29
boot/switch_prot.asm Normal file
View File

@ -0,0 +1,29 @@
[bits 16]
switch_to_pm:
cli ; turn off all interrupts until we have properly
; properly set them up
lgdt [gdt_descriptor] ; load the global descriptor table defining
; protected mode segments
mov eax, cr0 ; set flag in register to switch to protected mode
or eax, 0x1
mov cr0, eax
jmp GDT_CODE_SEG:init_pm ; make a far jump to the 32-bit code forcing a flush
; of the pipelining
[bits 32]
; initialize registers and the stack once in protected mode
init_pm:
mov ax, GDT_DATA_SEG ; point our new segment registers to the data
mov ds, ax ; selector defined in the GDT, since we cannot
mov ss, ax ; use the old 16-bit code
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; Update the stack position so it's at the top
mov esp, ebp ; of the free space
call BEGIN_PM