summaryrefslogtreecommitdiff
path: root/boot/bios.inc
blob: eede41e46c132b7a282304e2b664a87e45b0e7a8 (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
macro bios_a20_enable {
	mov ax, 0x2401
	int 0x15
}

macro bios_vga_write_mode_3 {
	mov ax, 0x03
	int 0x10
}

; assumes dl = drive number
macro bios_disk_read dst*, cyl*, head*, sector*, count*, err_label* {
	local read_disk

	assert 0 <= cyl    & cyl    <= 1023
	assert 0 <= head   & head   <= 15
	assert 1 <= sector & sector <= 17
	assert 1 <= count  & count  <= 128

	; try to read disk up to 3 times
	mov di, 3

read_disk:
	; ah = 0x02, al = number of sectors to read
	mov ax, (0x0200 or count)

	; es:bx = pointer to destination buffer
	if dst = 0
		xor bx, bx
	else
		mov bx, dst
	end if

	; ch = track/cylinder number, cl = sector number
	mov cx, ((cyl and 0xff) shl 8) or ((cyl and 0x300) shl 6) or sector

	; dh = head number
	if head = 0
		xor dh, dh
	else
		mov dh, head
	end if

	int 0x13

	jc .error
	cmp ax, count
	jne .error

	jmp .exit
.error:
	dec di
	jz err_label

	; reset disk on error
	xor ah, ah
	stc
	int 0x13
	jc err_label
	jmp read_disk
.exit:
}

macro bios_e820_mmap mmap*, err_label* {
	local e820, e820_entry
e820:
	virtual at di
		label e820_entry
		.base     dq ?
		.length   dq ?
		.type     dd ?
		.ext_attr dd ?
		.sizeof = $ - e820_entry
	end virtual

	mov di, mmap + 8
	xor ebx, ebx
	xor bp, bp

	mov edx, 0x0534d4150
	mov eax, 0xe820
	mov byte [.ext_attr], 0x01
	mov ecx, .sizeof
	int 0x15
	jc err_label

	mov edx, 0x0534d4150
	cmp eax, edx
	jne err_label

	test ebx, ebx
	jz err_label

	jmp @f

.e820_loop:
	mov ax, 0xe820
	mov byte [.ext_attr], 0x01
	mov ecx, .sizeof
	int 0x15
	jc err_label

	mov edx, 0x0534d4150
@@:
	jcxz .skip_entry

	; ACPI < 3.0
	cmp cl, (.sizeof-4)
	jbe .not_ext

	; ignore data flag
	test byte [.ext_attr], 0x01
	jz .skip_entry

.not_ext:
	mov ecx, dword [.length]
	or ecx, dword [.length + 4]
	jz .skip_entry

	inc bp
	add di, .sizeof
.skip_entry:
	test ebx, ebx
	jnz .e820_loop

	; store e820 mmap entry count at beginning
	mov [mmap], bp
}