* add p cc
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / pure64.boot0 / bootsector / boot16b.asm
blob47ec2ce94f99b59c4a922b0f6ea3611914319fce
1 USE16
2 org 0x7C00
4 entry:
5 jmp short begin
6 nop
8 %define bsOemName bp+0x03 ; OEM label (8)
9 %define bsBytesPerSec bp+0x0B ; bytes/sector (dw)
10 %define bsSecsPerClust bp+0x0D ; sectors/allocation unit (db)
11 %define bsResSectors bp+0x0E ; # reserved sectors (dw)
12 %define bsFATs bp+0x10 ; # of fats (db)
13 %define bsRootDirEnts bp+0x11 ; Max # of root dir entries (dw)
14 %define bsSectors bp+0x13 ; # sectors total in image (dw)
15 %define bsMedia bp+0x15 ; media descriptor (db)
16 %define bsSecsPerFat bp+0x16 ; # sectors in a fat (dw)
17 %define bsSecsPerTrack bp+0x18 ; # sectors/track
18 %define bsHeads bp+0x1A ; # heads (dw)
19 %define bsHidden bp+0x1C ; # hidden sectors (dd)
20 %define bsSectorHuge bp+0x20 ; # sectors if > 65536 (dd)
21 %define bsDriveNumber bp+0x24 ; (dw)
22 %define bsSigniture bp+0x26 ; (db)
23 %define bsVolumeSerial bp+0x27 ; (dd)
24 %define bsVolumeLabel bp+0x2B ; (11)
25 %define bsSysID bp+0x36 ; (8)
27 times 0x3B db 0 ; Code starts at offset 0x3E
29 begin:
30 mov [bsDriveNumber], dl ; BIOS passes drive number in DL
31 xor eax, eax
32 xor esi, esi
33 xor edi, edi
34 mov ds, ax
35 mov es, ax
36 mov bp, 0x7c00
38 ; Make sure the screen is set to 80x25 color text mode
39 mov ax, 0x0003 ; Set to normal (80x25 text) video mode
40 int 0x10
42 ; Print message
43 mov si, msg_Load
44 call print_string_16
46 ; read in the root cluster
47 ; check for the filename
48 ; if found save the starting cluster
49 ; if not then error
51 ;fatstart = bsResSectors
53 ;rootcluster = bsResSectors + (bsFATs * bsSecsPerFat)
54 ; 4 + (2 * 254) = sector 512
56 ;datastart = bsResSectors + (bsFATs * bsSecsPerFat) + ((bsRootDirEnts * 32) / bsBytesPerSec)
57 ; 4 + (2 * 254) + ((512 * 32) / 512) = sector 544
59 ;cluster X starting sector
60 ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart
62 ; 0x7C5C as of Jan 6, 2010
63 getoffset:
64 xor eax, eax
65 mov bx, 0x8000
66 call readsector ; Read the MBR to 0x8000
67 mov eax, [0x81C6] ; Grab the dword at 0x01C6 (num of sectors between MBR and first sector in partition)
68 mov [secoffset], eax ; Save it for later use
69 xor eax, eax
71 ff:
72 mov ax, [bsSecsPerFat]
73 shl ax, 1 ; quick multiply by two
74 add ax, [bsResSectors]
75 mov [rootstart], ax
77 mov bx, [bsRootDirEnts]
78 shr bx, 4 ; bx = (bx * 32) / 512
79 add bx, ax ; BX now holds the datastart sector number
80 mov [datastart], bx
82 ff_next_sector:
83 mov bx, 0x8000
84 mov si, bx
85 mov di, bx
86 add eax, [secoffset]
87 call readsector
89 ; Search for file name, and find start cluster.
90 ff_next_entry:
91 mov cx, 11
92 mov si, filename
93 repe cmpsb
94 jz ff_done ; note that di now is at dirent+11
96 add di, byte 0x20
97 and di, byte -0x20
98 cmp di, [bsBytesPerSec]
99 jnz ff_next_entry
100 ; load next sector
101 dec dx ; next sector in cluster
102 jnz ff_next_sector
104 ff_done:
105 add di, 15
106 mov ax, [di] ; AX now holds the starting cluster #
108 ; At this point we have found the file we want and know the cluster where the file starts
110 mov bx, 0x8000 ; We want to load to 0x0000:0x8000
111 loadfile:
112 call readcluster
113 cmp ax, 0xFFF8 ; Have we reached the end cluster marker?
114 jg loadfile ; If not then load another
116 jmp 0x0000:0x8000
120 ;------------------------------------------------------------------------------
121 ; Read a sector from a disk, using LBA
122 ; input: EAX - 32-bit DOS sector number
123 ; ES:BX - destination buffer
124 ; output: ES:BX points one byte after the last byte read
125 ; EAX - next sector
126 readsector:
127 push dx
128 push si
129 push di
131 read_it:
132 push eax ; Save the sector number
133 mov di, sp ; remember parameter block end
135 push byte 0 ; other half of the 32 bits at [C]
136 push byte 0 ; [C] sector number high 32bit
137 push eax ; [8] sector number low 32bit
138 push es ; [6] buffer segment
139 push bx ; [4] buffer offset
140 push byte 1 ; [2] 1 sector (word)
141 push byte 16 ; [0] size of parameter block (word)
143 mov si, sp
144 mov dl, [bsDriveNumber]
145 mov ah, 42h ; EXTENDED READ
146 int 0x13 ; http://hdebruijn.soo.dto.tudelft.nl/newpage/interupt/out-0700.htm#0651
148 mov sp, di ; remove parameter block from stack
149 pop eax ; Restore the sector number
151 jnc read_ok ; jump if no error
153 push ax
154 xor ah, ah ; else, reset and retry
155 int 0x13
156 pop ax
157 jmp read_it
159 read_ok:
160 inc eax ; next sector
161 add bx, 512 ; Add bytes per sector
162 jnc no_incr_es ; if overflow...
164 incr_es:
165 mov dx, es
166 add dh, 0x10 ; ...add 1000h to ES
167 mov es, dx
169 no_incr_es:
170 pop di
171 pop si
172 pop dx
174 ;------------------------------------------------------------------------------
177 ;------------------------------------------------------------------------------
178 ; Read a cluster from a disk partition, using LBA
179 ; input: AX - 16-bit cluster number
180 ; ES:BX - destination buffer
181 ; output: ES:BX points one byte after the last byte read
182 ; AX - next cluster
183 readcluster:
184 push cx
185 mov [tcluster], ax ; save our cluster value
186 ;cluster X starting sector
187 ; starting sector = (bsSecsPerClust * (cluster# - 2)) + datastart
188 xor cx, cx
189 sub ax, 2
190 mov cl, byte [bsSecsPerClust]
191 imul cx ; EAX now holds starting sector
192 add ax, word [datastart] ; add the datastart offset
194 xor cx, cx
195 mov cl, byte [bsSecsPerClust]
196 add eax, [secoffset]
197 readcluster_nextsector:
198 call readsector
199 dec cx
200 cmp cx, 0
201 jne readcluster_nextsector
203 ; Great! We read a cluster.. now find out where the next cluster is
204 push bx ; save our memory pointer
205 mov bx, 0x7E00 ; load a sector from the root cluster here
206 push bx
207 mov ax, [bsResSectors]
208 add eax, [secoffset]
209 call readsector
210 pop bx ; bx points to 0x7e00 again
211 mov ax, [tcluster] ; ax holds the cluster # we just read
212 shl ax, 1 ; multipy by 2
213 add bx, ax
214 mov ax, [bx]
216 pop bx ; restore our memory pointer
217 pop cx
220 ;------------------------------------------------------------------------------
223 ;------------------------------------------------------------------------------
224 ; 16-bit Function to print a sting to the screen
225 ; input: SI - Address of start of string
226 print_string_16: ; Output string in SI to screen
227 pusha
228 mov ah, 0x0E ; int 0x10 teletype function
229 .repeat:
230 lodsb ; Get char from string
231 cmp al, 0
232 je .done ; If char is zero, end of string
233 int 0x10 ; Otherwise, print it
234 jmp short .repeat
235 .done:
236 popa
238 ;------------------------------------------------------------------------------
241 msg_Load db "Loading... ", 0
242 msg_Error db "No "
243 filename db "PURE64 SYS", 0
244 datastart dw 0x0000
245 rootstart dw 0x0000
246 tcluster dw 0x0000
247 secoffset dd 0x00000000
249 times 510-$+$$ db 0
251 sign dw 0xAA55