diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/BIOS/MSLOAD.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/BIOS/MSLOAD.ASM')
| -rw-r--r-- | v4.0/src/BIOS/MSLOAD.ASM | 1090 |
1 files changed, 1090 insertions, 0 deletions
diff --git a/v4.0/src/BIOS/MSLOAD.ASM b/v4.0/src/BIOS/MSLOAD.ASM new file mode 100644 index 0000000..859a318 --- /dev/null +++ b/v4.0/src/BIOS/MSLOAD.ASM | |||
| @@ -0,0 +1,1090 @@ | |||
| 1 | |||
| 2 | page ,132; | ||
| 3 | title Non-Contiguous IBMBIO Loader (MSLOAD) | ||
| 4 | ;============================================================================== | ||
| 5 | ;REVISION HISTORY: | ||
| 6 | ;AN000 - New for DOS Version 4.00 - J.K. | ||
| 7 | ;AC000 - Changed for DOS Version 4.00 - J.K. | ||
| 8 | ;AN00x - PTMs for DOS Version 4.00 - J.K. | ||
| 9 | ;============================================================================== | ||
| 10 | ;AN001; - P1820 New Message SKL file 10/20/87 J.K. | ||
| 11 | ;AN002; - D381 For SYS.COM, put the version number 01/06/88 J.K. | ||
| 12 | ;============================================================================== | ||
| 13 | ;JK, 1987 - | ||
| 14 | ; For DOS 4.00, MSLOAD program has been changed to allow: | ||
| 15 | ; 1. 32 bit calculation, | ||
| 16 | ; 2. Reading a FAT sector when needed, instead of reading the whole FAT | ||
| 17 | ; sectors at once. This will make the Boot time faster, and eliminate | ||
| 18 | ; the memory size limitation problem, | ||
| 19 | ; 3. Solving the limitation of the file size (29 KB) of IBMBIO.COM, | ||
| 20 | ; 4. Adding the boot error message. Show the same boot error message | ||
| 21 | ; and do the same behavior when the read operation of IBMBIO.COM | ||
| 22 | ; failes as the MSBOOT program, since MSLOAD program is the | ||
| 23 | ; extention of MSBOOT program. | ||
| 24 | ; | ||
| 25 | |||
| 26 | IF1 | ||
| 27 | %OUT ASSEMBLING: Non-Contiguous IBMBIO Loader (MSLOAD) | ||
| 28 | %OUT | ||
| 29 | |||
| 30 | ENDIF | ||
| 31 | |||
| 32 | |||
| 33 | DSKADR = 1Eh * 4 ;ROM bios diskette table vector position | ||
| 34 | |||
| 35 | bootseg segment at 0h | ||
| 36 | |||
| 37 | |||
| 38 | org 7C00h | ||
| 39 | Boot_Sector label byte | ||
| 40 | bootseg ends | ||
| 41 | |||
| 42 | |||
| 43 | dosloadseg segment at 70h | ||
| 44 | org 00h | ||
| 45 | IBMBIO_Address label byte | ||
| 46 | |||
| 47 | dosloadseg ends | ||
| 48 | |||
| 49 | |||
| 50 | cseg segment public para 'code' | ||
| 51 | assume cs:cseg,ds:nothing,es:nothing,ss:nothing | ||
| 52 | |||
| 53 | include MSload.inc | ||
| 54 | include Bootform.inc ;AN000; Extended bpb, boot record defintion. | ||
| 55 | include versiona.inc ;AN001; Version number for SYS.COM | ||
| 56 | |||
| 57 | sec9 equ 522h ;;** 8/3/87 DCL | ||
| 58 | |||
| 59 | BIOOFF equ 700h | ||
| 60 | ; | ||
| 61 | org 0h | ||
| 62 | |||
| 63 | start: | ||
| 64 | jmp Save_Input_Values | ||
| 65 | SYS_Version dw EXPECTED_VERSION ;AN001; From VERSIONA.INC file | ||
| 66 | Mystacks dw 64 dup (0) ;AN000; local stack | ||
| 67 | MyStack_ptr label word | ||
| 68 | |||
| 69 | ;local data | ||
| 70 | Number_Of_Heads dw 0 | ||
| 71 | Size_Cluster dw 0 | ||
| 72 | Start_Sector_L dw 0 | ||
| 73 | Start_Sector_H dw 0 ;J.K. | ||
| 74 | Temp_H dw 0 ;J.K. For 32 bit calculation | ||
| 75 | Temp_Cluster dw 0 ;J.K. Temporary place for cluster number | ||
| 76 | Last_Fat_SecNum dw -1 ;Fat sector number starting from the first fat entry. | ||
| 77 | Sector_Count dw 0 | ||
| 78 | Number_Of_FAT_Sectors dw 0 | ||
| 79 | Hidden_Sectors_L dw 0 | ||
| 80 | Hidden_Sectors_H dw 0 ;J.K. | ||
| 81 | Sector_Size dw 0 | ||
| 82 | Reserved_Sectors dw 0 | ||
| 83 | Last_Found_Cluster dw 0 | ||
| 84 | Next_BIO_Location dw 0 | ||
| 85 | First_Sector_L dw 0 | ||
| 86 | First_Sector_H dw 0 ;J.K. | ||
| 87 | Drive_Lim_L dw 0 ;J.K. Max. number of sectors | ||
| 88 | Drive_Lim_H dw 0 ;J.K. | ||
| 89 | Sectors_Per_Track dw 0 | ||
| 90 | Drive_Number db 0 | ||
| 91 | FAT_Size db 0 | ||
| 92 | Media_Byte db 0 | ||
| 93 | EOF db 0 | ||
| 94 | Org_Rom_Disktable dd 0 | ||
| 95 | FAT_Segment dw 0 | ||
| 96 | Sectors_Per_Cluster db 0 | ||
| 97 | |||
| 98 | subttl Save Input Values | ||
| 99 | page | ||
| 100 | ;*********************************************************************** | ||
| 101 | ; Save_Input_Values | ||
| 102 | ;*********************************************************************** | ||
| 103 | ; | ||
| 104 | ; Input: none | ||
| 105 | ; | ||
| 106 | ; DL = INT 13 drive number we booted from | ||
| 107 | ; CH = media byte | ||
| 108 | ; BX = First data sector (low) on disk (0-based) | ||
| 109 | ; DS:SI = Original ROM BIOS DISKETTE Parameter table. | ||
| 110 | ;J.K. 6/2/87 If an extended Boot Record, then AX will be the First data sector | ||
| 111 | ;J.K. high word. Save AX and set First_Sector_H according to AX if it is an | ||
| 112 | ;J.K. extended boot record. | ||
| 113 | ; AX = First data sector (High) on disk ; | ||
| 114 | ; Output: | ||
| 115 | ; | ||
| 116 | ; BX = first data sector on disk | ||
| 117 | ; | ||
| 118 | ; Media_Byte = input CH | ||
| 119 | ; Drive_Number = input DL | ||
| 120 | ; First_Sector_L = input BX | ||
| 121 | ; First_Sector_H = input AX, if an extended Boot record.;J.K. | ||
| 122 | ; Drive_Lim_L = maximum sector number in this media ;J.K. | ||
| 123 | ; Drive_Lim_H = high word of the above | ||
| 124 | ; Hidden_Sectors_L = hidden secotrs | ||
| 125 | ; Hidden_Sectors_H | ||
| 126 | ; Reserved_Sectors = reserved sectors | ||
| 127 | ; Sectors_Per_Track = Sectors/track | ||
| 128 | ; Number_Of_Heads = heads/cylinder | ||
| 129 | ; | ||
| 130 | ; DS = 0 | ||
| 131 | ; AX,DX,SI destroyed | ||
| 132 | ; | ||
| 133 | ; Calls: none | ||
| 134 | ;----------------------------------------------------------------------- | ||
| 135 | ;Function: | ||
| 136 | ; Save input information and BPB informations from the boot record. | ||
| 137 | ; | ||
| 138 | ;---------------------------------------------------------------------- | ||
| 139 | Save_Input_Values: | ||
| 140 | |||
| 141 | |||
| 142 | mov First_Sector_L,bx ;AC000; | ||
| 143 | mov media_Byte,ch | ||
| 144 | mov Drive_Number,dl | ||
| 145 | mov word ptr Org_Rom_Disktable, si | ||
| 146 | push ds | ||
| 147 | pop word ptr Org_Rom_Disktable+2 | ||
| 148 | xor cx,cx ;Segment 0 | ||
| 149 | mov ds,cx | ||
| 150 | assume ds:Bootseg | ||
| 151 | |||
| 152 | push es ;;** DCL 8/3/87 | ||
| 153 | mov es,cx ;;** DCL 8/3/87 | ||
| 154 | assume es:Bootseg ;;** DCL 8/3/87 | ||
| 155 | |||
| 156 | MOV SI,WORD PTR DS:DSKADR ; ARR 2.41 | ||
| 157 | MOV DS,WORD PTR DS:DSKADR+2 ; DS:SI -> CURRENT TABLE ARR 2.41 | ||
| 158 | |||
| 159 | MOV DI,SEC9 ; ES:DI -> NEW TABLE ARR 2.41 | ||
| 160 | MOV CX,11 ; taken from ibmboot.asm ARR 2.41 | ||
| 161 | CLD ; | ||
| 162 | REP MOVSB ; COPY TABLE ARR 2.41 | ||
| 163 | PUSH ES ; ARR 2.41 | ||
| 164 | POP DS ; DS = 0 ARR 2.41 | ||
| 165 | |||
| 166 | MOV WORD PTR DS:DSKADR,SEC9 ; ARR 2.41 | ||
| 167 | MOV WORD PTR DS:DSKADR+2,DS ; POINT DISK PARM VECTOR TO NEW TABLE | ||
| 168 | pop es ;;** DCL 8/3/87 | ||
| 169 | assume es:nothing | ||
| 170 | |||
| 171 | mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AN000; | ||
| 172 | mov cs:Sector_Size, cx ;AN000; | ||
| 173 | mov cl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; | ||
| 174 | mov cs:Sectors_Per_Cluster, cl ;AN000; | ||
| 175 | mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERTRACK ;Get Sectors per track | ||
| 176 | mov cs:Sectors_Per_Track,cx | ||
| 177 | mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_HEADS ;Get BPB heads per cylinder | ||
| 178 | mov cs:Number_Of_Heads,cx | ||
| 179 | mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERFAT ;Get sectors per FAT | ||
| 180 | mov cs:Number_Of_FAT_Sectors,cx | ||
| 181 | mov cx,Boot_Sector.EXT_BOOT_BPB.EBPB_RESERVEDSECTORS ;Get Reserved Sectors | ||
| 182 | mov cs:Reserved_Sectors,cx | ||
| 183 | mov cx,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR ;Get hidden sectors | ||
| 184 | mov cs:Hidden_Sectors_L,cx | ||
| 185 | mov cx, Boot_Sector.EXT_BOOT_BPB.EBPB_TOTALSECTORS ;AN000; | ||
| 186 | mov cs:Drive_Lim_L, cx ;AN000; | ||
| 187 | |||
| 188 | ;J.K. First of all, check if it the boot record is an extended one. | ||
| 189 | ;J.K. This is just a safe guard in case some user just "copy" the 4.00 IBMBIO.COM | ||
| 190 | ;J.K. to a media with a conventional boot record. | ||
| 191 | |||
| 192 | cmp Boot_Sector.EXT_BOOT_SIG, EXT_BOOT_SIGNATURE ;AN000; | ||
| 193 | jne Relocate ;AN000; | ||
| 194 | mov cs:First_Sector_H, AX ;AN000; start data sector (high) | ||
| 195 | mov ax,word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_HIDDENSECTOR+2 ;AN000; | ||
| 196 | mov cs:Hidden_Sectors_H,ax ;AN000; | ||
| 197 | cmp cx, 0 ;AN000; CX set already before (=Totalsectors) | ||
| 198 | jne Relocate ;AN000; | ||
| 199 | mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS ;AN000; | ||
| 200 | mov cs:Drive_Lim_L, ax ;AN000; | ||
| 201 | mov ax, word ptr Boot_Sector.EXT_BOOT_BPB.EBPB_BIGTOTALSECTORS+2 ;AN000; | ||
| 202 | mov cs:Drive_Lim_H, ax ;AN000; | ||
| 203 | subttl Relocate | ||
| 204 | page | ||
| 205 | ; | ||
| 206 | ;*********************************************************************** | ||
| 207 | ; RELOCATE | ||
| 208 | ;*********************************************************************** | ||
| 209 | ; | ||
| 210 | ; Notes: | ||
| 211 | ; | ||
| 212 | ; Relocate the loader code to top-of-memory. | ||
| 213 | ; | ||
| 214 | ; Input: none | ||
| 215 | ; | ||
| 216 | ; Output: Code and data relocated. | ||
| 217 | ; ax,cx,si,di destroyed | ||
| 218 | ; | ||
| 219 | ; Calls: none | ||
| 220 | ;----------------------------------------------------------------------- | ||
| 221 | ; Copy code from Start to Top of memory. | ||
| 222 | ; | ||
| 223 | ; The length to copy is Total_length | ||
| 224 | ; | ||
| 225 | ; Jump to relocated code | ||
| 226 | ;----------------------------------------------------------------------- | ||
| 227 | ; | ||
| 228 | Relocate: | ||
| 229 | assume ds:nothing | ||
| 230 | cld ;AN000; | ||
| 231 | xor si,si ;AN000; | ||
| 232 | mov di,si ;AN000; | ||
| 233 | ;SB34LOAD000**************************************************************** | ||
| 234 | ;SB Determine the number of paragraphs (16 byte blocks) of memory. | ||
| 235 | ;SB This involves invoking the memory size determination interrupt, | ||
| 236 | ;SB which returns the number of 1K blocks of memory, and then | ||
| 237 | ;SB converting this to the number of paragraphs. | ||
| 238 | ;SB Leave the number of paragraphs of memory in AX. | ||
| 239 | |||
| 240 | int 12h ;get system memory size in Kbytes | ||
| 241 | mov cl,6 ; | ||
| 242 | shl ax,cl ;memory size in paragraphs | ||
| 243 | ;SB34LOAD000**************************************************************** | ||
| 244 | mov cl,4 ;AN000; | ||
| 245 | mov dx, cs:Sector_Size ;AN000; | ||
| 246 | shr dx,cl ;AN000; | ||
| 247 | inc dx ;AN000; | ||
| 248 | sub ax, dx ;AN000; | ||
| 249 | mov cs:Fat_Segment, ax ;AN000;This will be used for FAT sector | ||
| 250 | mov dx, offset total_length ;AN000; | ||
| 251 | shr dx, cl ;AN000; | ||
| 252 | inc dx ;AN000; | ||
| 253 | sub ax, dx ;AN000; | ||
| 254 | mov es, ax ;AN000;es:di -> place be relocated. | ||
| 255 | push cs ;AN000; | ||
| 256 | pop ds ;AN000;ds:si -> source | ||
| 257 | mov cx, offset total_length ;AN000; | ||
| 258 | rep movsb ;AN000; | ||
| 259 | |||
| 260 | push es ;AN000; | ||
| 261 | mov ax, offset Setup_stack ;AN000; | ||
| 262 | push ax ;AN000;massage stack for destination of cs:ip | ||
| 263 | Dumbbb proc far ;AN000; | ||
| 264 | ret ;AN000; | ||
| 265 | Dumbbb endp ;AN000; | ||
| 266 | |||
| 267 | |||
| 268 | ; push cs ;Set up ds segreg | ||
| 269 | ; pop ds | ||
| 270 | ; xor ax,ax ;Set up ES segreg | ||
| 271 | ; mov es,ax | ||
| 272 | ; | ||
| 273 | ; assume es:bootseg,ds:cseg | ||
| 274 | ; | ||
| 275 | ; mov si,offset Start ;Source | ||
| 276 | ; mov di,offset Relocate_Start ;Target | ||
| 277 | ; mov cx,Relocate_Length ;Length | ||
| 278 | ; rep movsb ;Go do it | ||
| 279 | ; jmp far ptr Relocate_Start | ||
| 280 | |||
| 281 | |||
| 282 | |||
| 283 | subttl Setup Stack | ||
| 284 | page | ||
| 285 | ;*********************************************************************** | ||
| 286 | ; Setup_Stack | ||
| 287 | ;*********************************************************************** | ||
| 288 | ; | ||
| 289 | ; Input: none | ||
| 290 | ; | ||
| 291 | ; Output: | ||
| 292 | ; | ||
| 293 | ; SS:SP set | ||
| 294 | ; AX destroyed | ||
| 295 | ;----------------------------------------------------------------------- | ||
| 296 | ; First thing is to reset the stack to a better and more known place. | ||
| 297 | ; | ||
| 298 | ; Move the stack to just under the boot record and relocation area (0:7C00h) | ||
| 299 | ; | ||
| 300 | ; Preserve all other registers | ||
| 301 | ;---------------------------------------------------------------------- | ||
| 302 | |||
| 303 | Setup_Stack: | ||
| 304 | assume ds:nothing, es:nothing, ss:nothing | ||
| 305 | ; CLI ;Stop interrupts till stack ok | ||
| 306 | mov ax,cs | ||
| 307 | MOV SS,AX ;Set up the stack to the known area. | ||
| 308 | mov sp, offset MyStack_Ptr | ||
| 309 | ; MOV SP,7C00h - 50 ;Leave room for stack frame | ||
| 310 | ; MOV BP,7C00h - 50 ;Point BP as stack index pointer | ||
| 311 | ; STI | ||
| 312 | |||
| 313 | subttl Find_Cluster_Size | ||
| 314 | page | ||
| 315 | ;*********************************************************************** | ||
| 316 | ; Find_Cluster_Size | ||
| 317 | ;*********************************************************************** | ||
| 318 | ; | ||
| 319 | ; Input: BPB information in loaded boot record at 0:7C00h | ||
| 320 | ; | ||
| 321 | ; Output: | ||
| 322 | ; | ||
| 323 | ; DS = 0 | ||
| 324 | ; AX = Bytes/Cluster | ||
| 325 | ; BX = Sectors/Cluster | ||
| 326 | ; SI destroyed | ||
| 327 | ; Calls: none | ||
| 328 | ;----------------------------------------------------------------------- | ||
| 329 | ; | ||
| 330 | ; Get Bytes/sector from BPB | ||
| 331 | ; | ||
| 332 | ; Get sectors/cluster from BPB | ||
| 333 | ; | ||
| 334 | ; Bytes/cluster = Bytes/sector * sector/cluster | ||
| 335 | ;---------------------------------------------------------------------- | ||
| 336 | Find_Cluster_Size: | ||
| 337 | |||
| 338 | ;For the time being just assume the boot record is valid and the BPB | ||
| 339 | ;is there. | ||
| 340 | |||
| 341 | xor ax,ax ;Segment 0 | ||
| 342 | mov ds,ax | ||
| 343 | |||
| 344 | assume ds:bootseg | ||
| 345 | |||
| 346 | mov ax,Boot_Sector.EXT_BOOT_BPB.EBPB_BYTESPERSECTOR ;AC000;Get BPB bytes/sector | ||
| 347 | xor bx,bx | ||
| 348 | mov bl,Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AC000;Get sectors/cluster | ||
| 349 | mul bx ;Bytes/cluster | ||
| 350 | mov cs:Size_Cluster,ax ;Save it | ||
| 351 | |||
| 352 | |||
| 353 | subttl Determine FAT size | ||
| 354 | page | ||
| 355 | ;*********************************************************************** | ||
| 356 | ; Determine_FAT_Size | ||
| 357 | ;*********************************************************************** | ||
| 358 | ; | ||
| 359 | ; Notes: | ||
| 360 | ; | ||
| 361 | ; Determine if FAT is 12 or 16 bit FAT. 12 bit FAT if floppy, read MBR | ||
| 362 | ; to find out what system id byte is. | ||
| 363 | ; | ||
| 364 | ; Input: | ||
| 365 | ; | ||
| 366 | ; Output: | ||
| 367 | ; | ||
| 368 | ; cs:Fat_Size = FAT12_bit or FAT16_bit | ||
| 369 | ; All other registers destroyed | ||
| 370 | ; | ||
| 371 | ;---------------------------------------------------------------------- | ||
| 372 | Determine_FAT_Size: | ||
| 373 | mov cs:FAT_Size,FAT12_bit ;AN000;Assume 12 bit fat | ||
| 374 | mov dx, cs:Drive_Lim_H ;AN000; | ||
| 375 | mov ax, cs:Drive_Lim_L ;AN000; | ||
| 376 | sub ax, cs:Reserved_Sectors ;AN000; | ||
| 377 | sbb dx, 0 ;AN000;now, dx;ax = available total sectors | ||
| 378 | mov bx, cs:Number_Of_FAT_Sectors ;AN000; | ||
| 379 | shl bx, 1 ;AN000;2 FATs | ||
| 380 | sub ax, bx ;AN000; | ||
| 381 | sbb dx, 0 ;AN000;now, dx;ax = tatal sectors - fat sectors | ||
| 382 | mov bx, Boot_Sector.EXT_BOOT_BPB.EBPB_ROOTENTRIES ;AN000; | ||
| 383 | mov cl, 4 ;AN000; | ||
| 384 | shr bx, cl ;AN000;Sectors for dir entries = dir entries / Num_DIR_Sector | ||
| 385 | sub ax, bx ;AN000; | ||
| 386 | sbb dx, 0 ;AN000; | ||
| 387 | xor cx, cx ;AN000; | ||
| 388 | mov cl, Boot_Sector.EXT_BOOT_BPB.EBPB_SECTORSPERCLUSTER ;AN000; | ||
| 389 | push ax ;AN000; | ||
| 390 | mov ax, dx ;AN000; | ||
| 391 | xor dx, dx ;AN000; | ||
| 392 | div cx ;AN000; | ||
| 393 | mov cs:Temp_H, ax ;AN000; | ||
| 394 | pop ax ;AN000; | ||
| 395 | ;J.K. We assume that cx > dx. | ||
| 396 | div cx ;AN000; | ||
| 397 | cmp ax, 4096-10 ;AN000; | ||
| 398 | ; jb Determine_First_Cluster ;AN000; | ||
| 399 | jb Read_In_FirstClusters | ||
| 400 | mov cs:FAT_Size, FAT16_Bit ;AN000;16 bit fat | ||
| 401 | |||
| 402 | ; cmp cs:Media_Byte,0F8h ;Is it floppy | ||
| 403 | ; jne FAT_Size_Found ;Yep, all set | ||
| 404 | ; mov cs:Logical_Sector,0 ;Got hardfile, go get MBR | ||
| 405 | ; xor ax,ax | ||
| 406 | ; mov es,ax | ||
| 407 | ; mov di,offset Relocate_Start | ||
| 408 | ; mov cs:Sector_Count,1 | ||
| 409 | ; call Disk_Read | ||
| 410 | ; mov si,offset Relocate_Start+1C2h | ||
| 411 | ; mov cx,4 | ||
| 412 | ; xor ax,ax | ||
| 413 | ; mov ds,ax | ||
| 414 | ;Find_Sys_Id: | ||
| 415 | ; mov cs:FAT_Size,FAT12_bit ;Assume 12 bit fat | ||
| 416 | ; cmp byte ptr [si],1 | ||
| 417 | ; je FAT_Size_Found | ||
| 418 | ; mov cs:FAT_Size,FAT16_bit ;Assume 12 bit fat | ||
| 419 | ; cmp byte ptr [si],4 | ||
| 420 | ; je Fat_Size_Found | ||
| 421 | ; add si,16 | ||
| 422 | ; loop Find_Sys_Id | ||
| 423 | ; ;xxxxxxxxxxxxxxxxxxxxxxxxxx error | ||
| 424 | ;FAT_Size_Found: | ||
| 425 | |||
| 426 | |||
| 427 | subttl Read_In_FirstClusters | ||
| 428 | page | ||
| 429 | ;*********************************************************************** | ||
| 430 | ; Read_In_FirstClusters | ||
| 431 | ;*********************************************************************** | ||
| 432 | ; | ||
| 433 | ; Notes: Read the start of the clusters that covers at least IBMLOADSIZE | ||
| 434 | ; fully. For example, if sector/cluster = 2, and IBMLOADSIZE=3 | ||
| 435 | ; then we are going to re-read the second cluster to fully cover | ||
| 436 | ; MSLOAD program in the cluster boundary. | ||
| 437 | ; | ||
| 438 | ; Input: | ||
| 439 | ; IBMLOADSIZE - Make sure this value is the same as the one in | ||
| 440 | ; MSBOOT program when you build the new version!!!!! | ||
| 441 | ; | ||
| 442 | ; Sectors_Per_Cluster | ||
| 443 | ; Size_Cluster | ||
| 444 | ; First_Sector_L | ||
| 445 | ; First_Sector_H | ||
| 446 | ; | ||
| 447 | ; Output: MSLOAD program is fully covered in a cluster boundary. | ||
| 448 | ; AX = # of clusters we read in so far. | ||
| 449 | ; | ||
| 450 | ; Calls: Disk_Read | ||
| 451 | ; Logic: | ||
| 452 | ; AX; DX = IBMLOADSIZE / # of sector in a cluster. | ||
| 453 | ; if DX = 0 then Ok. (MSLOAD is in a cluster boundary.) | ||
| 454 | ; else (Has to read (AX+1)th cluster to cover MSLOAD) | ||
| 455 | ; read (AX+1)th cluster into the address after the clusters we | ||
| 456 | ; read in so far. | ||
| 457 | ;----------------------------------------------------------------------- | ||
| 458 | |||
| 459 | Read_In_FirstClusters: | ||
| 460 | mov ax, IBMLOADSIZE ;AN000; | ||
| 461 | div cs:Sectors_Per_Cluster ;AN000; | ||
| 462 | cmp ah, 0 ;AN000; | ||
| 463 | je Set_Next_Cluster_Number ;AN000; | ||
| 464 | xor ah, ah ;AN000; | ||
| 465 | push ax ;AN000; | ||
| 466 | mov cx, cs:First_Sector_L ;AN000; | ||
| 467 | mov cs:Start_Sector_L, cx ;AN000; | ||
| 468 | mov cx, cs:First_Sector_H ;AN000; | ||
| 469 | mov cs:Start_Sector_H, cx ;AN000; | ||
| 470 | mul cs:Sectors_Per_Cluster ;AN000; Now, AX=# of sectors | ||
| 471 | add cs:Start_Sector_L, ax ;AN000; | ||
| 472 | adc cs:Start_Sector_H, 0 ;AN000; | ||
| 473 | pop ax ;AN000; | ||
| 474 | push ax ;AN000; | ||
| 475 | mov di, BIOOFF ;AN000; | ||
| 476 | mul cs:Size_Cluster ;AN000;AX = # of bytes read in before this cluster | ||
| 477 | add di, ax ;AN000; | ||
| 478 | xor ax, ax ;AN000; | ||
| 479 | mov es, ax ;AN000; | ||
| 480 | mov al, cs:Sectors_Per_Cluster ;AN000; | ||
| 481 | mov cs:Sector_Count, ax ;AN000; | ||
| 482 | call Disk_Read ;AN000; | ||
| 483 | pop ax ;AN000; | ||
| 484 | inc ax ;AN000;# of clusters read in so far. | ||
| 485 | |||
| 486 | subttl Set_Next_Cluster_Number | ||
| 487 | page | ||
| 488 | ;*********************************************************************** | ||
| 489 | ; Set_Next_Cluster_Number | ||
| 490 | ;*********************************************************************** | ||
| 491 | ; | ||
| 492 | ; Notes: Set LAST_Found_Cluster for the next use. | ||
| 493 | ; Last_Found_Cluster is the cluster number we are in now. | ||
| 494 | ; Since cluster number is 0 based and there are 2 clusters int | ||
| 495 | ; the beginning of FAT table used by the system, we just add | ||
| 496 | ; 1 to set Last_Found_Cluster. | ||
| 497 | ; | ||
| 498 | ; Input: | ||
| 499 | ; AX = # of clusters read in so far. | ||
| 500 | ; | ||
| 501 | ; Output: | ||
| 502 | ; | ||
| 503 | ; cs:Last_Found_Cluster | ||
| 504 | ; | ||
| 505 | ; Calls: none | ||
| 506 | ;------------------------------------------------------------------ | ||
| 507 | Set_Next_Cluster_Number: | ||
| 508 | inc ax ;AN000; For Last_Found_Cluster | ||
| 509 | mov cs:Last_Found_Cluster,ax ;2 is the first data cluster number(0 based) | ||
| 510 | |||
| 511 | subttl Read In FAT | ||
| 512 | page | ||
| 513 | ;*********************************************************************** | ||
| 514 | ; Read_In_FAT | ||
| 515 | ;*********************************************************************** | ||
| 516 | ; | ||
| 517 | ; Notes: | ||
| 518 | ; | ||
| 519 | ; Reads in the entire FAT at 800:0. This gives the relocated portion | ||
| 520 | ; of this loader a maximum size of 768 bytes (8000 - 7D00). | ||
| 521 | ; With 64 KB memory system, this can support maximum size of FAT to | ||
| 522 | ; be 32 KB. We assumes that the system memory size be 128 KB, if | ||
| 523 | ; the system has a big media with the total fat size bigger than | ||
| 524 | ; 32 KB. | ||
| 525 | ; | ||
| 526 | ; Input: none | ||
| 527 | ; | ||
| 528 | ; Output: | ||
| 529 | ; | ||
| 530 | ; ES = 0 | ||
| 531 | ; All sectors destroyed | ||
| 532 | ; | ||
| 533 | ; Calls: READ DISK | ||
| 534 | ;----------------------------------------------------------------------- | ||
| 535 | ; Get number of sectors in FAT | ||
| 536 | ; | ||
| 537 | ; Set ES:DI to 800:0 | ||
| 538 | ; | ||
| 539 | ; Read in the sectors | ||
| 540 | ; | ||
| 541 | ;---------------------------------------------------------------------- | ||
| 542 | ;Read_In_FAT: | ||
| 543 | ; mov ax,cs:Number_Of_FAT_Sectors ;Get sectors/FAT | ||
| 544 | ; mov cs:Sector_Count,ax ;Number of sectors to read | ||
| 545 | ; mov ax,cs:Hidden_Sectors_L ;Hidden+Reserved = start of FAT sector | ||
| 546 | ; mov dx,cs:Hidden_Sectors_H ;AN000; | ||
| 547 | ; add ax,cs:Reserved_Sectors | ||
| 548 | ; adc dx, 0 | ||
| 549 | ; mov cs:Start_Sector_L,ax ;AC000;Save it, setup for disk read | ||
| 550 | ; mov cs:Start_Sector_H,dx ;AN000; | ||
| 551 | ; mov di, 800h ;AC000; | ||
| 552 | ; mov es, di ;AC000; | ||
| 553 | ; xor di, di ;AC000; | ||
| 554 | ; assume es:nothing | ||
| 555 | ; call Disk_Read | ||
| 556 | ; | ||
| 557 | subttl Keep Loaded BIO | ||
| 558 | page | ||
| 559 | ;*********************************************************************** | ||
| 560 | ; KEEP LOADED BIO | ||
| 561 | ;*********************************************************************** | ||
| 562 | ; | ||
| 563 | ; Notes: | ||
| 564 | ; | ||
| 565 | ; Determine how much of IBMBIO was loaded in when the loader was loaded | ||
| 566 | ; by the boot record (only the portion that is guaranteed to be contiguous) | ||
| 567 | ; | ||
| 568 | ; Input: | ||
| 569 | ; | ||
| 570 | ; cs:Last_Found_Cluster = number of clusters used for loader+2 | ||
| 571 | ; | ||
| 572 | ; Output: | ||
| 573 | ; ES=70h | ||
| 574 | ; DI = Next offset to load IBMBIO code | ||
| 575 | ; AX,BX,CX,DX,SI destroyed | ||
| 576 | ; | ||
| 577 | ; cs:Next_BIO_Location = DI on output | ||
| 578 | ; cs:Last_Cluster = last cluster loaded | ||
| 579 | ; | ||
| 580 | ; Calls: none | ||
| 581 | ;----------------------------------------------------------------------- | ||
| 582 | ;Number of clusters loaded+2 is in cs:Last_Found_Cluster | ||
| 583 | ; | ||
| 584 | ;Multiply cluster * cluster size in bytes to get total loaded for MSLOAD | ||
| 585 | ; | ||
| 586 | ;Subtract TOTAL_LOADED - LOADBIO_SIZE to get loaded IBMBIO in last cluster | ||
| 587 | ; | ||
| 588 | ;Relocate this piece of IBMBIO down to 70:0 | ||
| 589 | ; | ||
| 590 | ;---------------------------------------------------------------------- | ||
| 591 | Keep_Loaded_BIO: | ||
| 592 | push ds | ||
| 593 | mov ax,cs:Last_Found_Cluster ;Point to last cluster loaded | ||
| 594 | sub ax,1 ;Get number of clusters loaded | ||
| 595 | mul cs:Size_Cluster ;Get total bytes loaded by | ||
| 596 | ;This is always < 64k, so | ||
| 597 | ;lower 16 bits ok | ||
| 598 | sub ax,LoadBio_Size ;Get portion of IBMBIO loaded | ||
| 599 | mov cx,ax ;Save length to move | ||
| 600 | mov ax,70h ;Segment at 70h | ||
| 601 | mov ds,ax | ||
| 602 | mov es,ax | ||
| 603 | mov si,offset Total_Length ;Point at IBMBIO | ||
| 604 | mov di,0 ;Point at 70:0 | ||
| 605 | rep movsb ;Relocate this code | ||
| 606 | mov cs:Next_Bio_Location,di ;Save where to load next | ||
| 607 | pop ds | ||
| 608 | |||
| 609 | subttl Get Contiguous Clusters | ||
| 610 | page | ||
| 611 | ;*********************************************************************** | ||
| 612 | ; Get_Contiguous_Clusters | ||
| 613 | ;*********************************************************************** | ||
| 614 | ; | ||
| 615 | ; Notes: Go find clusters as long as they are contiguous | ||
| 616 | ; | ||
| 617 | ; | ||
| 618 | ; Input: | ||
| 619 | ; | ||
| 620 | ; cs:Next_BIO_Location | ||
| 621 | ; cs: | ||
| 622 | ; | ||
| 623 | ; | ||
| 624 | ; Output: | ||
| 625 | ; | ||
| 626 | ; | ||
| 627 | ; Calls: Get_Next_FAT_Entry | ||
| 628 | ;----------------------------------------------------------------------- | ||
| 629 | ; | ||
| 630 | ;Set cs:Sector_Count to Sectors per cluster | ||
| 631 | ; | ||
| 632 | ;Call Get_Next_FAT_Entry to get next cluster in file | ||
| 633 | ; | ||
| 634 | ;Call Check_for_EOF | ||
| 635 | ; | ||
| 636 | ;IF (NC returned) | ||
| 637 | ; | ||
| 638 | ; {Call Get_Next_FAT_Entry | ||
| 639 | ; | ||
| 640 | ; IF (New cluster is contig to old cluster) | ||
| 641 | ; {Add sectors per cluster to cs:Sector_Count | ||
| 642 | ; | ||
| 643 | ; Call Check_For_EOF | ||
| 644 | ; | ||
| 645 | ; IF (NC returned) | ||
| 646 | ; | ||
| 647 | ; | ||
| 648 | ;---------------------------------------------------------------------- | ||
| 649 | Get_Contiguous_Cluster: | ||
| 650 | xor ah,ah | ||
| 651 | mov al,cs:Sectors_Per_Cluster ;Assume we will get one cluster | ||
| 652 | mov cs:Sector_Count,ax | ||
| 653 | push cs:Sector_Count | ||
| 654 | call Get_Next_Fat_Entry ;Go get it in AX | ||
| 655 | pop cs:Sector_Count | ||
| 656 | mov cs:Last_Found_Cluster,ax ;Update the last one found | ||
| 657 | cmp cs:EOF,END_OF_FILE | ||
| 658 | je GO_IBMBIO | ||
| 659 | |||
| 660 | ; je GOTO_IBMBIO | ||
| 661 | ;Got_Contig_Clusters: | ||
| 662 | |||
| 663 | xor dx,dx ;AN000; | ||
| 664 | sub ax,2 ;Zero base the cluster | ||
| 665 | xor ch,ch | ||
| 666 | mov cl,cs:Sectors_Per_Cluster ;Get sectors per cluster | ||
| 667 | mul cx ;Get how many | ||
| 668 | add ax,cs:First_Sector_L ;AC000;See where the data sector starts | ||
| 669 | adc dx,cs:First_Sector_H ;AN000; | ||
| 670 | mov cs:Start_Sector_L,ax ;AC000;Save it | ||
| 671 | mov cs:Start_Sector_H,dx ;AN000; | ||
| 672 | mov di,cs:Next_Bio_Location ;Get where to put code | ||
| 673 | push cs:Sector_Count ;Save how many sectors | ||
| 674 | mov ax,dosloadseg ;Get area to load code | ||
| 675 | mov es,ax | ||
| 676 | call Disk_Read | ||
| 677 | pop ax ;Get back total sectors read in | ||
| 678 | ; jc ########## | ||
| 679 | mul cs:Sector_Size ;AC000;Get number of bytes we loaded | ||
| 680 | ; mul Boot_Sector.ByteSec | ||
| 681 | add cs:Next_Bio_Location,ax ;Point to where to load next | ||
| 682 | jmp Get_Contiguous_Cluster | ||
| 683 | |||
| 684 | subttl GOTO IBMBIO | ||
| 685 | page | ||
| 686 | ;*********************************************************************** | ||
| 687 | ; GOTO_IBMBIO | ||
| 688 | ;*********************************************************************** | ||
| 689 | ; | ||
| 690 | ; Notes: | ||
| 691 | ; | ||
| 692 | ; Set up required registers for IBMBIO, then jump to it (70:0) | ||
| 693 | ; | ||
| 694 | ; Input: none | ||
| 695 | ; | ||
| 696 | ; cs:Media_Byte = media byte | ||
| 697 | ; cs:Drive_Number = INT 13 drive number we booted from | ||
| 698 | ; cs:First_Sector_L = First data sector on disk (Low) (0-based) | ||
| 699 | ; cs:First_Sector_H = First data sector on disk (High) | ||
| 700 | ; | ||
| 701 | ; Output: | ||
| 702 | ; | ||
| 703 | ; Required by MSINIT | ||
| 704 | ; DL = INT 13 drive number we booted from | ||
| 705 | ; CH = media byte | ||
| 706 | ; BX = First data sector on disk (0-based) | ||
| 707 | ; AX = First data sector on disk (High) | ||
| 708 | ; DI = Sectors/FAT for the boot media. | ||
| 709 | ; | ||
| 710 | ; Calls: none | ||
| 711 | ;----------------------------------------------------------------------- | ||
| 712 | ; | ||
| 713 | ; Set up registers for MSINIT then do Far Jmp | ||
| 714 | ; | ||
| 715 | ;---------------------------------------------------------------------- | ||
| 716 | GO_IBMBIO: | ||
| 717 | mov ch,cs:Media_Byte ;Restore regs required for MSINT | ||
| 718 | mov dl,cs:Drive_Number ;Physical Drive number we booted from. | ||
| 719 | mov bx,cs:First_Sector_L ;AC000; | ||
| 720 | mov ax,cs:First_Sector_H ;AN000; AX will be the First data sector (High) | ||
| 721 | ;J.K. Don't need this information any more. | ||
| 722 | ; mov di,cs:Number_Of_FAT_Sectors ;AN000 | ||
| 723 | jmp far ptr IBMBIO_Address | ||
| 724 | |||
| 725 | |||
| 726 | subttl Disk Read | ||
| 727 | page | ||
| 728 | ;*********************************************************************** | ||
| 729 | ; Disk_Read | ||
| 730 | ;*********************************************************************** | ||
| 731 | ; | ||
| 732 | ; Notes: | ||
| 733 | ; | ||
| 734 | ; Read in the cs:Sector_Count number of sectors at ES:DI | ||
| 735 | ; | ||
| 736 | ; | ||
| 737 | ; Input: none | ||
| 738 | ; | ||
| 739 | ; DI = Offset of start of read | ||
| 740 | ; ES = Segment of read | ||
| 741 | ; cs:Sector_Count = number of sectors to read | ||
| 742 | ; cs:Start_sector_L = starting sector (Low) | ||
| 743 | ; cs:Start_sector_H = starting sector (High) | ||
| 744 | ; Following is BPB info that must be setup prior to call | ||
| 745 | ; cs:Number_Of_Heads | ||
| 746 | ; cs:Number_Of_Sectors | ||
| 747 | ; cs:Drive_Number | ||
| 748 | ; cs:Sectors_Per_Track | ||
| 749 | ; | ||
| 750 | ; Output: | ||
| 751 | ; | ||
| 752 | ; AX,BX,CX,DX,SI,DI destroyed | ||
| 753 | ;----------------------------------------------------------------------- | ||
| 754 | ; Divide start sector by sectors per track | ||
| 755 | ; The remainder is the actual sector number, 0 based | ||
| 756 | ; | ||
| 757 | ; Increment actual sector number to get 1 based | ||
| 758 | ; | ||
| 759 | ; The quotient is the number of tracks - divide by heads to get the cyl | ||
| 760 | ; | ||
| 761 | ; The remainder is actual head, the quotient is cylinder | ||
| 762 | ; | ||
| 763 | ; Figure the number of sectors in that track, set AL to this | ||
| 764 | ; | ||
| 765 | ; Do the read | ||
| 766 | ; | ||
| 767 | ; If Error, Do RESET, then redo the INT 13h | ||
| 768 | ; | ||
| 769 | ; If successful read, Subtract # sectors read from Sector_Count, Add to Logical | ||
| 770 | ; Sector, add #sectors read * Sector_Size to BX; | ||
| 771 | ; | ||
| 772 | ; If Sector_Count <> 0 Do next read | ||
| 773 | ;---------------------------------------------------------------------- | ||
| 774 | Disk_Read: | ||
| 775 | |||
| 776 | ; | ||
| 777 | ; convert a logical sector into Track/sector/head. AX has the logical | ||
| 778 | ; sector number | ||
| 779 | ; | ||
| 780 | DODIV: | ||
| 781 | MOV cx,5 ;5 retries | ||
| 782 | |||
| 783 | Try_Read: | ||
| 784 | PUSH cx ;Save it | ||
| 785 | MOV AX,cs:Start_Sector_L ;AC000; Get starting sector | ||
| 786 | mov dx, cs:Start_Sector_H ;AN000; | ||
| 787 | ; XOR DX,DX | ||
| 788 | push ax ;AN000; | ||
| 789 | mov ax, dx ;AN000; | ||
| 790 | xor dx, dx ;AN000; | ||
| 791 | DIV word ptr cs:Sectors_Per_Track | ||
| 792 | mov cs:Temp_H, ax ;AN000; | ||
| 793 | pop ax ;AN000; | ||
| 794 | div word ptr cs:Sectors_Per_Track ;AN000;[temp_h];AX = track, DX = sector number | ||
| 795 | MOV bx,cs:Sectors_Per_Track ;Get number of sectors we can read in | ||
| 796 | sub bx,dx ;this track | ||
| 797 | mov si,bx | ||
| 798 | cmp cs:Sector_Count,si ;Is possible sectors in track more | ||
| 799 | jae Got_Length ;than what we need to read? | ||
| 800 | mov si,cs:Sector_Count ;Yes, only read what we need to | ||
| 801 | Got_Length: | ||
| 802 | INC DL ; sector numbers are 1-based | ||
| 803 | MOV bl,dl ;Start sector in DL | ||
| 804 | mov dx, cs:Temp_H ;AN000;now, dx;ax = track | ||
| 805 | ; XOR DX, DX | ||
| 806 | push ax ;AN000; | ||
| 807 | mov ax, dx ;AN000; | ||
| 808 | xor dx, dx ;AN000; | ||
| 809 | DIV word ptr cs:Number_Of_Heads ;Start cyl in ax,head in DL | ||
| 810 | mov cs:Temp_h, ax ;AN000; | ||
| 811 | pop ax ;AN000; | ||
| 812 | div word ptr cs:Number_of_Heads ;AN000;now [temp_h];AX = cyliner, dx = head | ||
| 813 | ;J.K. At this moment, we assume that Temp_h = 0, AX <= 1024, DX <= 255 | ||
| 814 | MOV DH,DL | ||
| 815 | ; | ||
| 816 | ; Issue one read request. ES:BX have the transfer address, AL is the number | ||
| 817 | ; of sectors. | ||
| 818 | ; | ||
| 819 | MOV CL,6 | ||
| 820 | SHL AH,CL ;Shift cyl high bits up | ||
| 821 | OR AH,BL ;Mix in with sector bits | ||
| 822 | MOV CH,AL ;Setup Cyl low | ||
| 823 | MOV CL,AH ;Setup Cyl/high - Sector | ||
| 824 | mov bx,di ;Get back offset | ||
| 825 | MOV DL,cs:Drive_Number ;Get drive | ||
| 826 | mov ax,si ;Get number of sectors to read (AL) | ||
| 827 | |||
| 828 | MOV AH,2 ;Read | ||
| 829 | push ax ;Save length of read | ||
| 830 | push di | ||
| 831 | ; Issue one read request. ES:BX have the transfer address, AL is the number | ||
| 832 | ; of sectors. | ||
| 833 | INT 13H | ||
| 834 | pop di | ||
| 835 | pop ax | ||
| 836 | pop cx ;Get retry count back | ||
| 837 | jnc Read_OK | ||
| 838 | mov bx,di ;Get offset | ||
| 839 | xor ah,ah | ||
| 840 | push cx | ||
| 841 | mov dl,cs:Drive_Number | ||
| 842 | push di | ||
| 843 | int 13h | ||
| 844 | pop di | ||
| 845 | pop cx | ||
| 846 | ; loop Try_Read ;AC000; | ||
| 847 | ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error | ||
| 848 | dec cx ;AN000; | ||
| 849 | jz Read_Error ;AN000; | ||
| 850 | jmp Try_Read ;AN000; | ||
| 851 | Read_Error: ;AN000; | ||
| 852 | jmp ErrorOut ;AN000; | ||
| 853 | |||
| 854 | Read_OK: | ||
| 855 | xor ah,ah ;Mask out read command, just get # read | ||
| 856 | sub cs:Sector_Count,ax ;Bump number down | ||
| 857 | jz Read_Finished | ||
| 858 | add cs:Start_Sector_L,ax ;AC000;Where to start next time | ||
| 859 | adc cs:Start_Sector_H, 0 ;AN000; | ||
| 860 | xor bx,bx ;Get number sectors read | ||
| 861 | mov bl,al | ||
| 862 | mov ax,cs:Sector_Size ;Bytes per sector | ||
| 863 | mul bx ;Get total bytes read | ||
| 864 | add di,ax ;Add it to offset | ||
| 865 | jmp DODIV | ||
| 866 | Read_Finished: | ||
| 867 | RET | ||
| 868 | |||
| 869 | subttl GET NEXT FAT ENTRY | ||
| 870 | page | ||
| 871 | ;*********************************************************************** | ||
| 872 | ; GET_NEXT_FAT_ENTRY | ||
| 873 | ;*********************************************************************** | ||
| 874 | ; | ||
| 875 | ; Notes: | ||
| 876 | ; | ||
| 877 | ; Given the last cluster found, this will return the next cluster of | ||
| 878 | ; IBMBIO. If the last cluster is (F)FF8 - (F)FFF, then the final cluster | ||
| 879 | ; of IBMBIO has been loaded, and control is passed to GOTO_IBMBIO | ||
| 880 | ; MSLOAD can handle maximum FAT area size of 64 KB. | ||
| 881 | ; | ||
| 882 | ; Input: | ||
| 883 | ; | ||
| 884 | ; cs:Last_Found_Cluster | ||
| 885 | ; cs:Fat_Size | ||
| 886 | ; | ||
| 887 | ; Output: | ||
| 888 | ; | ||
| 889 | ; cs:Last_Found_Cluster (updated) | ||
| 890 | ; | ||
| 891 | ; Calls: Get_Fat_Sector | ||
| 892 | ;----------------------------------------------------------------------- | ||
| 893 | ; Get Last_Found_Cluster | ||
| 894 | ; | ||
| 895 | ; IF (16 bit FAT) | ||
| 896 | ; {IF (Last_Found_Cluster = FFF8 - FFFF) | ||
| 897 | ; {JMP GOTO_IBMBIO} | ||
| 898 | ; ELSE | ||
| 899 | ; {Get offset by multiply cluster by 2} | ||
| 900 | ; | ||
| 901 | ; ELSE | ||
| 902 | ; {IF (Last_Found_Cluster = FF8 - FFF) | ||
| 903 | ; {JMP GOTO_IBMBIO} | ||
| 904 | ; ELSE | ||
| 905 | ; {Get offset by - multiply cluster by 3 | ||
| 906 | ; | ||
| 907 | ; Rotate right to divide by 2 | ||
| 908 | ; | ||
| 909 | ; IF (CY set - means odd number) | ||
| 910 | ; {SHR 4 times to keep high twelve bits} | ||
| 911 | ; | ||
| 912 | ; ELSE | ||
| 913 | ; {AND with 0FFFh to keep low 12 bits} | ||
| 914 | ; } | ||
| 915 | ; } | ||
| 916 | ; | ||
| 917 | ; | ||
| 918 | ;---------------------------------------------------------------------- | ||
| 919 | Get_Next_FAT_Entry: | ||
| 920 | |||
| 921 | push es ;AN000; | ||
| 922 | mov ax, cs:FAT_Segment ;AN000; | ||
| 923 | mov es, ax ;AN000; es-> Fat area segment | ||
| 924 | assume es:nothing | ||
| 925 | |||
| 926 | mov cs:EOF,End_Of_File ;Assume last cluster | ||
| 927 | mov ax,cs:Last_Found_Cluster ;Get last cluster | ||
| 928 | cmp cs:Fat_Size,FAT12_bit | ||
| 929 | jne Got_16_Bit | ||
| 930 | mov si, ax ;AN000; | ||
| 931 | shr ax, 1 ;AN000; | ||
| 932 | add si, ax ;AN000; si = ax*1.5 = ax+ax/2 | ||
| 933 | call Get_Fat_Sector ;AN000; | ||
| 934 | jne Ok_cluster ;AN000; | ||
| 935 | mov al, byte ptr es:[bx] ;AN000; | ||
| 936 | mov byte ptr cs:Temp_cluster, al ;AN000; | ||
| 937 | inc si ;AN000; | ||
| 938 | call Get_Fat_Sector ;AN000;read next FAT sector | ||
| 939 | mov al, byte ptr es:[0] ;AN000; | ||
| 940 | mov byte ptr cs:Temp_cluster+1, al ;AN000; | ||
| 941 | mov ax, cs:Temp_cluster ;AN000; | ||
| 942 | jmp short Even_Odd ;AN000; | ||
| 943 | Ok_cluster: ;AN000; | ||
| 944 | mov ax, es:[bx] ;AN000; | ||
| 945 | Even_Odd: ;AN000; | ||
| 946 | |||
| 947 | ; xor bx,bx | ||
| 948 | ; mov bl,3 ;Mult by 3 | ||
| 949 | ; mul bx | ||
| 950 | ; shr ax,1 ;Div by 2 to get 1.5 | ||
| 951 | ; mov si,ax ;Get the final buffer offset | ||
| 952 | ; mov ax,[si]+8000h ;Get new cluster | ||
| 953 | |||
| 954 | test cs:Last_Found_Cluster,1 ;Was last cluster odd? | ||
| 955 | jnz Odd_Result ;If Carry set it was odd | ||
| 956 | and ax,0FFFh ;Keep low 12 bits | ||
| 957 | jmp short Test_EOF ; | ||
| 958 | |||
| 959 | Odd_Result: | ||
| 960 | mov cl,4 ;AN000;Keep high 12 bits for odd | ||
| 961 | shr ax,cl | ||
| 962 | Test_EOF: | ||
| 963 | cmp ax,0FF8h ;Is it last cluster? | ||
| 964 | jae Got_Cluster_Done ;Yep, all done here | ||
| 965 | jmp short Not_Last_CLuster | ||
| 966 | |||
| 967 | Got_16_Bit: | ||
| 968 | shl ax,1 ;Multiply cluster by 2 | ||
| 969 | mov si,ax ;Get the final buffer offset | ||
| 970 | call Get_Fat_Sector ;AN000; | ||
| 971 | mov ax, es:[bx] ;AN000; | ||
| 972 | ; mov ax,[si]+8000h ;Get new cluster | ||
| 973 | cmp ax,0FFF8h | ||
| 974 | jae Got_Cluster_Done | ||
| 975 | |||
| 976 | Not_Last_Cluster: | ||
| 977 | mov cs:EOF,not END_OF_FILE ;Assume last cluster | ||
| 978 | |||
| 979 | Got_Cluster_Done: | ||
| 980 | pop es | ||
| 981 | ret | ||
| 982 | |||
| 983 | |||
| 984 | Get_Fat_Sector proc near | ||
| 985 | ;Function: Find and read the corresponding FAT sector into ES:0 | ||
| 986 | ;In). SI = offset value (starting from FAT entry 0) of FAT entry to find. | ||
| 987 | ; ES = FAT sector segment | ||
| 988 | ; cs:Sector_Size | ||
| 989 | ;Out). Corresponding FAT sector read in. | ||
| 990 | ; BX = offset value of the corresponding FAT entry in the FAT sector. | ||
| 991 | ; CX destroyed. | ||
| 992 | ; Zero flag set if the FAT entry is splitted, i.e. when 12 bit FAT entry | ||
| 993 | ; starts at the last byte of the FAT sector. In this case, the caller | ||
| 994 | ; should save this byte, and read the next FAT sector to get the rest | ||
| 995 | ; of the FAT entry value. (This will only happen with the 12 bit fat). | ||
| 996 | |||
| 997 | push ax ;AN000; | ||
| 998 | push si ;AN000; | ||
| 999 | push di ;AN000; | ||
| 1000 | push dx ;AN000; | ||
| 1001 | xor dx, dx ;AN000; | ||
| 1002 | mov ax, si ;AN000; | ||
| 1003 | mov cx, cs:Sector_Size ;AN000; | ||
| 1004 | div cx ;AN000;ax = sector number, dx = offset | ||
| 1005 | cmp ax, cs:Last_Fat_SecNum ;AN000;the same fat sector? | ||
| 1006 | je GFS_Split_Chk ;AN000;don't need to read it again. | ||
| 1007 | mov cs:Last_Fat_SecNum, ax ;AN000; | ||
| 1008 | push dx ;AN000; | ||
| 1009 | xor dx, dx ;AN000; | ||
| 1010 | add ax, cs:Hidden_Sectors_L ;AN000; | ||
| 1011 | adc dx, cs:Hidden_Sectors_H ;AN000; | ||
| 1012 | add ax, cs:Reserved_Sectors ;AN000; | ||
| 1013 | adc dx, 0 ;AN000; | ||
| 1014 | mov cs:Start_Sector_L, ax ;AN000; | ||
| 1015 | mov cs:Start_Sector_H, dx ;AN000;set up for Disk_Read | ||
| 1016 | mov cs:Sector_Count, 1 ;AN000;1 sector | ||
| 1017 | xor di, di ;AN000; | ||
| 1018 | call Disk_Read ;AN000; | ||
| 1019 | pop dx ;AN000; | ||
| 1020 | mov cx, cs:Sector_Size ;AN000; | ||
| 1021 | GFS_Split_Chk: ;AN000; | ||
| 1022 | dec cx ;AN000;now, cx= sector size - 1 | ||
| 1023 | cmp dx, cx ;AN000;if the last byte of the sector, then splitted entry. | ||
| 1024 | mov bx, dx ;AN000;Set BX to DX | ||
| 1025 | pop dx ;AN000; | ||
| 1026 | pop di ;AN000; | ||
| 1027 | pop si ;AN000; | ||
| 1028 | pop ax ;AN000; | ||
| 1029 | ret ;AN000; | ||
| 1030 | Get_Fat_Sector endp ;AN000; | ||
| 1031 | |||
| 1032 | |||
| 1033 | Errorout: ;AN000; | ||
| 1034 | push cs ;AN000; | ||
| 1035 | pop ds ;AN000; | ||
| 1036 | mov si, offset Sysmsg ;AN000; | ||
| 1037 | call write ;AN000; | ||
| 1038 | ;SB34LOAD001**************************************************************** | ||
| 1039 | ;SB Wait for a keypress on the keyboard. Use the BIOS keyboard interrupt. | ||
| 1040 | ;SB 2 LOCS | ||
| 1041 | |||
| 1042 | xor ah,ah | ||
| 1043 | int 16h ;read keyboard | ||
| 1044 | ;SB34LOAD001**************************************************************** | ||
| 1045 | |||
| 1046 | ;SB34LOAD002**************************************************************** | ||
| 1047 | ;SB We have to restore the address of the original rom Disk parameter table | ||
| 1048 | ;SB to the location at [0:DSKADR]. The address of this original table has been | ||
| 1049 | ;SB saved previously in 0:Org_Rom_DiskTable and 0:Org_Rom_Disktable+2. | ||
| 1050 | ;SB After this table address has been restored we can reboot by | ||
| 1051 | ;SB invoking the bootstrap loader BIOS interrupt. | ||
| 1052 | |||
| 1053 | xor bx, bx | ||
| 1054 | mov ds, bx | ||
| 1055 | les bx, dword ptr ds:Org_Rom_DiskTable | ||
| 1056 | mov si, DSKADR | ||
| 1057 | mov word ptr ds:[si], bx ;restore offset | ||
| 1058 | mov word ptr ds:[si+2], es ;restore segment | ||
| 1059 | int 19h ;reboot | ||
| 1060 | ;SB34LOAD002**************************************************************** | ||
| 1061 | |||
| 1062 | Write proc near ;show error messages | ||
| 1063 | ;In) DS:SI -> ASCIIZ string. | ||
| 1064 | |||
| 1065 | lodsb ;AN000; | ||
| 1066 | or al, al ;AN000; | ||
| 1067 | jz Endwr ;AN000; | ||
| 1068 | ;SB34LOAD003**************************************************************** | ||
| 1069 | ;SB Write the character in al to the screen. | ||
| 1070 | ;SB Use Video service 'Write teletype to active page' (ROM_TELETYPE) | ||
| 1071 | ;SB Use normal character attribute | ||
| 1072 | mov ah, ROM_TELETYPE | ||
| 1073 | mov bl, 7 ;"normal" attribute ? | ||
| 1074 | int 10h ;video write | ||
| 1075 | ;SB34LOAD003**************************************************************** | ||
| 1076 | jmp Write ;AN000; | ||
| 1077 | Endwr: ;AN000; | ||
| 1078 | ret ;AN000; | ||
| 1079 | Write endp | ||
| 1080 | ; | ||
| 1081 | |||
| 1082 | ;include MSbtmes.inc ;AN000; | ||
| 1083 | include MSbio.cl1 ;AN001; | ||
| 1084 | |||
| 1085 | Relocate_Length equ $ - start | ||
| 1086 | Total_Length label byte | ||
| 1087 | LoadBIO_Size equ $ - Start | ||
| 1088 | |||
| 1089 | cseg ends | ||
| 1090 | end start | ||