summaryrefslogtreecommitdiff
path: root/boot/boot.asm
blob: 62f80f836dd4ab1e4b3dab614fe2eceac6400577 (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
format ELF64

extrn kmain

PML4_TABLE = 0x1000
E820_MMAP  = 0xf000

MSR_EFER   = 0xc0000080

include 'bios.inc'
include 'page.inc'
include 'segdesc.inc'

section '.boot' executable writeable

org 0x7c00
use16
	jmp far 0x0000:@f ; ensure cs = 0x0000
@@:
	xor ax, ax
	mov ds, ax
	mov es, ax

	; put stack directly bellow bootloader
	mov ss, ax
	mov sp, $$
	cld

	mov [boot_disk], dl

	bios_disk_read ($$+0x200), 0, 0, 2, 57, disk_error

	bios_e820_mmap E820_MMAP, e820_error

	bios_a20_enable
	bios_vga_write_mode_3

	page_table_init_real PML4_TABLE

	; disable IRQs
	mov al, 0xff
	out 0xa1, al
	out 0x21, al

	lidt [dummy_idtr]

	; enable PAE (1<<5) and PGE (1<<7)
	mov eax, (1 shl 7) or (1 shl 5)
	mov cr4, eax

	; point cr3 at PML4
	mov edx, edi
	mov cr3, edx

	; enable long mode
	mov ecx, MSR_EFER
	rdmsr
	or eax, (1 shl 8)
	wrmsr

	; enable protected mode
	mov ebx, cr0
	or ebx, (1 shl 31) or (1 shl 0)
	mov cr0, ebx

	lgdt [gdtr]

	jmp far (gdt.kcode-gdt):longmode

e820_error:
	; change beginning of error message ("disk" -> "e820")
	mov dword [errmsg], 0x30323865
disk_error:
	mov si, errmsg
	mov ah, 0x0e
	jmp @f
.loop:
	int 0x10
@@:
	lodsb
	test al, al
	jnz .loop

	; wait until keypress, then jump to reset vector (reboot)
	xor ah, ah
	int 0x16
	jmp far 0xffff:0x0000

use64
longmode:
	mov ax, (gdt.kdata-gdt)
	mov ds, ax
	mov es, ax
	mov ss, ax

	cli

	; copy kernel to 0x100000
	mov ecx, (57*0x200)/8
	mov esi, 0x7e00
	mov edi, 0x100000
	rep movsq

	xor eax, eax
	xor ebx, ebx
	xor ecx, ecx
	xor edx, edx
	xor edi, edi
	xor esi, esi

	; put stack at top of addressable memory
	mov esp, 0x200000
	mov ebp, esp

	; manually encoded 'jmp rel32', fasm throws an 'invalid use of symbol'
	; error when generating code for a jmp to an external symbol after
	; setting code origin with 'org' directive or a 'virtual at X' block.
	db 0xe9
	dd kmain-$-4

align 4
dw 0
label gdtr fword
	.limit dw (gdt.sizeof - 1)
	.addr  dd gdt

align 4
errmsg db "disk error: press any key to reboot",0

align 8
gdt:
	.null dq 0
	.kcode seg_desc 0, 0, (GDT_CODE_64 or SEG_PRIV0)
	.kdata seg_desc 0, 0, (GDT_DATA_64 or SEG_PRIV0)
	.ucode seg_desc 0, 0, (GDT_CODE_64 or SEG_PRIV3)
	.udata seg_desc 0, 0, (GDT_DATA_64 or SEG_PRIV3)
	.sizeof = $ - gdt

align 4
boot_disk db 0, 0
label dummy_idtr fword
	.limit dw 0
	.addr  dd 0

if ($-$$) <= 510
	db 510-($-$$) dup 0
else
	display "ERR: boot sector image exceeds 512 bytes",10
	assert ($-$$) <= 510
end if
db 0x55,0xaa