~cypheon/xos

xos/boot1.asm -rw-r--r-- 3.1 KiB
567db604 — Johann Rudloff Implement scanning and allocation of physical memory. 7 years ago
                                                                                
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
BITS 16

global pread_sector

extern boot2_main

%define BIOS_MEMDETECT_MAGIC 0x534d4150
%define MMAP_BASE 0x1000

start:
  mov si, hallo
  call print

  push dword MMAP_BASE
  call near detect_memory
  add esp, 4

  ; hide cursor
  mov ah, 0x01
  mov cx, 0x2607
  int 0x10

  jmp enter_protected

hallo: db 'xos boot loader stage 1 ...', 0xa, 0xd, 0

print:
  mov ah, 0x0e
.repeat:
  lodsb
  cmp al, 0
  je .done
  int 0x10
  jmp .repeat
.done:
  ret

enter_protected:
  cli
  lgdt [gdt_desc]

  mov eax, cr0
  or al, 1
  mov cr0, eax

  jmp 0x08:protected_main

detect_memory:
  mov di, [esp + 2] ; mmap base
  add di, 4 ; first dword reserved for count
  xor ebp, ebp ; valid entries counter

  xor ebx, ebx

  call .e820
  jc .failed

  ; first call checks:
  cmp eax, BIOS_MEMDETECT_MAGIC
  jne .failed
  test ebx, ebx
  je .failed

.item:
  jcxz .next
  cmp cl, 0x18 ; extended record?
  jb .normal
.extended:
  test [di + 20], byte 1 ; ignored
  je .next
.normal:
  mov ecx, [di + 8]
  or ecx, [di + 12] ; zero length?
  jz .next
  inc bp
  add di, 20

.next:
  test ebx, ebx
  je .finish
  call .e820
  jc .finish
  jmp .item

.failed:
  mov ebp, 0
.finish:
  mov di, [esp+2]
  mov [di], ebp
  ret

.e820
  mov eax, 0xe820
  mov edx, BIOS_MEMDETECT_MAGIC
  mov [di + 20], dword 1
  mov ecx, 24
  int 0x15
  ret

bits 32

protected_main:
  mov eax, 0x10
  mov ds, ax
  mov es, ax
  mov ss, ax
  mov eax, 0x8000
  mov esp, eax

  jmp boot2_main

; pread_sector(unit32_t lba, uint8_t *dest)
%define DRIVE_PORT_BASE 0x01f0
%define DRIVE_PORT(n) (DRIVE_PORT_BASE + n)

%macro PORT_OUTB 2
  mov dx, %1
  mov al, %2
  out dx, al
%endmacro

pread_sector:
  push ebp
  mov ebp, esp
  push edi

  mov ecx, 8
  mov dx, DRIVE_PORT(7)
  in al, dx
  in al, dx
  in al, dx
  in al, dx

  mov eax, [ebp + 8]
  shr eax, 24
  and eax, 0x0f
  or al, 0xe0
  PORT_OUTB DRIVE_PORT(6), al ; drive select MASTER | 4bits of LBA high

  mov ecx, 4
  mov dx, DRIVE_PORT(7)
.delay:
  in al, dx
  loop .delay

  ;PORT_OUTB DRIVE_PORT(1), 0x00 ; legacy
  PORT_OUTB DRIVE_PORT(2), 0x01 ; sector count

  mov eax, [ebp + 8]
  and eax, 0xff
  PORT_OUTB DRIVE_PORT(3), al ; LBA low
  mov eax, [ebp + 8]
  shr eax, 8
  and eax, 0xff
  PORT_OUTB DRIVE_PORT(4), al ; LBA mid
  mov eax, [ebp + 8]
  shr eax, 16
  and eax, 0xff
  PORT_OUTB DRIVE_PORT(5), al ; LBA high

  PORT_OUTB DRIVE_PORT(7), 0x20 ; PIO READ

  mov dx, DRIVE_PORT(7)
.wait_rdy:
  in al, dx
  and al, 0x80
  jnz .wait_rdy

  mov dx, DRIVE_PORT(0)
  mov edi, [ebp + 12]
  mov ecx, 0x80 ; 128 x 4 byte = 512 byte block
.read_loop:
  in eax, dx
  stosd
  loop .read_loop

  pop edi
  pop ebp
  ret

bits 16

gdt_desc:
  dw 0x1f
  dd gdt

gdt:

gdt_entry0: ; invalid
  .limit_low:   dw 0x42
  .base_low:    dw 0
  .base_middle: db 0
  .access:      db 0 ;b10011010
  .granularity: db 0 ;b11000000
  .base_high:   db 0

gdt_entry1: ; flat code
  .limit_low:   dw 0xffff
  .base_low:    dw 0
  .base_middle: db 0
  .access:      db 0b10011010
  .granularity: db 0b11001111
  .base_high:   db 0

gdt_entry2: ; flat data
  .limit_low:   dw 0xffff
  .base_low:    dw 0x0000
  .base_middle: db 0
  .access:      db 0b10010010
  .granularity: db 0b11001111
  .base_high:   db 0