summaryrefslogtreecommitdiff
path: root/v4.0/src/BIOS/MSLOAD.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/BIOS/MSLOAD.ASM')
-rw-r--r--v4.0/src/BIOS/MSLOAD.ASM1090
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
2page ,132;
3title 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
26IF1
27 %OUT ASSEMBLING: Non-Contiguous IBMBIO Loader (MSLOAD)
28 %OUT
29
30ENDIF
31
32
33DSKADR = 1Eh * 4 ;ROM bios diskette table vector position
34
35bootseg segment at 0h
36
37
38 org 7C00h
39Boot_Sector label byte
40bootseg ends
41
42
43dosloadseg segment at 70h
44 org 00h
45IBMBIO_Address label byte
46
47dosloadseg ends
48
49
50cseg segment public para 'code'
51 assume cs:cseg,ds:nothing,es:nothing,ss:nothing
52
53include MSload.inc
54include Bootform.inc ;AN000; Extended bpb, boot record defintion.
55include versiona.inc ;AN001; Version number for SYS.COM
56
57sec9 equ 522h ;;** 8/3/87 DCL
58
59BIOOFF equ 700h
60;
61org 0h
62
63start:
64 jmp Save_Input_Values
65SYS_Version dw EXPECTED_VERSION ;AN001; From VERSIONA.INC file
66Mystacks dw 64 dup (0) ;AN000; local stack
67MyStack_ptr label word
68
69;local data
70Number_Of_Heads dw 0
71Size_Cluster dw 0
72Start_Sector_L dw 0
73Start_Sector_H dw 0 ;J.K.
74Temp_H dw 0 ;J.K. For 32 bit calculation
75Temp_Cluster dw 0 ;J.K. Temporary place for cluster number
76Last_Fat_SecNum dw -1 ;Fat sector number starting from the first fat entry.
77Sector_Count dw 0
78Number_Of_FAT_Sectors dw 0
79Hidden_Sectors_L dw 0
80Hidden_Sectors_H dw 0 ;J.K.
81Sector_Size dw 0
82Reserved_Sectors dw 0
83Last_Found_Cluster dw 0
84Next_BIO_Location dw 0
85First_Sector_L dw 0
86First_Sector_H dw 0 ;J.K.
87Drive_Lim_L dw 0 ;J.K. Max. number of sectors
88Drive_Lim_H dw 0 ;J.K.
89Sectors_Per_Track dw 0
90Drive_Number db 0
91FAT_Size db 0
92Media_Byte db 0
93EOF db 0
94Org_Rom_Disktable dd 0
95FAT_Segment dw 0
96Sectors_Per_Cluster db 0
97
98subttl Save Input Values
99page
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;----------------------------------------------------------------------
139Save_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;
203subttl Relocate
204page
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;
228Relocate:
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
263Dumbbb proc far ;AN000;
264 ret ;AN000;
265Dumbbb 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
283subttl Setup Stack
284page
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
303Setup_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
313subttl Find_Cluster_Size
314page
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;----------------------------------------------------------------------
336Find_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
353subttl Determine FAT size
354page
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;----------------------------------------------------------------------
372Determine_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
427subttl Read_In_FirstClusters
428page
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
459Read_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
486subttl Set_Next_Cluster_Number
487page
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;------------------------------------------------------------------
507Set_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
511subttl Read In FAT
512page
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;
557subttl Keep Loaded BIO
558page
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;----------------------------------------------------------------------
591Keep_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
609subttl Get Contiguous Clusters
610page
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;----------------------------------------------------------------------
649Get_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
684subttl GOTO IBMBIO
685page
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;----------------------------------------------------------------------
716GO_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
726subttl Disk Read
727page
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;----------------------------------------------------------------------
774Disk_Read:
775
776;
777; convert a logical sector into Track/sector/head. AX has the logical
778; sector number
779;
780DODIV:
781 MOV cx,5 ;5 retries
782
783Try_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
801Got_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;
851Read_Error: ;AN000;
852 jmp ErrorOut ;AN000;
853
854Read_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
866Read_Finished:
867 RET
868
869subttl GET NEXT FAT ENTRY
870page
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;----------------------------------------------------------------------
919Get_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;
943Ok_cluster: ;AN000;
944 mov ax, es:[bx] ;AN000;
945Even_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
959Odd_Result:
960 mov cl,4 ;AN000;Keep high 12 bits for odd
961 shr ax,cl
962Test_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
967Got_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
976Not_Last_Cluster:
977 mov cs:EOF,not END_OF_FILE ;Assume last cluster
978
979Got_Cluster_Done:
980 pop es
981 ret
982
983
984Get_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;
1021GFS_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;
1030Get_Fat_Sector endp ;AN000;
1031
1032
1033Errorout: ;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
1062Write 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;
1077Endwr: ;AN000;
1078 ret ;AN000;
1079Write endp
1080;
1081
1082;include MSbtmes.inc ;AN000;
1083include MSbio.cl1 ;AN001;
1084
1085Relocate_Length equ $ - start
1086Total_Length label byte
1087LoadBIO_Size equ $ - Start
1088
1089cseg ends
1090 end start