:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / loaders / boot / osldr.asm
1 ;
2 ; Loads the kernel and any required modules
3 ;
4
5 org 0
6
7 ;
8 ; Segment where we are loaded
9 ;
10 LOADSEG equ 02000h
11
12 ;
13 ; Segment used for temporay storage
14 ;
15 WORKSEG equ 01000h
16
17
18 KERNELBASE equ 05000h
19
20 ;
21 ; Offsets of work areas
22 ;
23 FAT_CHAIN equ 0h
24
25 DIR_BUFFER equ 4000h
26 END_DIR_BUFFER equ 0ffe0h
27
28 FAT_SEG equ 03000h
29
30
31 ;
32 ; These are all on the stack
33 ;
34 %define oem                  [bp+3]
35 %define bytesPerSector       [bp+0bh]
36 %define sectPerCluster       [bp+0dh]
37 %define resSectors           [bp+0eh]
38 %define nFats                [bp+10h]
39 %define nRootDir             [bp+11h]
40 %define nSectors             [bp+13h]
41 %define MID                  [bp+15h]
42 %define sectPerFat           [bp+16h]
43 %define sectPerTrack         [bp+18h]
44 %define nHeads               [bp+1ah]
45 %define nHidden              [bp+1ch]
46 %define nHidden_hi           [bp+1eh]
47 %define nSectorHuge          [bp+20h]
48 %define drive                [bp+24h]
49 %define extBoot              [bp+26h]
50 %define volid                [bp+27h]
51 %define vollabel             [bp+2bh]
52 %define filesys              36h
53
54 RETRYCOUNT equ 5
55
56 %define fat_start       [bp-4]          ; first FAT sector
57 %define fat_start_hi    [bp-2]
58 %define root_dir_start  [bp-8]          ; first root directory sector
59 %define root_dir_start_hi [bp-6]
60 %define data_start      [bp-12]         ; first data sector
61 %define data_start_hi   [bp-10]
62
63
64 entry:
65         mov     drive,dl
66         
67         mov     ax,LOADSEG
68         mov     ds,ax
69
70
71         ;
72         ; Print out a message
73         ;
74         mov     di,loadmsg
75         call    printmsg
76
77
78         ;
79         ; Check here for shift pressed and if so display boot menu
80         ;
81
82         ;
83         ; Load the entire fat
84         ;
85 ;        mov     ax,fat_start
86 ;        mov     dx,fat_start_hi
87 ;        mov     di,sectPerFat
88 ;        mov     ax,FAT_SEG
89 ;        mov     es,ax
90 ;        mov     bx,0
91 ;        call    readDisk
92
93
94         ;
95         ; Load root directory
96         ;
97         mov     ax,WORKSEG
98         mov     es,ax
99
100         mov     dx,root_dir_start_hi
101         mov     ax,root_dir_start
102         mov     bx,DIR_BUFFER
103         mov     di,nRootDir
104         shr     di,4
105         mov     di,1
106         call    readDisk
107         jc      disk_error
108
109         ;
110         ; Look for a directory called boot
111         ;        
112         mov     di,DIR_BUFFER
113         cld
114         mov     cx,4
115 l1:
116         mov     si,boot_dir_name
117 ;        cmp     byte [di],0
118 ;        je      boot_error
119         repe    cmpsb
120         je      found_it
121         or      di,31
122         inc     di
123         cmp     di,END_DIR_BUFFER
124         jge     boot_error
125         jmp     l1
126
127
128 boot_error:
129         mov     di,errormsg
130         call    printmsg
131 l3:
132         jmp     l3
133
134 disk_error:
135         mov     di,errormsg1
136         call    printmsg
137         jmp     l3
138
139
140
141 found_it:
142         mov     di,msg1
143         call    printmsg
144
145         ;
146         ; Load the boot directory found above
147         ;
148         sub     di,4
149         call    readFile
150
151 l2:
152         jmp     l2
153
154 ;
155 ; readFile
156 ;
157 %define file_length [di+01ch]
158 %define start_cluster [di+01ah]
159 readFile:
160         cmp     byte  extBoot, 29h
161         jne     fat_12
162         cmp     byte  [bp+filesys+4], '6'  ; check for FAT-16 system
163         je      fat_16
164
165 fat_12:
166         mov     di,msg2
167         call    printmsg
168 l4:
169         jmp l4
170
171 fat_16:
172         mov     di,msg3
173         call    printmsg
174         jmp     l4
175         
176         
177
178 ;       readDisk:       Reads a number of sectors into memory.
179 ;
180 ;       Call with:      DX:AX = 32-bit DOS sector number
181 ;                       DI = number of sectors to read
182 ;                       ES:BX = destination buffer
183 ;                       ES must be 64k aligned (1000h, 2000h etc).
184 ;
185 ;       Returns:        CF set on error
186 ;                       ES:BX points one byte after the last byte read. 
187
188 readDisk:
189                 push    bp
190                 push    si
191 read_next:      push    dx
192                 push    ax
193
194                 ;
195                 ; translate sector number to BIOS parameters
196                 ;
197
198                 ;
199                 ; abs = sector                          offset in track
200                 ;     + head * sectPerTrack             offset in cylinder
201                 ;     + track * sectPerTrack * nHeads   offset in platter
202                 ; 
203                 ; t1     = abs  /  sectPerTrack         (ax has t1)
204                 ; sector = abs mod sectPerTrack         (cx has sector)
205                 ;
206                 div     word sectPerTrack
207                 mov     cx, dx
208
209                 ;
210                 ; t1   = head + track * nHeads
211                 ;
212                 ; track = t1  /  nHeads                 (ax has track)
213                 ; head  = t1 mod nHeads                 (dl has head)
214                 ;
215                 xor     dx, dx
216                 div     word nHeads
217
218                 ; the following manipulations are necessary in order to 
219                 ; properly place parameters into registers.
220                 ; ch = cylinder number low 8 bits
221                 ; cl = 7-6: cylinder high two bits
222                 ;      5-0: sector
223                 mov     dh, dl                  ; save head into dh for bios
224                 ror     ah, 1                   ; move track high bits into
225                 ror     ah, 1                   ; bits 7-6 (assumes top = 0)
226                 xchg    al, ah                  ; swap for later
227                 mov     dl, byte sectPerTrack
228                 sub     dl, cl
229                 inc     cl                      ; sector offset from 1
230                 or      cx, ax                  ; merge cylinder into sector
231                 mov     al, dl                  ; al has # of sectors left
232
233                 ; Calculate how many sectors can be transfered in this read
234                 ; due to dma boundary conditions.
235                 push    dx
236
237                 mov     si, di                  ; temp register save
238                 ; this computes remaining bytes because of modulo 65536
239                 ; nature of dma boundary condition
240                 mov     ax, bx                  ; get offset pointer
241                 neg     ax                      ; and convert to bytes
242                 jz      ax_min_1                ; started at seg:0, skip ahead
243
244                 xor     dx, dx                  ; convert to sectors
245                 div     word bytesPerSector
246                 
247                 cmp     ax, di                  ; check remainder vs. asked
248                 jb      ax_min_1                ; less, skip ahead
249                 mov     si, ax                  ; transfer only what we can
250
251 ax_min_1:       pop     dx
252
253                 ; Check that request sectors do not exceed track boundary
254                 mov     si, sectPerTrack
255                 inc     si
256                 mov     ax, cx                  ; get the sector/cyl byte
257                 and     ax, 03fh                ; and mask out sector
258                 sub     si, ax                  ; si has how many we can read
259                 mov     ax, di
260                 cmp     si, di                  ; see if asked <= available
261                 jge     ax_min_2
262                 mov     ax, si                  ; get what can be xfered
263
264 ax_min_2:       mov     si, RETRYCOUNT
265                 mov     ah, 2
266                 mov     dl, drive
267
268 retry:          push    ax
269                 int     13h
270                 pop     ax
271                 jnc     read_ok
272                 push    ax
273                 xor     ax, ax          ; reset the drive
274                 int     13h
275                 pop     ax
276                 dec     si
277                 jnz     retry
278                 stc
279                 pop     ax
280                 pop     dx
281                 pop     si
282                 pop     bp
283                 ret
284
285 read_next_jmp:  jmp     short read_next
286 read_ok:        xor     ah, ah                          
287                 mov     si, ax                  ; AX = SI = number of sectors read      
288                 mul     word bytesPerSector ; AX = number of bytes read
289                 add     bx, ax                  ; add number of bytes read to BX
290                 jnc     no_incr_es              ; if overflow...
291
292                 mov     ax, es       
293                 add     ah, 10h                 ; ...add 1000h to ES
294                 mov     es, ax
295                 
296 no_incr_es:     pop     ax
297                 pop     dx                      ; DX:AX = last sector number
298
299                 add     ax, si
300                 adc     dx, 0                   ; DX:AX = next sector to read
301                 sub     di, si                  ; if there is anything left to read,
302                 jg      read_next_jmp           ; continue
303
304                 clc
305                 pop     si
306                 pop     bp
307                 ret
308
309 ;
310 ; Print string (DI = start) 
311 ;
312 printmsg:
313         push    ax
314         push    bx
315         push    di
316         mov     ah,0eh
317         mov     bh,0
318         mov     bl,07h
319 .l1
320         mov     al,[di]
321         cmp     al,0
322         je      .l2
323         inc     di
324         int     10h
325         jmp     .l1
326 .l2
327         pop     di
328         pop     bx
329         pop     ax
330         ret
331
332
333
334 loadmsg db "Starting ReactOS...",0xd,0xa,0
335 boot_dir_name db 'BOOT'
336 errormsg db "Files missing on boot disk",0
337 errormsg1 db "Disk read error",0
338 msg1 db "Found boot directory",0xd,0xa,0
339 msg2 db 'FAT12',0
340 msg3 db 'FAT16',0