summaryrefslogtreecommitdiff
path: root/src/boot.asm
blob: 3257a5683605353aba3c81fb62168a326937f8dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
; legacy BIOS PC-boot code, starts in 16-bit real mode
	
; BIOS always loads us to this location
	[org 0x7c00]

; 16-bit real-mode
	[bits 16]

; export a map of kernel symbols for debugging	
	[map symbols kernel.map]
		 
; initialize segment registers
	mov ax, 0
	mov ds, ax
	mov es, ax
	mov ss, ax

; dl contains the boot drive, primarily because that's the last function
; called by the BIOS MBR loader, we remember that for loading additional
; blocks from the boot medium
	mov [BOOT_DRIVE], dl
	
; make sure we know the location of the stack by setting it on our own
; this stack is only used in real mode in stage 1, so it's growing from
; 0xffff down
	mov bp, 0xFFFF
	mov sp, bp
	
; print out some information about CPU mode and BIOS boot drive
	mov si, MESSAGE_REAL_MODE
	call print_string

	mov si, MESSAGE_BOOT_DRIVE
	call print_string
	mov ax, dx
	call print_hex	
	call print_newline

; print we are going to load stage 2 of the boot blocks
	mov si, MESSAGE_LOADING_STAGE_2
	call print_string

; load stage 2 and the kernel together to 0x7e00 (directly
; after the boot sector)	
	mov dl, [BOOT_DRIVE]
	call read_from_disk
	
; jump over variables and subroutines of stage 1 and execute stage 2
	jmp stage2
	
%include "stage1_functions.asm"
		
DISK_ERROR:
	db "DISK ERROR ", 0

SHORT_READ:
	db "DISK SHORT READ", 0

MESSAGE_REAL_MODE:
	db "Started in 16-bit Real Mode", 13, 10, 0

MESSAGE_BOOT_DRIVE:
	db "Booting from drive ", 0
	
MESSAGE_LOADING_STAGE_2:
	db "Loading stage 2 boot loader", 13, 10, 0
	
BOOT_DRIVE:
	db 0
	
; pad rest of sector with zeroes so we get 512 bytes in the end
times 510-($-$$) db 0

; magic number of a boot sector
dw 0xaa55

stage2:
; print a message that we are indeed in stage 2 now
	mov si, MESSAGE_STAGE_2_LOADED
	call print_string

; remember current position on screen, otherwise we loose this
; information after switching to protected mode 
	call current_row
	mov [CURSOR_Y], dh

; enter protected mode
	call switch_to_protected_mode
	
; we should never get here, but just in case
	jmp $

MESSAGE_STAGE_2_LOADED:
	db "Stage 2 boot sectors loaded", 13, 10, 0
	
%include "switch_mode.asm"

[bits 32]

BEGIN_PROTECTED_MODE:

; we switched to protected mode
	mov si, MESSAGE_PROTECTED_MODE
	call pm_print_string
	call pm_print_newline

; check sanity of kernel by searching for MAGIC string at a given
; position
	call check_magic
	cmp ax, 1
	jnz HALT_OS

; print a message before we call the C level kernel	
	mov si, MESSAGE_CALL_C_ENTRY
	call pm_print_string
	call pm_print_newline
	
; call our kernel
	call c_entry

; restore cursor variables from VGA hardware
	call read_hardware_vga_cursor

; "kernel halted" message, when we terminate the C kernel
HALT_OS:
	mov si, MESSAGE_HALTED
	call pm_print_string
	call pm_print_newline

; end of C, disable interupts again, NMIs can still happen
; make sure we loop endlessly here but without burning too
; much CPU
	cli
_halt_loop:
	hlt
	jmp _halt_loop
	
MESSAGE_PROTECTED_MODE:
	db "Switched to 32-bit Protected Mode", 0

MESSAGE_CALL_C_ENTRY:
	db "Calling C entry function", 0
	
MESSAGE_HALTED:
	db "Operating system halted", 0

%include "stage2_functions.asm"

; make sure we have full sectors, stage one is 512 bytes, so we
; have to will up 3 sectors
times 2048-($-$$) db 0

; position is 0x8400 now for the C entry
c_entry: