summaryrefslogtreecommitdiff
path: root/asm/boot.asm
blob: bb852efca11324aef737b74612b16f564766ccea (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
155
156
157
158
; bootler
; legacy bootloader in nasm-flavoured asm
; 2026 Andromeda
; GPL licensed

[bits 16]
[org 0x7C00] ; address where bootloader is loaded

xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00

mov ah, 0x0E
mov al, 'R'
int 0x10
mov al, 'e'
int 0x10
mov al, 'a'
int 0x10
mov al, 'l'
int 0x10
mov al, 0x0D
int 0x10
mov al, 0x0A
int 0x10
mov al, 0x00 ; stops serial and bios output from overlapping in qemu -nographic
int 0x10     ; output

; activate a20
mov ax, 0x2401
int 0x15
jc error

; load kernel
; 'docs' from https://www.ctyme.com/intr/rb-0607.htm
mov ah, 0x02
mov al, 1 ; number of sectors to read (must be nonzero)
mov ch, 0 ; low eight bits of cylinder number
mov cl, 2 ; sector number 1-63 (bits 0-5); high two bits of cylinder (bits 6-7,
          ; hard disk only)
mov dh, 0 ; head number
; dl is already set by bios
mov bx, 0x1000 ; data buffer
mov es, bx
xor bx, bx
int 0x13 ; read disk
jc error

; load gdt
lgdt [gdt_descriptor]

; jump to pm
cli
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:pm_start

error:
  mov al, 'e'
  int 0x10
  mov al, 'r'
  int 0x10
  mov al, 'r'
  int 0x10
  mov al, 'o'
  int 0x10
  mov al, 'r'
  int 0x10
  jmp $

gdt_data:
  ; null segment
  dq 0x0000000000000000
  ; code segment
  dw 0xFFFF
  dw 0x0000

  db 0x00
  db 10011010b ; 32-bit code segment, present, ring 0
  db 11001111b ; limit bits 16-19
  db 0x00

  ; data segment
  dw 0xFFFF
  dw 0x0000

  db 0x00
  db 10010010b ; 32-bit data segment, present, ring 0
  db 11001111b ; limit bits 16-19
  db 0x00

gdt_descriptor:
  dw $ - gdt_data - 1 ; size
  dd gdt_data         ; start

[bits 32]

; entry point
pm_start:
  ; data segment registers
  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov ss, ax
  mov esp, 0x80000

  ; TODO actually configure COM1
  mov dx, 0x3F8 ; COM1
  mov al, 'P'
  out dx, al
  mov al, 'r'
  out dx, al
  mov al, 'o'
  out dx, al
  mov al, 't'
  out dx, al
  mov al, 'e'
  out dx, al
  mov al, 'c'
  out dx, al
  mov al, 't'
  out dx, al
  mov al, 'e'
  out dx, al
  mov al, 'd'
  out dx, al
  mov al, 0x0D
  out dx, al
  mov al, 0x0A
  out dx, al

  jmp 0x08:0x10000

pm_error:
  mov al, 'p'
  out dx, al
  mov al, 'm'
  out dx, al
  mov al, 'e'
  out dx, al
  mov al, 'r'
  out dx, al
  mov al, 'r'
  out dx, al
  mov al, 'o'
  out dx, al
  mov al, 'r'
  out dx, al
  jmp $
  
times 510-($-$$) db 0 ; 2 bytes less now
db 0x55
db 0xAA