3 title Non
-Contiguous IBMBIO Loader
(MSLOAD
)
4 ;==============================================================================
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 ;==============================================================================
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.
27 %
OUT ASSEMBLING
: Non
-Contiguous IBMBIO Loader
(MSLOAD
)
33 DSKADR
= 1Eh
* 4 ;ROM bios diskette table vector position
39 Boot_Sector
label byte
43 dosloadseg
segment at 70h
45 IBMBIO_Address
label byte
50 cseg
segment public para
'code'
51 assume
cs:cseg
,ds:nothing
,es:nothing
,ss:nothing
54 include Bootform
.inc ;AN000; Extended bpb, boot record defintion.
55 include versiona
.inc ;AN001; Version number for SYS.COM
57 sec9 equ 522h
;;** 8/3/87 DCL
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
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.
78 Number_Of_FAT_Sectors dw 0
80 Hidden_Sectors_H dw 0 ;J.K.
83 Last_Found_Cluster dw 0
84 Next_BIO_Location 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
94 Org_Rom_Disktable dd 0
96 Sectors_Per_Cluster db 0
98 subttl Save Input Values
100 ;***********************************************************************
102 ;***********************************************************************
106 ; DL = INT 13 drive number we booted from
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 ;
116 ; BX = first data sector on disk
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
126 ; Reserved_Sectors = reserved sectors
127 ; Sectors_Per_Track = Sectors/track
128 ; Number_Of_Heads = heads/cylinder
134 ;-----------------------------------------------------------------------
136 ; Save input information and BPB informations from the boot record.
138 ;----------------------------------------------------------------------
142 mov First_Sector_L
,bx ;AC000;
145 mov word ptr Org_Rom_Disktable
, si
147 pop word ptr Org_Rom_Disktable
+2
152 push es ;;** DCL 8/3/87
153 mov es,cx ;;** DCL 8/3/87
154 assume
es:Bootseg
;;** DCL 8/3/87
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
159 MOV DI,SEC9
; ES:DI -> NEW TABLE ARR 2.41
160 MOV CX,11 ; taken from ibmboot.asm ARR 2.41
162 REP MOVSB ; COPY TABLE ARR 2.41
164 POP DS ; DS = 0 ARR 2.41
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
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;
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.
192 cmp Boot_Sector
.EXT_BOOT_SIG
, EXT_BOOT_SIGNATURE
;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)
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;
206 ;***********************************************************************
208 ;***********************************************************************
212 ; Relocate the loader code to top-of-memory.
216 ; Output: Code and data relocated.
217 ; ax,cx,si,di destroyed
220 ;-----------------------------------------------------------------------
221 ; Copy code from Start to Top of memory.
223 ; The length to copy is Total_length
225 ; Jump to relocated code
226 ;-----------------------------------------------------------------------
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.
240 int 12h
;get system memory size in Kbytes
242 shl ax,cl ;memory size in paragraphs
243 ;SB34LOAD000****************************************************************
245 mov dx, cs:Sector_Size
;AN000;
249 mov cs:Fat_Segment
, ax ;AN000;This will be used for FAT sector
250 mov dx, offset total_length
;AN000;
254 mov es, ax ;AN000;es:di -> place be relocated.
256 pop ds ;AN000;ds:si -> source
257 mov cx, offset total_length
;AN000;
261 mov ax, offset Setup_stack
;AN000;
262 push ax ;AN000;massage stack for destination of cs:ip
263 Dumbbb proc
far ;AN000;
268 ; push cs ;Set up ds segreg
270 ; xor ax,ax ;Set up ES segreg
273 ; assume es:bootseg,ds:cseg
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
285 ;***********************************************************************
287 ;***********************************************************************
295 ;-----------------------------------------------------------------------
296 ; First thing is to reset the stack to a better and more known place.
298 ; Move the stack to just under the boot record and relocation area (0:7C00h)
300 ; Preserve all other registers
301 ;----------------------------------------------------------------------
304 assume
ds:nothing
, es:nothing
, ss:nothing
305 ; CLI ;Stop interrupts till stack ok
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
313 subttl Find_Cluster_Size
315 ;***********************************************************************
317 ;***********************************************************************
319 ; Input: BPB information in loaded boot record at 0:7C00h
325 ; BX = Sectors/Cluster
328 ;-----------------------------------------------------------------------
330 ; Get Bytes/sector from BPB
332 ; Get sectors/cluster from BPB
334 ; Bytes/cluster = Bytes/sector * sector/cluster
335 ;----------------------------------------------------------------------
338 ;For the time being just assume the boot record is valid and the BPB
346 mov ax,Boot_Sector
.EXT_BOOT_BPB
.EBPB_BYTESPERSECTOR
;AC000;Get BPB bytes/sector
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
353 subttl Determine FAT size
355 ;***********************************************************************
357 ;***********************************************************************
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.
368 ; cs:Fat_Size = FAT12_bit or FAT16_bit
369 ; All other registers destroyed
371 ;----------------------------------------------------------------------
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
381 sbb dx, 0 ;AN000;now, dx;ax = tatal sectors - fat sectors
382 mov bx, Boot_Sector
.EXT_BOOT_BPB
.EBPB_ROOTENTRIES
;AN000;
384 shr bx, cl ;AN000;Sectors for dir entries = dir entries / Num_DIR_Sector
388 mov cl, Boot_Sector
.EXT_BOOT_BPB
.EBPB_SECTORSPERCLUSTER
;AN000;
393 mov cs:Temp_H
, ax ;AN000;
395 ;J.K. We assume that cx > dx.
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
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
407 ; mov di,offset Relocate_Start
408 ; mov cs:Sector_Count,1
410 ; mov si,offset Relocate_Start+1C2h
415 ; mov cs:FAT_Size,FAT12_bit ;Assume 12 bit fat
416 ; cmp byte ptr [si],1
418 ; mov cs:FAT_Size,FAT16_bit ;Assume 12 bit fat
419 ; cmp byte ptr [si],4
423 ; ;xxxxxxxxxxxxxxxxxxxxxxxxxx error
427 subttl Read_In_FirstClusters
429 ;***********************************************************************
430 ; Read_In_FirstClusters
431 ;***********************************************************************
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.
439 ; IBMLOADSIZE - Make sure this value is the same as the one in
440 ; MSBOOT program when you build the new version!!!!!
442 ; Sectors_Per_Cluster
447 ; Output: MSLOAD program is fully covered in a cluster boundary.
448 ; AX = # of clusters we read in so far.
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
457 ;-----------------------------------------------------------------------
459 Read_In_FirstClusters:
460 mov ax, IBMLOADSIZE
;AN000;
461 div cs:Sectors_Per_Cluster
;AN000;
463 je Set_Next_Cluster_Number
;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;
475 mov di, BIOOFF
;AN000;
476 mul cs:Size_Cluster
;AN000;AX = # of bytes read in before this cluster
480 mov al, cs:Sectors_Per_Cluster
;AN000;
481 mov cs:Sector_Count
, ax ;AN000;
482 call Disk_Read
;AN000;
484 inc ax ;AN000;# of clusters read in so far.
486 subttl Set_Next_Cluster_Number
488 ;***********************************************************************
489 ; Set_Next_Cluster_Number
490 ;***********************************************************************
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.
499 ; AX = # of clusters read in so far.
503 ; cs:Last_Found_Cluster
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)
513 ;***********************************************************************
515 ;***********************************************************************
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
531 ; All sectors destroyed
534 ;-----------------------------------------------------------------------
535 ; Get number of sectors in FAT
539 ; Read in the sectors
541 ;----------------------------------------------------------------------
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
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;
557 subttl Keep Loaded BIO
559 ;***********************************************************************
561 ;***********************************************************************
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)
570 ; cs:Last_Found_Cluster = number of clusters used for loader+2
574 ; DI = Next offset to load IBMBIO code
575 ; AX,BX,CX,DX,SI destroyed
577 ; cs:Next_BIO_Location = DI on output
578 ; cs:Last_Cluster = last cluster loaded
581 ;-----------------------------------------------------------------------
582 ;Number of clusters loaded+2 is in cs:Last_Found_Cluster
584 ;Multiply cluster * cluster size in bytes to get total loaded for MSLOAD
586 ;Subtract TOTAL_LOADED - LOADBIO_SIZE to get loaded IBMBIO in last cluster
588 ;Relocate this piece of IBMBIO down to 70:0
590 ;----------------------------------------------------------------------
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
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
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
609 subttl Get Contiguous Clusters
611 ;***********************************************************************
612 ; Get_Contiguous_Clusters
613 ;***********************************************************************
615 ; Notes: Go find clusters as long as they are contiguous
620 ; cs:Next_BIO_Location
627 ; Calls: Get_Next_FAT_Entry
628 ;-----------------------------------------------------------------------
630 ;Set cs:Sector_Count to Sectors per cluster
632 ;Call Get_Next_FAT_Entry to get next cluster in file
638 ; {Call Get_Next_FAT_Entry
640 ; IF (New cluster is contig to old cluster)
641 ; {Add sectors per cluster to cs:Sector_Count
648 ;----------------------------------------------------------------------
649 Get_Contiguous_Cluster:
651 mov al,cs:Sectors_Per_Cluster
;Assume we will get one cluster
652 mov cs:Sector_Count
,ax
654 call Get_Next_Fat_Entry
;Go get it in AX
656 mov cs:Last_Found_Cluster
,ax ;Update the last one found
657 cmp cs:EOF
,END_OF_FILE
661 ;Got_Contig_Clusters:
664 sub ax,2 ;Zero base the cluster
666 mov cl,cs:Sectors_Per_Cluster
;Get sectors per cluster
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
677 pop ax ;Get back total sectors read in
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
686 ;***********************************************************************
688 ;***********************************************************************
692 ; Set up required registers for IBMBIO, then jump to it (70:0)
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)
704 ; DL = INT 13 drive number we booted from
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.
711 ;-----------------------------------------------------------------------
713 ; Set up registers for MSINIT then do Far Jmp
715 ;----------------------------------------------------------------------
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
728 ;***********************************************************************
730 ;***********************************************************************
734 ; Read in the cs:Sector_Count number of sectors at ES:DI
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
746 ; cs:Number_Of_Sectors
748 ; cs:Sectors_Per_Track
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
757 ; Increment actual sector number to get 1 based
759 ; The quotient is the number of tracks - divide by heads to get the cyl
761 ; The remainder is actual head, the quotient is cylinder
763 ; Figure the number of sectors in that track, set AL to this
767 ; If Error, Do RESET, then redo the INT 13h
769 ; If successful read, Subtract # sectors read from Sector_Count, Add to Logical
770 ; Sector, add #sectors read * Sector_Size to BX;
772 ; If Sector_Count <> 0 Do next read
773 ;----------------------------------------------------------------------
777 ; convert a logical sector into Track/sector/head. AX has the logical
785 MOV AX,cs:Start_Sector_L
;AC000; Get starting sector
786 mov dx, cs:Start_Sector_H
;AN000;
791 DIV word ptr cs:Sectors_Per_Track
792 mov cs:Temp_H
, 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
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
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
809 DIV word ptr cs:Number_Of_Heads
;Start cyl in ax,head in DL
810 mov cs:Temp_h
, 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
816 ; Issue one read request. ES:BX have the transfer address, AL is the number
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)
829 push ax ;Save length of read
831 ; Issue one read request. ES:BX have the transfer address, AL is the number
836 pop cx ;Get retry count back
838 mov bx,di ;Get offset
841 mov dl,cs:Drive_Number
846 ; loop Try_Read ;AC000;
847 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error
849 jz Read_Error
;AN000;
855 xor ah,ah ;Mask out read command, just get # read
856 sub cs:Sector_Count
,ax ;Bump number down
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
862 mov ax,cs:Sector_Size
;Bytes per sector
863 mul bx ;Get total bytes read
864 add di,ax ;Add it to offset
869 subttl GET NEXT FAT
ENTRY
871 ;***********************************************************************
873 ;***********************************************************************
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.
884 ; cs:Last_Found_Cluster
889 ; cs:Last_Found_Cluster (updated)
891 ; Calls: Get_Fat_Sector
892 ;-----------------------------------------------------------------------
893 ; Get Last_Found_Cluster
896 ; {IF (Last_Found_Cluster = FFF8 - FFFF)
899 ; {Get offset by multiply cluster by 2}
902 ; {IF (Last_Found_Cluster = FF8 - FFF)
905 ; {Get offset by - multiply cluster by 3
907 ; Rotate right to divide by 2
909 ; IF (CY set - means odd number)
910 ; {SHR 4 times to keep high twelve bits}
913 ; {AND with 0FFFh to keep low 12 bits}
918 ;----------------------------------------------------------------------
922 mov ax, cs:FAT_Segment
;AN000;
923 mov es, ax ;AN000; es-> Fat area segment
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
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;
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;
944 mov ax, es:[bx] ;AN000;
948 ; mov bl,3 ;Mult by 3
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
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
960 mov cl,4 ;AN000;Keep high 12 bits for odd
963 cmp ax,0FF8h ;Is it last cluster?
964 jae Got_Cluster_Done
;Yep, all done here
965 jmp short Not_Last_CLuster
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
977 mov cs:EOF
,not END_OF_FILE
;Assume last cluster
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
989 ;Out). Corresponding FAT sector read in.
990 ; BX = offset value of the corresponding FAT entry in the FAT sector.
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).
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;
1010 add ax, cs:Hidden_Sectors_L
;AN000;
1011 adc dx, cs:Hidden_Sectors_H
;AN000;
1012 add ax, cs:Reserved_Sectors
;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
1018 call Disk_Read
;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
1030 Get_Fat_Sector endp
;AN000;
1036 mov si, offset Sysmsg
;AN000;
1038 ;SB34LOAD001****************************************************************
1039 ;SB Wait for a keypress on the keyboard. Use the BIOS keyboard interrupt.
1043 int 16h
;read keyboard
1044 ;SB34LOAD001****************************************************************
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.
1055 les bx, dword ptr ds:Org_Rom_DiskTable
1057 mov word ptr ds:[si], bx ;restore offset
1058 mov word ptr ds:[si+2], es ;restore segment
1060 ;SB34LOAD002****************************************************************
1062 Write proc
near ;show error messages
1063 ;In) DS:SI -> ASCIIZ string.
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****************************************************************
1082 ;include MSbtmes.inc ;AN000;
1083 include MSbio
.cl1
;AN001;
1085 Relocate_Length equ
$ - start
1086 Total_Length
label byte
1087 LoadBIO_Size equ
$ - Start