This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / loaders / boot / boot.asm
1 ;
2 ; File:
3 ;                            boot.asm
4 ; Description:
5 ;                           DOS-C boot
6 ;
7 ;                       Copyright (c) 1997;                     
8 ;                           Svante Frey
9 ;                       All Rights Reserved
10 ;
11 ; This file is part of DOS-C.
12 ;
13 ; DOS-C is free software; you can redistribute it and/or
14 ; modify it under the terms of the GNU General Public License
15 ; as published by the Free Software Foundation; either version
16 ; 2, or (at your option) any later version.
17 ;
18 ; DOS-C is distributed in the hope that it will be useful, but
19 ; WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
21 ; the GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public
24 ; License along with DOS-C; see the file COPYING.  If not,
25 ; write to the Free Software Foundation, 675 Mass Ave,
26 ; Cambridge, MA 02139, USA.
27 ;
28 ; $Header$
29 ;       
30 ;          Rev 1.5   10 Jan 1997  4:58:06   patv
31 ;       Corrected copyright
32 ;       
33 ;          Rev 1.4   10 Jan 1997  4:52:50   patv
34 ;       Re-written to support C drive and eliminate restrictions on IPL.SYS
35 ;       
36 ;          Rev 1.3   29 Aug 1996 13:06:50   patv
37 ;       Bug fixes for v0.91b
38 ;       
39 ;          Rev 1.2   01 Sep 1995 17:56:44   patv
40 ;       First GPL release.
41 ;       
42 ;          Rev 1.1   30 Jul 1995 20:37:38   patv
43 ;       Initialized stack before use.
44 ;       
45 ;          Rev 1.0   02 Jul 1995 10:57:52   patv
46 ;       Initial revision.
47 ;
48
49 section .text
50
51                 org     0
52 Entry:          jmp     real_start
53
54 ;       bp is initialized to 7c00h
55 %define oem                  [bp+3]
56 %define bytesPerSector       [bp+0bh]
57 %define sectPerCluster       [bp+0dh]
58 %define resSectors           [bp+0eh]
59 %define nFats                [bp+10h]
60 %define nRootDir             [bp+11h]
61 %define nSectors             [bp+13h]
62 %define MID                  [bp+15h]
63 %define sectPerFat           [bp+16h]
64 %define sectPerTrack         [bp+18h]
65 %define nHeads               [bp+1ah]
66 %define nHidden              [bp+1ch]
67 %define nHidden_hi           [bp+1eh]
68 %define nSectorHuge          [bp+20h]
69 %define drive                [bp+24h]
70 %define extBoot              [bp+26h]
71 %define volid                [bp+27h]
72 %define vollabel             [bp+2bh]
73 %define filesys              36h
74
75 LOADSEG         equ     2000h
76
77 FATBUF          equ     4000h           ; offset of temporary buffer for FAT 
78                                         ; chain
79 RETRYCOUNT      equ     5               ; number of retries on disk errors
80
81 ;       Some extra variables that are created on the stack frame
82
83 %define fat_start       [bp-4]          ; first FAT sector
84 %define fat_start_hi    [bp-2]
85 %define root_dir_start  [bp-8]          ; first root directory sector
86 %define root_dir_start_hi [bp-6]
87 %define data_start      [bp-12]         ; first data sector
88 %define data_start_hi   [bp-10]
89
90 ;
91 ; Include macros for filesystem access
92 ;
93 %include "boot.inc"
94
95 ;
96 ;
97 ;
98                 TIMES 3eh-($-$$) DB 0
99
100 %define tempbuf         [bp+3eh]
101 load_seg        dw      LOADSEG
102
103 real_start:     cli
104                 cld
105                 mov     ax, cs
106                 mov     ss, ax          ; initialize stack      
107                 mov     bp, 7c00h
108                 lea     sp, [bp-20h]
109                 sti
110
111                 mov     es, ax
112                 mov     ds, ax
113                 mov     drive, dl       ; BIOS passes drive number in DL
114
115                 GETDRIVEPARMS
116
117                 FINDFILE                ; locate file in root directory
118                 jc      boot_error      ; fail if not found
119
120                 GETFATCHAIN             ; read FAT chain
121                 LOADFILE                ; load file (jumps to boot_sucess if successful)
122
123 boot_error:     mov     cx, ERRMSGLEN
124                 mov     si, errmsg+7c00h
125
126 next_char:      lodsb                   ; print error message
127                 mov     ah, 0eh
128                 xor     bh, bh
129                 int     10h
130                 loop    next_char
131
132                 xor     ah, ah
133                 int     16h             ; wait for keystroke
134                 int     19h             ; invoke bootstrap loader
135
136 boot_success:   mov     dl, drive
137
138                 db      0eah            ; far jump to LOADSEG:0000
139                 dw      0
140                 dw      LOADSEG
141
142
143 ;       readDisk:       Reads a number of sectors into memory.
144 ;
145 ;       Call with:      DX:AX = 32-bit DOS sector number
146 ;                       DI = number of sectors to read
147 ;                       ES:BX = destination buffer
148 ;                       ES must be 64k aligned (1000h, 2000h etc).
149 ;
150 ;       Returns:        CF set on error
151 ;                       ES:BX points one byte after the last byte read. 
152
153 readDisk:
154                 push    si
155 read_next:      push    dx
156                 push    ax
157
158                 ;
159                 ; translate sector number to BIOS parameters
160                 ;
161
162                 ;
163                 ; abs = sector                          offset in track
164                 ;     + head * sectPerTrack             offset in cylinder
165                 ;     + track * sectPerTrack * nHeads   offset in platter
166                 ; 
167                 ; t1     = abs  /  sectPerTrack         (ax has t1)
168                 ; sector = abs mod sectPerTrack         (cx has sector)
169                 ;
170                 div     word sectPerTrack
171                 mov     cx, dx
172
173                 ;
174                 ; t1   = head + track * nHeads
175                 ;
176                 ; track = t1  /  nHeads                 (ax has track)
177                 ; head  = t1 mod nHeads                 (dl has head)
178                 ;
179                 xor     dx, dx
180                 div     word nHeads
181
182                 ; the following manipulations are necessary in order to 
183                 ; properly place parameters into registers.
184                 ; ch = cylinder number low 8 bits
185                 ; cl = 7-6: cylinder high two bits
186                 ;      5-0: sector
187                 mov     dh, dl                  ; save head into dh for bios
188                 ror     ah, 1                   ; move track high bits into
189                 ror     ah, 1                   ; bits 7-6 (assumes top = 0)
190                 xchg    al, ah                  ; swap for later
191                 mov     dl, byte sectPerTrack
192                 sub     dl, cl
193                 inc     cl                      ; sector offset from 1
194                 or      cx, ax                  ; merge cylinder into sector
195                 mov     al, dl                  ; al has # of sectors left
196
197                 ; Calculate how many sectors can be transfered in this read
198                 ; due to dma boundary conditions.
199                 push    dx
200
201                 mov     si, di                  ; temp register save
202                 ; this computes remaining bytes because of modulo 65536
203                 ; nature of dma boundary condition
204                 mov     ax, bx                  ; get offset pointer
205                 neg     ax                      ; and convert to bytes
206                 jz      ax_min_1                ; started at seg:0, skip ahead
207
208                 xor     dx, dx                  ; convert to sectors
209                 div     word bytesPerSector
210                 
211                 cmp     ax, di                  ; check remainder vs. asked
212                 jb      ax_min_1                ; less, skip ahead
213                 mov     si, ax                  ; transfer only what we can
214
215 ax_min_1:       pop     dx
216
217                 ; Check that request sectors do not exceed track boundary
218                 mov     si, sectPerTrack
219                 inc     si
220                 mov     ax, cx                  ; get the sector/cyl byte
221                 and     ax, 03fh                ; and mask out sector
222                 sub     si, ax                  ; si has how many we can read
223                 mov     ax, di
224                 cmp     si, di                  ; see if asked <= available
225                 jge     ax_min_2
226                 mov     ax, si                  ; get what can be xfered
227
228 ax_min_2:       mov     si, RETRYCOUNT
229                 mov     ah, 2
230                 mov     dl, drive
231
232 retry:          push    ax
233                 int     13h
234                 pop     ax
235                 jnc     read_ok
236                 push    ax
237                 xor     ax, ax          ; reset the drive
238                 int     13h
239                 pop     ax
240                 dec     si
241                 jnz     retry
242                 stc
243                 pop     ax
244                 pop     dx
245                 pop     si
246                 ret
247
248 read_next_jmp:  jmp     short read_next
249 read_ok:        xor     ah, ah                          
250                 mov     si, ax                  ; AX = SI = number of sectors read      
251                 mul     word bytesPerSector ; AX = number of bytes read
252                 add     bx, ax                  ; add number of bytes read to BX
253                 jnc     no_incr_es              ; if overflow...
254
255                 mov     ax, es       
256                 add     ah, 10h                 ; ...add 1000h to ES
257                 mov     es, ax
258                 
259 no_incr_es:     pop     ax
260                 pop     dx                      ; DX:AX = last sector number
261
262                 add     ax, si
263                 adc     dx, 0                   ; DX:AX = next sector to read
264                 sub     di, si                  ; if there is anything left to read,
265                 jg      read_next_jmp           ; continue
266
267                 clc
268                 pop     si
269                 ret
270
271 errmsg          db      "Boot error"
272 ERRMSGLEN       equ     $ - errmsg
273
274
275 ;filename        db      "OSLDR   BIN"
276 filename        db      "KERNEL  BIN"
277
278                 TIMES 510-($-$$) DB 0 
279 sign            dw      0aa55h
280                 
281