summaryrefslogtreecommitdiff
path: root/src/boot.asm
blob: f56d6a658e4729cde53927f41c0e2322b45a5eba (plain) (blame)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
bits 16
org 0x7c3e

kernel_sectors equ 128
kernel_segment equ 0x3000

support_flags equ 0x4000
pci_hw_char   equ 0x4001
pci_ver       equ 0x4002
last_pci_bus  equ 0x4004
bios_mmap_len equ 0x4006
vbe_mode      equ 0x4008

vbe_block     equ 0x4200
vbe_mode_info equ 0x4400

pci_support equ 0x80
pae_support equ 0x40

  in al, 0x92
  or al, 0x02
  out 0x92, al

  xor ax, ax
  mov ss, ax
  mov sp, 0x8000

  mov ax, kernel_segment
  mov es, ax
  mov ax, 0x0200 + kernel_sectors
  xor bx, bx
  mov cx, 0x0002
  xor dh, dh
  int 0x13

  mov ax, 0xb101
  int 0x1a

  cmp edx, 0x20494350
  jne no_pci

  test ah, ah
  jnz no_pci

  mov byte [support_flags], pci_support
  mov byte [pci_hw_char], al
  mov word [pci_ver], bx
  mov byte [last_pci_bus], cl

no_pci:
  mov eax, 1
  cpuid

  test dl, 0x40
  jz no_pae

  or byte [support_flags], pae_support

no_pae:
  mov ax, 0x1000
  mov es, ax
  xor di, di

  mov edx, 0x534d4150
  xor ebx, ebx

mmap_loop:
  mov eax, 0xe820
  mov ecx, 24
  int 0x15

  jc mmap_end
  add di, 24
  test ebx, ebx
  jnz mmap_loop
mmap_end:
  mov word [bios_mmap_len], di

  xor ax, ax
  mov es, ax
  mov di, vbe_block
  mov ah, 0x4f

  mov dword [di], 0x32454256;'VBE2'

  int 0x10

  cmp dword [di], 0x41534556;'VESA'
  jne no_vbe

  mov bx, word [di + 0x0e]
  mov ax, word [di + 0x10]
  mov fs, ax
  xor esi, esi
  mov bp, 0xffff
  mov di, 0x5000

vbe_loop:
  max_height equ 800
  ;fs:bx is mode pointer
  ;esi is highest resolution yet (width * height)
  ;bp is that mode's number
  ;uses 0x5000 - 0x50ff as mode info buffer
  ;skips those without byte-aligned pixels

  mov cx, word [fs:bx]
  cmp cx, 0xffff
  je got_highest_vbe

  add bx, 4

  mov ax, 0x4f01
  int 0x10

  mov al, byte [di]
  not al

  test al, 0x9a
  jnz vbe_loop

  mov dx, word [di + 0x14];height
  cmp dx, max_height
  jg vbe_loop

  mov ax, word [di + 0x12];width
  mul dx

  shl edx, 16
  mov dx, ax

  xor eax, eax

  mov al, byte [di + 0x19];bpp
  test al, 0x07
  jnz vbe_loop

  mul edx

  cmp eax, esi
  jle vbe_loop

  mov esi, eax
  mov bp, cx
  jmp vbe_loop

got_highest_vbe:
  cmp bp, 0xffff
  je no_vbe

  mov cx, bp
  mov ax, 0x4f01
  mov di, vbe_mode_info
  int 0x10

  or ch, 0x40
  mov word [vbe_mode], cx

  mov ax, 0x4f02
  mov bx, cx
  int 0x10

  cli

  lgdt [gdt]

  mov eax, cr0
  or al, 0x01
  mov cr0, eax

  jmp 0x10:pmode

no_vbe:
  xor ax, ax
  mov es, ax

  mov ax, 0x1300
  mov bx, 0x004f
  mov cx, no_vbe_str.len
  xor dx, dx
  mov bp, no_vbe_str
  int 0x10

real_halt:
  hlt
  jmp real_halt

no_vbe_str:
  db "NO VBE2!"
.len equ $ - no_vbe_str

bits 32

pmode:
  mov ax, 0x18
  mov ds, ax
  mov es, ax
  mov ss, ax
  mov esp, 0x0002f000

  xor ebp, ebp

  call kernel_segment * 16

halt:
  hlt
  jmp halt

times $$ + 510 - 0x3e - $ - (gdt.e - gdt) db 0

gdt:
  dw .e - .t
  dd .t
.t:
  dq 0x0000_0000_0000_0000;0x00: null
  dq 0x0040_8900_4f98_0068;0x08: tss, 0x4f98
  dq 0x00cf_9a00_0000_ffff;0x10: kernel code
  dq 0x00cf_9200_0000_ffff;0x18: kernel data
  dq 0x00cf_fa00_0000_ffff;0x20: user code
  dq 0x00cf_f200_0000_ffff;0x28: user data
.e:

dw 0xaa55