-
Notifications
You must be signed in to change notification settings - Fork 3
/
bootloader.asm
142 lines (104 loc) · 3.05 KB
/
bootloader.asm
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
; compile with nasm, use as disk image to qemu-system-i386
[BITS 16]
[ORG 0x7c00]
BOOT_DRIVE equ $
entry:
cli ; disable interrupts
jmp 0x0000:start ; set CS:IP to known values
lba dw 0 ; starting sector LBA=0 (incl. boot sector)
retries db 10 ; max 10 retries until fail
banner db 10, "SP/OS (2013) Saul Pwanson", 13, 10, 0
start:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00 ; just before the code
mov [BOOT_DRIVE], dl ; save off boot drive
mov di, banner
call writestr
mov si, 0x7000 ; drive parameters buffer
%define NUM_CYLINDERS word [si+0x04] ; dword [0x7004]
%define NUM_HEADS word [si+0x08] ; dword [0x7008]
%define SECTOR_PER_TRACK word [si+0x0c] ; dword [0x700C]
; %define TOTAL_SECTORS word [si+0x10] ; qword [0x7010]
; %define PARA_PER_SECTOR word [si+0x18] ; word [0x7018] (in bytes at first)
mov dl, [BOOT_DRIVE]
mov ah, 0x08
int 0x13
jnc parmsok
mov al, '&'
call putc
hlt
parmsok:
; set up parameters for LBAtoCHS
;;; unnecessary
; push cx
; shr cx, 6
; mov NUM_CYLINDERS, cx ; max value of cylinder
; pop cx
and cx, 0x3f ; mask off lower two bits of cylinder
mov SECTOR_PER_TRACK, cx ; max value of sector
shr dx, 8 ; dx = dh (# heads)
inc dx
mov NUM_HEADS, dx
mov cx, 64 ; read inital 32k
mov di, 0x8000
sub cx, [lba] ; # sectors to read = total sectors - 1 boot sector
nextsector:
mov ax, [lba]
push cx
xor dx, dx ; DX:AX = LBA
mov bx, SECTOR_PER_TRACK ; BX = SectorsPerTrack
mov cx, NUM_HEADS ; CX = NumHeads
; in: DX:AX=LBA Sector, BX=SectorsPerTrack, CX = NumHeads
; out: DH, CX compatible with int 13h/02
LBAtoCHS:
div bx ; ax = LBA/SectorsPerTrack = track# * head#
inc dx ; dx = remainder+1 = sector#
push dx
xor dx, dx ; dx:ax = track# * head#
div cx ; ax = track#, dx = head#
mov dh, dl ; dh = head#
pop cx ; cl[5:0] = sector#
mov ch, al ; ch = low 8 bits of track#
shl ah, 6
or cl, ah ; cl[7:6] = high bits of track#
mov dl, [BOOT_DRIVE]
mov bx, di ; ES:BX = dest address for load
mov ax, 0x0201 ; function 13h/02, read 01 sectors
int 0x13
jnc success
mov al, '!'
call putc
; DEBUG: print ah for error code
call resetdisk
pop cx
dec byte [retries]
jnz nextsector
mov al, '<'
call putc
; might be an odd-shaped disk, let's jump anyway
jmp leap
; dl = boot drive
resetdisk:
xor ax, ax
int 0x13 ; 13h/00 = reset drive
jc resetdisk
ret
success:
%ifdef DEBUG
mov al, '.'
call putc
%endif
add di, 512
pop cx
inc word [lba]
loop nextsector
%ifdef DEBUG
mov al, '>'
call putc
%endif
%include "bootcommon.asm"
times (512 - $ + entry - 2) db 0 ; pad boot sector with zeroes
db 0x55, 0xAA ; 2 byte boot signature