1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
|
Page 60,132 ; SCCSID = @(#)msboot.asm 1.1 85/05/13
TITLE BOOT SECTOR 1 OF TRACK 0 - BOOT LOADER
; Rev 1.0 ChrisP, AaronR and others. 2.0 format boot
;
; Rev 3.0 MarkZ PC/AT enhancements
; 2.50 in label
; Rev 3.1 MarkZ 3.1 in label due to vagaries of SYSing to IBM drive D's
; This resulted in the BPB being off by 1. So we now trust
; 2.0 and 3.1 boot sectors and disbelieve 3.0.
;
; Rev 3.2 LeeAc Modify layout of extended BPB for >32M support
; Move PHYDRV to 3rd byte from end of sector
; so that it won't have to be moved again
; FORMAT and SYS count on PHYDRV being in a known location
;
; Rev. 3.3 D.C. L. Changed Sec 9 EOT field from 15 to 18. May 29, 1986.
;
; Rev 3.31 MarkT The COUNT value has a bogus check (JBE????) to determine
; if we've loaded in all the sectors of IBMBIO. This will
; cause too big of a load if the sectors per track is high
; enough, causing either a stack overflow or the boot code
; to be overwritten.
;
; Rev 4.00 J. K. For DOS 4.00 Modified to handle the extended BPB, and
; 32 bit sector number calculation to enable the primary
; partition be started beyond 32 MB boundary.
;
;
; The ROM in the IBM PC starts the boot process by performing a hardware
; initialization and a verification of all external devices. If all goes
; well, it will then load from the boot drive the sector from track 0, head 0,
; sector 1. This sector is placed at physical address 07C00h. The initial
; registers are set up as follows: CS=DS=ES=SS=0. IP=7C00h, SP=0400H.
;
; The code in this sector is responsible for locating the MSDOS device drivers
; (IBMBIO) and for placing the directory sector with this information at
; physical address 00500h. After loading in this sector, it reads in the
; entirety of the BIOS at BIOSEG:0 and does a long jump to that point.
;
; If no BIOS/DOS pair is found an error message is displayed and the user is
; prompted to reinsert another disk. If there is a disk error during the
; process, a message is displayed and things are halted.
;
; At the beginning of the boot sector, there is a table which describes the
; MSDOS structure of the media. This is equivalent to the BPB with some
; additional information describing the physical layout of the driver (heads,
; tracks, sectors)
;
;==============================================================================
;REVISION HISTORY:
;AN000 - New for DOS Version 4.00 - J.K.
;AC000 - Changed for DOS Version 4.00 - J.K.
;AN00x - PTM number for DOS Version 4.00 - J.K.
;==============================================================================
;AN001; d52 Make the fixed positioned variable "CURHD" to be local. 7/6/87 J.K.
;AN002; d48 Change head settle at boot time. 7/7/87 J.K.
;AN003; P1820 New message SKL file 10/20/87 J.K.
;AN004; D304 New structrue of Boot record for OS2. 11/09/87 J.K.
;==============================================================================
ORIGIN EQU 7C00H ; Origin of bootstrap LOADER
BIOSEG EQU 70H ; destingation segment of BIOS
BioOff EQU 700H ; offset of bios
cbSec EQU 512
cbDirEnt EQU 32
DirOff EQU 500h
IBMLOADSIZE equ 3 ;J.K. Size of IBMLOAD module in sectors
ROM_DISKRD equ 2
include version.inc
;
; Define the destination segment of the BIOS, including the initialization
; label
;
SEGBIOS SEGMENT AT BIOSEG
BIOS LABEL BYTE
SEGBIOS ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
; ORG DirOff + 1Ch
;BiosFS LABEL WORD
ORG ORIGIN
DSKADR = 1EH*4 ;POINTER TO DRIVE PARAMETERS
Public $START
$START:
JMP START
;----------------------------------------------------------
;
; THE FOLLOWING DATA CONFIGURES THE BOOT PROGRAM
; FOR ANY TYPE OF DRIVE OR HARDFILE
;
;J.K. Extened_BPB
if ibmcopyright
DB "IBM "
else
DB "MSDOS"
endif
DB "4.0" ;AN005;
ByteSec DW cbSec ; SIZE OF A PHYSICAL SECTOR
DB 8 ; SECTORS PER ALLOCATION UNIT
cSecRes DW 1 ; NUMBER OF RESERVED SECTORS
cFat DB 2 ; NUMBER OF FATS
DirNum DW 512 ; NUMBER OF DIREC ENTRIES
cTotSec DW 4*17*305-1 ; NUMBER OF SECTORS - NUMBER OF HIDDEN SECTORS
; (0 when 32 bit sector number)
MEDIA DB 0F8H ; MEDIA BYTE
cSecFat DW 8 ; NUMBER OF FAT SECTORS
SECLIM DW 17 ; SECTORS PER TRACK
HDLIM DW 4 ; NUMBER OF SURFACES
Ext_cSecHid label dword
cSecHid_L DW 1 ;AN000; NUMBER OF HIDDEN SECTORS
cSecHid_H dw 0 ;AN000; high order word of Hiden Sectors
Ext_cTotSec label dword
ctotsec_L dw 0 ;AN000; 32 bit version of NUMBER OF SECTORS
ctotsec_H dw 0 ;AN000; (when 16 bit version is zero)
;
Phydrv db 80h ;AN004;
Curhd db 0h ;AN004; Current Head
Ext_Boot_Sig db 41 ;AN000;
Boot_Serial dd 0 ;AN000;
Boot_Vol_Label db 'NO NAME ' ;AN000;
Boot_System_id db 'FAT12 ' ;AN000;
;J.K. Danger!!! If not 32 bit sector number calculation, FORMAT should
;set the value of cSecHid_h and Ext_cTotSec to 0 !!!
;
;
Public UDATA
UDATA LABEL byte
Sec9 equ byte ptr UDATA+0 ;11 byte diskette parm. table
BIOS$_L EQU WORD PTR UDATA+11
BIOS$_H equ word ptr UDATA+13 ;AN000;
CURTRK EQU WORD PTR UDATA+15
CURSEC EQU BYTE PTR UDATA+17
DIR$_L EQU WORD PTR UDATA+18
Dir$_H equ word ptr UDATA+20 ;AN000;
START:
;
; First thing is to reset the stack to a better and more known place. The ROM
; may change, but we'd like to get the stack in the correct place.
;
CLI ;Stop interrupts till stack ok
XOR AX,AX
MOV SS,AX ;Work in stack just below this routine
ASSUME SS:CODE
MOV SP,ORIGIN
PUSH SS
POP ES
ASSUME ES:CODE
;
; We copy the disk parameter table into a local area. We scan the table above
; for non-zero parameters. Any we see get changed to their non-zero values.
;
;J.K. We copy the disk parameter table into a local area (overlayed into the
;code), and set the head settle time to 1, and End of Track to SECLIM given
;by FORMAT.
MOV BX,DSKADR
LDS SI,DWORD PTR SS:[BX] ; get address of disk table
PUSH DS ; save original vector for possible
PUSH SI ; restore
PUSH SS
PUSH BX
MOV DI,offset Sec9
MOV CX,11
CLD
if $ le BIOS$_L
%OUT Don't destroy unexcuted code yet!!!
endif
repz movsb ;AN000;
push es ;AN000;
pop ds ;AN000; DS = ES = code = 0.
assume ds:code ;AN000;
; mov byte ptr [di-2], 1 ;AN000; Head settle time
;J.K. Change the head settle to 15 ms will slow the boot time quite a bit!!!
mov byte ptr [di-2], 0fh ;AN002; Head settle time
mov cx, SECLIM ;AN004;
mov byte ptr [di-7], cl ;AN000; End of Track
;
; Place in new disk parameter table vector.
;
MOV [BX+2],AX
MOV [BX],offset SEC9
;
; We may now turn interrupts back on. Before this, there is a small window
; when a reboot command may come in when the disk parameter table is garbage
;
STI ;Interrupts OK now
;
; Reset the disk system just in case any thing funny has happened.
;
INT 13H ;Reset the system
; JC RERROR
jc CKErr ;AN000;
;
; The system is now prepared for us to begin reading. First, determine
; logical sector numbers of the start of the directory and the start of the
; data area.
xor ax,ax ;AN000;
cmp cTotSec,ax ;AN000; 32 bit calculation?
je Dir_Cont ;AN000;
mov cx,cTotSec ;AN000;
mov cTotSec_L,cx ;AN000; cTotSec_L,cTotSec_H will be used for calculation
Dir_Cont: ;AN000;
MOV AL,cFat ;Determine sector dir starts on
MUL cSecFat ;DX;AX
ADD AX,cSecHid_L
adc DX,cSecHid_H ;AN000;
ADD AX,cSecRes
ADC DX,0
MOV [DIR$_L],AX ; DX;AX = cFat*cSecFat + cSecRes + cSecHid
mov [DIR$_H],DX ;AN000;
MOV [BIOS$_L],AX
mov [BIOS$_H],DX ;AN000;
;
; Take into account size of directory (only know number of directory entries)
;
MOV AX,cbDirEnt ; bytes per directory entry
MUL DirNum ; convert to bytes in directory
MOV BX,ByteSec ; add in sector size
ADD AX,BX
DEC AX ; decrement so that we round up
DIV BX ; convert to sector number
ADD [BIOS$_L],AX ; Start sector # of Data area
adc [BIOS$_H],0 ;AN000;
;
; We load in the first directory sector and examine it to make sure the the
; BIOS and DOS are the first two directory entries. If they are not found,
; the user is prompted to insert a new disk. The directory sector is loaded
; into 00500h
;
MOV BX,DirOff ; sector to go in at 00500h
mov dx,[DIR$_H] ;AN000;
MOV AX,[DIR$_L] ; logical sector of directory
CALL DODIV ; convert to sector, track, head
jc CKErr ;AN000; Overflow? BPB must be wrong!!
; MOV AX,0201H ; disk read 1 sector
mov al, 1 ;AN000; disk read 1 sector
CALL DOCALL ; do the disk read
JB CKERR ; if errors try to recover
;
; Now we scan for the presence of IBMBIO COM and IBMDOS COM. Check the
; first directory entry.
;
MOV DI,BX
MOV CX,11
MOV SI,OFFSET BIO ; point to "ibmbio com"
REPZ CMPSB ; see if the same
JNZ CKERR ; if not there advise the user
;
; Found the BIOS. Check the second directory entry.
;
LEA DI,[BX+20h]
MOV SI,OFFSET DOS ; point to "ibmdos com"
MOV CX,11
REPZ CMPSB
JZ DoLoad
;
; There has been some recoverable error. Display a message and wait for a
; keystroke.
;
CKERR: MOV SI,OFFSET SYSMSG ; point to no system message
ErrOut: CALL WRITE ; and write on the screen
XOR AH,AH ; wait for response
INT 16H ; get character from keyboard
POP SI ; reset disk parameter table back to
POP DS ; rom
POP [SI]
POP [SI+2]
INT 19h ; Continue in loop till good disk
Load_Failure:
pop ax ;adjust the stack
pop ax
pop ax
jmp short Ckerr ;display message and reboot.
;J.K. We don't have the following error message any more!!!
;J.K. Sysmsg is fine. This will save space by eliminating DMSSG message.
;RERROR: MOV SI,OFFSET DMSSG ; DISK ERROR MESSAGE
; JMP ErrOut
;
; We now begin to load the BIOS in. Compute the number of sectors needed.
; J.K. All we have to do is just read in sectors contiguously IBMLOADSIZE
; J.K. times. We here assume that IBMLOAD module is contiguous. Currently
; J.K. we estimate that IBMLOAD module will not be more than 3 sectors.
DoLoad:
mov BX,BioOff ;offset of ibmbio(IBMLOAD) to be loaded.
mov CX,IBMLOADSIZE ;# of sectors to read.
mov AX, [BIOS$_L] ;Sector number to read.
mov DX, [BIOS$_H] ;AN000;
Do_While: ;AN000;
push AX ;AN000;
push DX ;AN000;
push CX ;AN000;
call DODIV ;AN000; DX;AX = sector number.
jc Load_Failure ;AN000; Adjust stack. Show error message
mov al, 1 ;AN000; Read 1 sector at a time.
;This is to handle a case of media
;when the first sector of IBMLOAD is the
;the last sector in a track.
call DOCALL ;AN000; Read the sector.
pop CX ;AN000;
pop DX ;AN000;
pop AX ;AN000;
jc CkErr ;AN000; Read error?
add AX,1 ;AN000; Next sector number.
adc DX,0 ;AN000;
add BX,ByteSec ;AN000; adjust buffer address.
loop Do_While ;AN000;
; MOV AX,BiosFS ; get file size
; XOR DX,DX ; presume < 64K
; DIV ByteSec ; convert to sectors
; INC AL ; reading in one more can't hurt
; MOV COUNT,AL ; Store running count
; MOV AX,BIOS$ ; get logical sector of beginning of BIOS
; MOV BIOSAV,AX ; store away for real bios later
; MOV BX,BioOff ; Load address from BIOSSEG
;
; Main read-in loop.
; ES:BX points to area to read.
; Count is the number of sectors remaining.
; BIOS$ is the next logical sector number to read
;
;LOOPRD:
; MOV AX,BIOS$ ; Starting sector
; CALL DODIV
;
; CurHD is the head for this next disk request
; CurTrk is the track for this next request
; CurSec is the beginning sector number for this request
;
; Compute the number of sectors that we may be able to read in a single ROM
; request.
;
; MOV AX,SECLIM
; SUB AL,CURSEC
; INC AX
;
; AX is the number of sectors that we may read.
;
;
;New code for Rev 3.31
;*****************************************************************************
; CMP COUNT,AL ;Is sectors we can read more than we need?
; JAE GOT_SECTORS ;No, it is okay
; MOV AL,COUNT ;Yes, only read in what is left
;GOT_SECTORS:
;*****************************************************************************
;End of change
;
; PUSH AX
; CALL DOCALL
; POP AX
; JB RERROR ; If errors report and go to ROM BASIC
; SUB COUNT,AL ; Are we finished?
;
;Old code replaced by Rev 3.3
;********************************************************************
; JBE DISKOK ; Yes -- transfer control to the DOS
;********************************************************************
;New code for Rev 3.3
;
; JZ DISKOK ; Yes -- transfer control to the DOS
;********************************************************************
;End of change
;
; ADD BIOS$,AX ; increment logical sector position
; MUL ByteSec ; determine next offset for read
; ADD BX,AX ; (BX)=(BX)+(SI)*(Bytes per sector)
; JMP LOOPRD ; Get next track
;
; IBMINIT requires the following input conditions:
;
; DL = INT 13 drive number we booted from
; CH = media byte
;J.K.I1. BX was the First data sector on disk (0-based)
;J.K.I1. IBMBIO init routine should check if the boot record is the
;J.K.I1. extended one by looking at the extended_boot_signature.
;J.K.I1. If it is, then should us AX;BX for the starting data sector number.
DISKOK:
MOV CH,Media
MOV DL,PhyDrv
MOV bx,[BIOS$_L] ;AN000; J.K.I1.Get bios sector in bx
mov ax,[BIOS$_H] ;AN000; J.K.I1.
JMP FAR PTR BIOS ;CRANK UP THE DOS
WRITE: LODSB ;GET NEXT CHARACTER
OR AL,AL ;clear the high bit
JZ ENDWR ;ERROR MESSAGE UP, JUMP TO BASIC
MOV AH,14 ;WILL WRITE CHARACTER & ATTRIBUTE
MOV BX,7 ;ATTRIBUTE
INT 10H ;PRINT THE CHARACTER
JMP WRITE
; convert a logical sector into Track/sector/head. AX has the logical
; sector number
; J.K. DX;AX has the sector number. Because of not enough space, we are
; going to use Simple 32 bit division here.
; Carry set if DX;AX is too big to handle.
;
DODIV:
cmp dx,Seclim ;AN000; To prevent overflow!!!
jae DivOverFlow ;AN000; Compare high word with the divisor.
DIV SECLIM ;AX = Total tracks, DX = sector number
INC DL ;Since we assume SecLim < 255 (a byte), DH =0.
;Cursec is 1-based.
MOV CURSEC, DL ;save it
XOR DX,DX
DIV HDLIM
MOV CURHD,DL ;Also, Hdlim < 255.
MOV CURTRK,AX
clc ;AN000;
ret ;AN000;
DivOverFlow: ;AN000;
stc ;AN000;
EndWR:
ret
;
;J.K.We don't have space for the following full 32 bit division.
; convert a logical sector into Track/sector/head. AX has the logical
; sector number
; J.K. DX;AX has the sector number.
;DODIV:
; push ax
; mov ax,dx
; xor dx,dx
; div SecLim
; mov Temp_H,ax
; pop ax
; div SecLim ;J.K.Temp_H;AX = total tracks, DX=sector
; INC DL ;Since we assume SecLim < 255 (a byte), DH =0.
; ;Cursec is 1-based.
; MOV CURSEC, DL ;save it
; push ax
; mov ax,Temp_H
; XOR DX,DX
; DIV HDLIM
; mov Temp_H,ax
; pop ax
; div HdLim ;J.K.Temp_H;AX=total cyliners,DX=head
; MOV CURHD,DL ;Also, Hdlim < 255.
; cmp Temp_H,0
; ja TooBigToHandle
; cmp ax, 1024
; ja TooBigToHandle
; MOV CURTRK,AX
;ENDWR: RET
;TooBigToHandle:
; stc
; ret
;
; Issue one read request. ES:BX have the transfer address, AL is the number
; of sectors.
;
DOCALL: MOV AH,ROM_DISKRD ;AC000;=2
MOV DX,CURTRK
MOV CL,6
SHL DH,CL
OR DH,CURSEC
MOV CX,DX
XCHG CH,CL
MOV DL, PHYDRV
mov dh, curhd
INT 13H
RET
; include ibmbtmes.inc
include boot.cl1 ;AN003;
IF IBMCOPYRIGHT
BIO DB "IBMBIO COM"
DOS DB "IBMDOS COM"
ELSE
BIO DB "IO SYS"
DOS DB "MSDOS SYS"
ENDIF
Free EQU (cbSec - 4) - ($-$start) ;AC000;
;Free EQU (cbSec - 5) - ($-$start)
if Free LT 0
%out FATAL PROBLEM:boot sector is too large
endif
org origin + (cbSec - 2) ;AN004;
; org origin + (cbSec - 5)
;Warning!! Do not change the position of following unless
;Warning!! you change BOOTFORM.INC (in COMMON subdirectory) file.
;Format should set this EOT value for IBMBOOT.
;FEOT db 12h ;AN000; set by FORMAT. AN004;Use SecLim in BPB instead.
; FORMAT and SYS count on CURHD,PHYDRV being right here
;J.K. CURHD has been deleted since it is not being used by anybody.
;CURHD DB ? ;AN001;Unitialized (J.K. Maybe don't need this).
;PHYDRV db 0 ;AN000;moved into the header part.
; Boot sector signature
db 55h,0aah
CODE ENDS
END
|