:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / loaders / boot / boot.inc
1 ;       To save space, functions that are just called once are 
2 ;       implemented as macros instead. Four bytes are saved by
3 ;       avoiding the call / ret instructions.
4
5
6 ;       FINDFILE: Searches for the file in the root directory.
7 ;
8 ;       Returns:
9 ;
10 ;       If file not found:      CF set
11 ;       
12 ;       If file found:          CF clear
13 ;                               AX = first cluster of file
14
15
16 %macro FINDFILE 0      
17                 ; First, read the whole root directory
18                 ; into the temporary buffer.
19
20                 mov     ax, word  root_dir_start
21                 mov     dx, word  root_dir_start_hi
22                 mov     di, nRootDir
23                 xor     bx, bx
24                 mov     es, tempbuf
25                 call    readDisk
26                 jc      ffDone
27
28                 xor     di, di
29
30 next_entry:     mov     cx, 11
31                 mov     si, filename+7c00h
32                 push    di
33                 repe    cmpsb
34                 pop     di
35                 mov     ax, [es:di+1ah]    ; get cluster number from directory entry
36                 clc
37                 je      ffDone
38
39                 add     di, 20h             ; go to next directory entry
40                 cmp     byte  [es:di], 0     ; if the first byte of the name is 0,
41                 jnz     next_entry              ; there is no more files in the directory
42
43                 stc
44 ffDone:
45 %endmacro             
46
47 ;       GETDRIVEPARMS:  Calculate start of some disk areas.
48
49 %macro GETDRIVEPARMS 0
50                 mov     si, word  nHidden
51                 mov     di, word  nHidden_hi
52                 add     si, word  resSectors
53                 adc     di, 0                   ; DI:SI = first FAT sector
54
55                 mov     word  fat_start, si
56                 mov     word  fat_start_hi, di
57
58                 mov     al, nFats
59                 xor     ah, ah
60                 mul     word  sectPerFat     ; DX:AX = total number of FAT sectors
61
62                 add     si, ax
63                 adc     di, dx                  ; DI:SI = first root directory sector
64                 mov     word  root_dir_start, si
65                 mov     word  root_dir_start_hi, di
66
67                 ; Calculate how many sectors the root directory occupies.
68                 mov     bx, bytesPerSector
69                 mov     cl, 5                   ; divide BX by 32
70                 shr     bx, cl                  ; BX = directory entries per sector
71
72                 mov     ax, nRootDir
73                 xor     dx, dx
74                 div     bx                      
75
76                 mov     nRootDir, ax            ; AX = sectors per root directory
77
78                 add     si, ax                  
79                 adc     di, 0                   ; DI:SI = first data sector
80
81                 mov     data_start, si
82                 mov     data_start_hi, di
83 %endmacro
84
85 ;       GETFATCHAIN:    
86 ;
87 ;       Reads the FAT chain and stores it in a temporary buffer in the first
88 ;       64 kb.  The FAT chain is stored an array of 16-bit cluster numbers,
89 ;       ending with 0.
90 ;       
91 ;       The file must fit in conventional memory, so it can't be larger than
92 ;       640 kb. The sector size must be at least 512 bytes, so the FAT chain
93 ;       can't be larger than around 3 kb.
94 ;
95 ;       Call with:      AX = first cluster in chain
96 ;
97 ;       Returns:        CF clear on success, set on error
98
99 %macro GETFATCHAIN    0 
100                 push    ax                      ; store first cluster number
101
102                 ; Load the complete FAT into memory. The FAT can't be larger
103                 ; than 128 kb, so it should fit in the temporary buffer.
104
105                 mov     es, tempbuf
106                 xor     bx, bx
107                 mov     di, sectPerFat
108                 mov     ax, word  fat_start
109                 mov     dx, word  fat_start_hi
110                 call    readDisk
111                 pop     ax                      ; restore first cluster number
112                 jc      boot_error
113
114                 ; Set ES:DI to the temporary storage for the FAT chain.
115                 push    ds
116                 push    es
117                 pop     ds
118                 pop     es
119                 mov     di, FATBUF
120
121 next_clust:     stosw                           ; store cluster number
122                 mov     si, ax                  ; SI = cluster number
123                 cmp     byte  extBoot, 29h
124                 jne     fat_12
125                 cmp     byte  [bp+filesys+4], '6'  ; check for FAT-16 system
126                 je      fat_16
127
128                 ; This is a FAT-12 disk.
129
130 fat_12:         add     si, si          ; multiply cluster number by 3...
131                 add     si, ax
132                 shr     si, 1           ; ...and divide by 2
133                 lodsw
134
135                 ; If the cluster number was even, the cluster value is now in
136                 ; bits 0-11 of AX. If the cluster number was odd, the cluster
137                 ; value is in bits 4-15, and must be shifted right 4 bits. If
138                 ; the number was odd, CF was set in the last shift instruction.
139
140                 jnc     fat_even
141                 mov     cl, 4      
142                 shr     ax, cl          ; shift the cluster number 
143                 
144 fat_even:       and     ah, 0fh         ; mask off the highest 4 bits
145                 cmp     ax, 0fffh       ; check for EOF
146                 jmp     short next_test
147
148                 ; This is a FAT-16 disk. The maximal size of a 16-bit FAT
149                 ; is 128 kb, so it may not fit within a single 64 kb segment.
150  
151 fat_16:         mov     dx, tempbuf
152                 add     si, si          ; multiply cluster number by two
153                 jnc     first_half      ; if overflow...
154                 add     dh, 10h         ; ...add 64 kb to segment value
155
156 first_half:     mov     ds, dx          ; DS:SI = pointer to next cluster
157                 lodsw                   ; AX = next cluster
158
159                 cmp     ax, 0fff8h      ; >= FFF8 = 16-bit EOF
160 next_test:      jb      next_clust      ; continue if not EOF
161
162 finished:       ; Mark end of FAT chain with 0, so we have a single
163                 ; EOF marker for both FAT-12 and FAT-16 systems.
164
165                 xor      ax, ax
166                 stosw
167 fatError:
168 %endmacro
169
170
171 ;       loadFile: Loads the file into memory, one cluster at a time.
172
173 %macro LOADFILE  0
174                 mov     es, tempbuf     ; set ES:BX to load address
175                 xor     bx, bx
176
177                 mov     si, FATBUF      ; set DS:SI to the FAT chain
178                 push    cs      
179                 pop     ds              
180
181 next_cluster:   lodsw                           ; AX = next cluster to read
182                 or      ax, ax                  ; if EOF...
183                 je      boot_success            ; ...boot was successful
184
185                 dec     ax                      ; cluster numbers start with 2
186                 dec     ax
187
188                 mov     di, word  sectPerCluster
189                 and     di, 0ffh                ; DI = sectors per cluster
190                 mul     di                       
191                 add     ax, data_start
192                 adc     dx, data_start_hi        ; DX:AX = first sector to read
193                 call    readDisk
194                 jnc     next_cluster            
195
196 %endmacro