Enabled FASTCALL calling convention
[reactos.git] / freeldr / bootsect / BOOTSECT.ASM
1 ; BOOTSECT.ASM
2 ; FAT12/16 Boot Sector
3 ; Copyright (c) 1998 Brian Palmer
4
5 org 7c00h
6
7 segment .text
8
9 bits 16
10
11 start:
12 jmp short main
13 nop
14
15 OEMName db 'FreeLDR!'
16 BytesPerSector dw 512
17 SectsPerCluster db 1
18 ReservedSectors dw 1
19 NumberOfFats db 2
20 MaxRootEntries dw 224
21 TotalSectors dw 2880
22 MediaDescriptor db 0f0h
23 SectorsPerFat dw 9
24 SectorsPerTrack dw 18
25 NumberOfHeads dw 2
26 HiddenSectors dd 0
27 TotalSectorsBig dd 0
28 BootDrive db 0
29 Reserved db 0
30 ExtendSig db 29h
31 SerialNumber dd 00000000h
32 VolumeLabel db 'FreeLoader!'
33 FileSystem db 'FAT12 '
34
35 main:
36 cli
37 cld
38 xor ax,ax
39 mov ss,ax
40 mov sp,7c00h ; Setup a stack
41 mov ax,cs ; Setup segment registers
42 mov ds,ax ; Make DS correct
43 mov es,ax ; Make ES correct
44
45
46 sti ; Enable ints now
47 mov [BootDrive],dl ; Save the boot drive
48 xor ax,ax ; Zero out AX
49
50 ; Reset disk controller
51 int 13h
52 jnc Continue1
53 jmp BadBoot ; Reset failed...
54
55 Continue1:
56 ; Now we must find our way to the first sector of the root directory
57 xor ax,ax
58 xor cx,cx
59 mov al,[NumberOfFats] ; Number of fats
60 mul WORD [SectorsPerFat] ; Times sectors per fat
61 add ax,WORD [HiddenSectors]
62 adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors
63 add ax,[ReservedSectors] ; Add the number of reserved sectors
64 adc dx,cx ; Add carry bit
65 push ax ; Store it on the stack
66 push dx ; Save 32-bit logical start sector
67 push ax
68 push dx ; Save it for later use also
69 ; DX:AX now has the number of the starting sector of the root directory
70
71 ; Now calculate the size of the root directory
72 mov ax,0020h ; Size of dir entry
73 mul WORD [MaxRootEntries] ; Times the number of entries
74 mov bx,[BytesPerSector]
75 add ax,bx
76 dec ax
77 div bx ; Divided by the size of a sector
78 ; AX now has the number of root directory sectors
79
80 xchg ax,cx ; Now CX has number of sectors
81 pop dx
82 pop ax ; Restore logical sector start
83 push cx ; Save for later use
84 mov bx,7c0h ; We will load the root directory
85 add bx,20h ; Right after the boot sector in memory
86 mov es,bx
87 xor bx,bx ; We will load it to [0000:7e00h]
88 call ReadSectors ; Read the sectors
89 jnc Continue2 ; BadBoot on error
90 jmp BadBoot
91 Continue2:
92
93
94 ; Now we have to find our way through the root directory to
95 ; The OSLOADER.SYS file
96 mov bx,[MaxRootEntries]; Search entire root directory
97 mov ax,7e0h ; We loaded at 07e0:0000
98 mov es,ax
99 xor di,di
100 mov si,filename
101 mov cx,11
102 rep cmpsb ; Compare filenames
103 jz FoundFile ; If same we found it
104 dec bx
105 jnz FindFile
106 jmp ErrBoot
107
108 FindFile:
109 mov ax,es ; We didn't find it in the previous dir entry
110 add ax,2 ; So lets move to the next one
111 mov es,ax ; And search again
112 xor di,di
113 mov si,filename
114 mov cx,11
115 rep cmpsb ; Compare filenames
116 jz FoundFile ; If same we found it
117 dec bx ; Keep searching till we run out of dir entries
118 jnz FindFile ; Last entry?
119 jmp ErrBoot
120
121 FoundFile:
122 xor di,di ; ES:DI has dir entry
123 xor dx,dx
124 mov ax,WORD [es:di+1ah] ; Get start cluster
125 dec ax
126 dec ax
127 xor ch,ch
128 mov cl,BYTE [SectsPerCluster] ; Times sectors per cluster
129 mul cx
130 pop cx ; Get number of sectors for root dir
131 add ax,cx
132 adc dx,0
133 pop cx ; Get logical start sector of
134 pop bx ; Root directory
135 add ax,bx ; Now we have DX:AX with the logical start
136 adc dx,cx ; Sector of OSLOADER.SYS
137 push ax
138 push dx
139 mov ax,WORD [es:di+1ch]
140 mov dx,WORD [es:di+1eh]
141 mov bx,[BytesPerSector]
142 dec bx
143 add ax,bx
144 adc dx,0
145 div WORD [BytesPerSector]
146 xchg ax,cx ; Now CX has number of sectors of OSLOADER.SYS
147 pop dx
148 pop ax
149 mov bx,800h
150 mov es,bx
151 xor bx,bx ; Load ROSLDR at 0000:8000h
152 call ReadSectors ; Load it
153 jc BadBoot
154 mov dl,[BootDrive]
155 xor ax,ax
156 push ax
157 mov ax,8000h
158 push ax ; We will do a far return to 0000:8000h
159 retf ; Transfer control to ROSLDR
160
161
162
163 ; Reads logical sectors into [ES:BX]
164 ; DX:AX has logical sector number to read
165 ; CX has number of sectors to read
166 ; CarryFlag set on error
167 ReadSectors:
168 push ax
169 push dx
170 push cx
171 xchg ax,cx
172 xchg ax,dx
173 xor dx,dx
174 div WORD [SectorsPerTrack]
175 xchg ax,cx
176 div WORD [SectorsPerTrack] ; Divide logical by SectorsPerTrack
177 inc dx ; Sectors numbering starts at 1 not 0
178 xchg cx,dx
179 div WORD [NumberOfHeads] ; Number of heads
180 mov dh,dl ; Head to DH, drive to DL
181 mov dl,[BootDrive] ; Drive number
182 mov ch,al ; Cylinder in CX
183 ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
184 ror ah,1 ; in CL shifted to bits 6 & 7
185 or cl,ah ; Or with sector number
186 mov ax,513
187 int 13h ; DISK - READ SECTORS INTO MEMORY
188 ; AL = number of sectors to read, CH = track, CL = sector
189 ; DH = head, DL = drive, ES:BX -> buffer to fill
190 ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
191 pop cx
192 pop dx
193 pop ax
194 jc ReadFail
195 inc ax ;Increment Sector to Read
196 jnz NoCarry
197 inc dx
198
199
200 NoCarry:
201 push bx
202 mov bx,es
203 add bx,20h
204 mov es,bx
205 pop bx
206 ; Increment read buffer for next sector
207 loop ReadSectors ; Read next sector
208
209
210 ReadFail:
211 ret
212
213
214
215 ; Displays a bad boot message
216 ; And reboots
217 BadBoot:
218 mov si,msgDiskError ; Bad boot disk message
219 call PutChars ; Display it
220 mov si,msgAnyKey ; Press any key message
221 call PutChars ; Display it
222
223 jmp Reboot
224
225 ; Displays an error message
226 ; And reboots
227 ErrBoot:
228 mov si,msgFreeLdr ; FreeLdr not found message
229 call PutChars ; Display it
230 mov si,msgAnyKey ; Press any key message
231 call PutChars ; Display it
232
233 Reboot:
234 xor ax,ax
235 int 16h ; Wait for a keypress
236 int 19h ; Reboot
237
238 PutChars:
239 lodsb
240 or al,al
241 jz short Done
242 mov ah,0eh
243 mov bx,07h
244 int 10h
245 jmp short PutChars
246 Done:
247 retn
248
249 msgDiskError db 'Disk error',0dh,0ah,0
250 msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
251 msgAnyKey db 'Press any key to continue.',0dh,0ah,0
252 filename db 'FREELDR SYS'
253
254 times 510-($-$$) db 0 ; Pad to 510 bytes
255 dw 0aa55h ; BootSector signature
256