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
|
How It Works -- OS2 Boot Sector
Version 1a
by Hale Landis (landis@sugs.tware.com)
THE "HOW IT WORKS" SERIES
This is one of several How It Works documents. The series
currently includes the following:
* How It Works -- CHS Translation
* How It Works -- Master Boot Record
* How It Works -- DOS Floppy Boot Sector
* How It Works -- OS2 Boot Sector
* How It Works -- Partition Tables
OS2 BOOT SECTOR
Note: I'll leave it to someone else to provide you with a
disassembly of an OS/2 HPFS boot sector, or a Linux boot sector,
or a WinNT boot sector, etc.
This article is a disassembly of a floppy or hard disk boot
sector for OS/2. Apparently OS/2 uses the same boot sector for
both environments. Basically a bootable FAT hard disk partition
looks like a big floppy during the early stages of the system's
boot processing. This sector is at cylinder 0, head 0, sector 1
of a floppy or it is the first sector within a FAT hard disk
partition. OS/2 floppy disk and hard disk boot sectors are
created by the OS/2 FORMAT program.
At the completion of your system's Power On Self Test (POST), INT
19 is called. Usually INT 19 tries to read a boot sector from
the first floppy drive. If a boot sector is found on the floppy
disk, the that boot sector is read into memory at location
0000:7C00 and INT 19 jumps to memory location 0000:7C00.
However, if no boot sector is found on the first floppy drive,
INT 19 tries to read the MBR from the first hard drive. If an
MBR is found it is read into memory at location 0000:7c00 and INT
19 jumps to memory location 0000:7c00. The small program in the
MBR will attempt to locate an active (bootable) partition in its
partition table. If such a partition is found, the boot sector
of that partition is read into memory at location 0000:7C00 and
the MBR program jumps to memory location 0000:7C00. Each
operating system has its own boot sector format. The small
program in the boot sector must locate the first part of the
operating system's kernel loader program (or perhaps the kernel
itself or perhaps a "boot manager program") and read that into
memory.
INT 19 is also called when the CTRL-ALT-DEL keys are used. On
most systems, CTRL-ALT-DEL causes an short version of the POST to
be executed before INT 19 is called.
=====
Where stuff is:
The BIOS Parameter Block (BPB) starts at offset 0.
The boot sector program starts at offset 46.
The messages issued by this program start at offset 198.
The OS/2 boot loader file name starts at offset 1d5.
The boot sector signature is at offset 1fe.
Here is a summary of what this thing does:
1) If booting from a hard disk partition, skip to step 6.
2) Copy Diskette Parameter Table which is pointed to by INT 1E
to the top of memory.
3) Alter the copy of the Diskette Parameter Table.
4) Alter INT 1E to point to altered Diskette Parameter Table at
the top of memory.
5) Do INT 13 AH=00, disk reset call so that the altered
Diskette Parameter Table is used.
6) Compute sector address of the root directory.
7) Read the entire root directory into memory starting at
location 1000:0000.
8) Search the root directory entires for the file OS2BOOT.
9) Read the OS2BOOT file into memory at 0800:0000.
10) Do a far return to enter the OS2BOOT program at 0800:0000.
NOTES:
This program uses the CHS based INT 13H AH=02 to read the FAT
root directory and to read the OS2BOOT file. If the drive is
>528MB, this CHS must be a translated CHS (or L-CHS, see my
BIOS TYPES document). Except for internal computations no
addresses in LBA form are used, another reason why LBA doesn't
solve the >528MB problem.
=====
Here is the entire sector in hex and ascii.
OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F *0123456789ABCDEF*
000000 eb449049 424d2032 302e3000 02100100 *.D.IBM 20.0.....*
000010 02000200 00f8d800 3e000e00 3e000000 *........>...>...*
000020 06780d00 80002900 1c0c234e 4f204e41 *.x....)...#NO NA*
000030 4d452020 20204641 54202020 20200000 *ME FAT ..*
000040 00100000 0000fa33 db8ed3bc ff7bfbba *.......3.....{..*
000050 c0078eda 803e2400 00753d1e b840008e *.....>$..u=..@..*
000060 c026ff0e 1300cd12 c1e0068e c033ff33 *.&...........3.3*
000070 c08ed8c5 367800fc b90b00f3 a41fa118 *....6x..........*
000080 0026a204 001e33c0 8ed8a378 008c067a *.&....3....x...z*
000090 001f8a16 2400cd13 a0100098 f7261600 *....$........&..*
0000a0 03060e00 5091b820 00f72611 008b1e0b *....P.. ..&.....*
0000b0 0003c348 f7f35003 c1a33e00 b800108e *...H..P...>.....*
0000c0 c033ff59 890e4400 58a34200 33d2e873 *.3.Y..D.X.B.3..s*
0000d0 0033db8b 0e11008b fb51b90b 00bed501 *.3.......Q......*
0000e0 f3a65974 0583c320 e2ede335 268b471c *..Yt... ...5&.G.*
0000f0 268b571e f7360b00 fec08ac8 268b571a *&.W..6......&.W.*
000100 4a4aa00d 0032e4f7 e203063e 0083d200 *JJ...2.....>....*
000110 bb00088e c333ff06 57e82800 8d360b00 *.....3..W.(..6..*
000120 cbbe9801 eb03bead 01e80900 bec201e8 *................*
000130 0300fbeb feac0ac0 7409b40e bb0700cd *........t.......*
000140 10ebf2c3 50525103 061c0013 161e00f7 *....PRQ.........*
000150 361800fe c28ada33 d2f7361a 008afa8b *6......3..6.....*
000160 d0a11800 2ac34050 b402b106 d2e60af3 *....*.@P........*
000170 8bca86e9 8a162400 8af78bdf cd1372a6 *......$.......r.*
000180 5b598bc3 f7260b00 03f85a58 03c383d2 *[Y...&....ZX....*
000190 002acb7f afc31200 4f532f32 20212120 *.*......OS/2 !! *
0001a0 53595330 31343735 0d0a0012 004f532f *SYS01475.....OS/*
0001b0 32202121 20535953 30323032 350d0a00 *2 !! SYS02025...*
0001c0 12004f53 2f322021 21205359 53303230 *..OS/2 !! SYS020*
0001d0 32370d0a 004f5332 424f4f54 20202020 *27...OS2BOOT *
0001e0 00000000 00000000 00000000 00000000 *................*
0001f0 00000000 00000000 00000000 000055aa *..............U.*
=====
The first 62 bytes of a boot sector are known as the BIOS
Parameter Block (BPB). Here is the layout of the BPB fields
and the values they are assigned in this boot sector:
db JMP instruction at 7c00 size 2 = eb44
db NOP instruction 7c02 1 90
db OEMname 7c03 8 'IBM 20.0'
dw bytesPerSector 7c0b 2 0200
db sectPerCluster 7c0d 1 01
dw reservedSectors 7c0e 2 0001
db numFAT 7c10 1 02
dw numRootDirEntries 7c11 2 0200
dw numSectors 7c13 2 0000 (use numSectorsHuge)
db mediaType 7c15 1 f8
dw numFATsectors 7c16 2 00d8
dw sectorsPerTrack 7c18 2 003e
dw numHeads 7c1a 2 000e
dd numHiddenSectors 7c1c 4 00000000
dd numSectorsHuge 7c20 4 000d7806
db driveNum 7c24 1 80
db reserved 7c25 1 00
db signature 7c26 1 29
dd volumeID 7c27 4 001c0c23
db volumeLabel 7c2b 11 'NO NAME '
db fileSysType 7c36 8 'FAT '
=====
Here is the boot sector...
The first 3 bytes of the BPB are JMP and NOP instructions.
0000:7C00 EB44 JMP START
0000:7C02 90 NOP
Here is the rest of the BPB.
0000:7C00 eb449049 424d2032 302e3000 02100100 *.D.IBM 20.0.....*
0000:7C10 02000200 00f8d800 3e000e00 3e000000 *........>...>...*
0000:7C20 06780d00 80002900 1c0c234e 4f204e41 *.x....)...#NO NA*
0000:7C30 4d452020 20204641 54202020 20200000 *ME FAT ..*
Additional data areas.
0000:7C30 ........ ........ ........ ....0000 * ..*
0000:7C40 00100000 0000.... ........ ........ *...... *
Note:
0000:7c3e (DS:003e) = number of sectors in the FATs and root dir.
0000:7c42 (DS:0042) = number of sectors in the FAT.
0000:7c44 (DS:0044) = number of sectors in the root dir.
START: START OF BOOT SECTOR PROGRAM
0000:7C46 FA CLI interrupts off
0000:7C47 33DB XOR BX,BX zero BX
0000:7C49 8ED3 MOV SS,BX SS now zero
0000:7C4B BCFF7B MOV SP,7BFF SP now 7bff
0000:7C4E FB STI interrupts on
0000:7C4F BAC007 MOV DX,07C0 set DX to
0000:7C52 8EDA MOV DS,DX 07c0
Are we booting from a floppy or a
hard disk partition?
0000:7C54 803E240000 CMP BYTE PTR [0024],00 is driveNum in BPB 00?
0000:7C59 753D JNZ NOT_FLOPPY jmp if not zero
We are booting from a floppy. The
Diskette Parameter Table must be
copied and altered...
Diskette Parameter Table is pointed to by INT 1E. This
program moves this table to high memory, alters the table, and
changes INT 1E to point to the altered table.
This table contains the following data:
????:0000 = Step rate and head unload time.
????:0001 = Head load time and DMA mode flag.
????:0002 = Delay for motor turn off.
????:0003 = Bytes per sector.
????:0004 = Sectors per track.
????:0005 = Intersector gap length.
????:0006 = Data length.
????:0007 = Intersector gap length during format.
????:0008 = Format byte value.
????:0009 = Head settling time.
????:000a = Delay until motor at normal speed.
Compute a valid high memory address.
0000:7C5B 1E PUSH DS save DS
0000:7C5C B84000 MOV AX,0040 set ES
0000:7C5F 8EC0 MOV ES,AX to 0040 (BIOS data area)
0000:7C61 26 ES: reduce system memory
0000:7C62 FF0E1300 DEC WORD PTR [0013] size by 1024
0000:7C66 CD12 INT 12 get system memory size
0000:7C68 C1E06 SHL AX,06 shift AX (mult by 64)
0000:7C6B 8EC0 MOV ES,AX move to ES
0000:7C6D 33FF XOR DI,DI zero DI
Move the diskette param table to high memory.
0000:7C6F 33C0 XOR AX,AX zero AX
0000:7C71 8ED8 MOV DS,AX DS now zero
0000:7C73 C5367800 LDS SI,[0078] DS:SI = INT 1E vector
0000:7C77 FC CLD clear direction
0000:7C78 B90B00 MOV CX,000B count is 11
0000:7C7B F3 REPZ copy diskette param table
0000:7C7C A4 MOVSB to top of memory
Alter the number of sectors per track
in the diskette param table in high memory.
0000:7C7D 1F POP DS restore DS
0000:7C7E A11800 MOV AX,[0018] get sectorsPerTrack from BPB
0000:7C81 26 ES: alter sectors per track
0000:7C82 A20400 MOV [0004],AL in diskette param table
Change INT 1E to point to altered diskette
param table and do a INT 13 disk reset call.
0000:7C85 1E PUSH DS save DS
0000:7C86 33C0 XOR AX,AX AX now zero
0000:7C88 8ED8 MOV DS,AX DS no zero
0000:7C8A A37800 MOV [0078],AX alter INT 1E vector
0000:7C8D 8C067A00 MOV [007A],ES to point to altered
diskette param table
0000:7C91 1F POP DS restore DS
0000:7C92 8A162400 MOV DL,[0024] driveNum from BPB
0000:7C96 CD13 INT 13 diskette reset
NOT_FLOPPY:
Compute the location and the size of
the root directory. Read the entire
root directory into memory.
0000:7C98 A01000 MOV AL,[0010] get numFAT
0000:7C9B 98 CBW make into a word
0000:7C9C F7261600 MUL WORD PTR [0016] mult by numFatSectors
0000:7CA0 03060E00 ADD AX,[000E] add reservedSectors
0000:7CA4 50 PUSH AX save
0000:7CA5 91 XCHG CX,AX move to CX
0000:7CA6 B82000 MOV AX,0020 dir entry size
0000:7CA9 F7261100 MUL WORD PTR [0011] mult by numRootDirEntries
0000:7CAD 8B1E0B00 MOV BX,[000B] get bytesPerSector
0000:7CB1 03C3 ADD AX,BX add
0000:7CB3 48 DEC AX subtract 1
0000:7CB4 F7F3 DIV BX div by bytesPerSector
0000:7CB6 50 PUSH AX save number of dir sectors
0000:7CB7 03C1 ADD AX,CX add number of fat sectors
0000:7CB9 A33E00 MOV [003E],AX save
0000:7CBC B80010 MOV AX,1000 AX is now 1000
0000:7CBF 8EC0 MOV ES,AX ES is now 1000
0000:7CC1 33FF XOR DI,DI DI is now zero
0000:7CC3 59 POP CX get number dir sectors
0000:7CC4 890E4400 MOV [0044],CX save
0000:7CC8 58 POP AX get number fat sectors
0000:7CC9 A34200 MOV [0042],AX save
0000:7CCC 33D2 XOR DX,DX DX now zero
0000:7CCE E87300 CALL READ_SECTOR read 1st sect of root dir
0000:7CD1 33DB XOR BX,BX BX is now zero
0000:7CD3 8B0E1100 MOV CX,[0011] number of root dir entries
DIR_SEARCH: SEARCH FOR OS2BOOT.
Search the root directory for the file
name OS2BOOT.
0000:7CD7 8BFB MOV DI,BX DI is dir entry addr
0000:7CD9 51 PUSH CX save CX
0000:7CDA B90B00 MOV CX,000B count is 11
0000:7CDD BED501 MOV SI,01D5 addr of "OS2BOOT"
0000:7CE0 F3 REPZ is 1st dir entry
0000:7CE1 A6 CMPSB for "OS2BOOT"?
0000:7CE2 59 POP CX restore CX
0000:7CE3 7405 JZ FOUND_OS2BOOT jmp if OS2BOOT
0000:7CE5 83C320 ADD BX,+20 incr to next dir entry
0000:7CE8 E2ED LOOP DIR_SEARCH try again
FOUND_OS2BOOT: FOUND OS2BOOT.
OS2BOOT was found. Get the starting
cluster number and convert to a sector
address. Read OS2BOOT into memory and
finally do a far return to enter
the OS2BOOT program.
0000:7CEA E335 JCXZ FAILED1 JMP if CX zero.
0000:7CEC 26 ES: get the szie of
0000:7CED 8B471C MOV AX,[BX+1C] the OS2BOOT file
0000:7CF0 26 ES: from the OS2BOOT
0000:7CF1 8B571E MOV DX,[BX+1E] directory entry
0000:7CF4 F7360B00 DIV WORD PTR [000B] div by bytesPerSect
0000:7CF8 FEC0 INC AL add 1
0000:7CFA 8AC8 MOV CL,AL num sectors OS2BOOT
0000:7CFC 26 ES: get the starting
0000:7CFD 8B571A MOV DX,[BX+1A] cluster number
0000:7D00 4A DEC DX subtract 1
0000:7D01 4A DEC DX subtract 1
0000:7D02 A00D00 MOV AL,[000D] sectorsPerCluster
0000:7D05 32E4 XOR AH,AH mutiply
0000:7D07 F7E2 MUL DX to get LBA
0000:7D09 03063E00 ADD AX,[003E] add number of FAT sectors
0000:7D0D 83D200 ADC DX,+00 to LBA
0000:7D10 BB0008 MOV BX,0800 set ES
0000:7D13 8EC3 MOV ES,BX to 0800
0000:7D15 33FF XOR DI,DI set ES:DI to entry point
0000:7D17 06 PUSH ES address of
0000:7D18 57 PUSH DI OS2BOOT
0000:7D19 E82800 CALL READ_SECTOR read OS2BOOT into memory
0000:7D1C 8D360B00 LEA SI,[000B] set DS:SI
0000:7D20 CB RETF "far return" to OS2BOOT
FAILED1: OS2BOOT WAS NOT FOUND.
0000:7D21 BE9801 MOV SI,0198 "SYS01475" message
0000:7D24 EB03 JMP FAILED3
FAILED2: ERROR FROM INT 13.
0000:7D26 BEAD01 MOV SI,01AD "SYS02025" message
FAILED3: OUTPUT ERROR MESSAGES.
0000:7D29 E80900 CALL MSG_LOOP display message
0000:7D2C BEC201 MOV SI,01C2 "SYS02027" message
0000:7D2F E80300 CALL MSG_LOOP display message
0000:7D32 FB STI interrupts on
HANG: HANG THE SYSTEM!
0000:7D33 EBFE JMP HANG sit and stay!
MSG_LOOP: DISPLAY AN ERROR MESSAGE.
Routine to display the message
text pointed to by SI.
0000:7D35 AC LODSB get next char of message
0000:7D36 0AC0 OR AL,AL end of message?
0000:7D38 7409 JZ RETURN jmp if yes
0000:7D3A B40E MOV AH,0E write 1 char
0000:7D3C BB0700 MOV BX,0007 video attributes
0000:7D3F CD10 INT 10 INT 10 to write 1 char
0000:7D41 EBF2 JMP MSG_LOOP do again
RETURN:
0000:7D43 C3 RET return
READ_SECTOR: ROUTINE TO READ SECTORS.
Read sectors into memory. Read multiple
sectors but don't read across a track
boundary.
The caller supplies the following:
DX:AX = sector address to read (as LBA)
CX = number of sectors to read
ES:DI = memory address to read into
0000:7D44 50 PUSH AX save lower part of LBA
0000:7D45 52 PUSH DX save upper part of LBA
0000:7D46 51 PUSH CX save number of sect to read
0000:7D47 03061C00 ADD AX,[001C] add numHiddenSectors
0000:7D4B 13161E00 ADC DX,[001E] to LBA
0000:7D4F F7361800 DIV WORD PTR [0018] div by sectorsPerTrack
0000:7D53 FEC2 INC DL add 1 to sector number
0000:7D55 8ADA MOV BL,DL save sector number
0000:7D57 33D2 XOR DX,DX zero upper part of LBA
0000:7D59 F7361A00 DIV WORD PTR [001A] div by numHeads
0000:7D5D 8AFA MOV BH,DL save head number
0000:7D5F 8BD0 MOV DX,AX save cylinder number
0000:7D61 A11800 MOV AX,[0018] sectorsPerTrack
0000:7D64 2AC3 SUB AL,BL sub sector number
0000:7D66 40 INC AX add 1
0000:7D67 50 PUSH AX save number of sector to read
0000:7D68 B402 MOV AH,02 INT 13 read sectors
0000:7D6A B106 MOV CL,06 shift count
0000:7D6C D2E6 SHL DH,CL shift high cyl left
0000:7D6E 0AF3 OR DH,BL or in sector number
0000:7D70 8BCA MOV CX,DX move cyl/sect to CX
0000:7D72 86E9 XCHG CH,CL swap cyl/sect
0000:7D74 8A162400 MOV DL,[0024] driveNum
0000:7D78 8AF7 MOV DH,BH head number
0000:7D7A 8BDF MOV BX,DI memory addr to read into
0000:7D7C CD13 INT 13 INT 13 read sectors call
0000:7D7E 72A6 JB FAILED2 jmp if any error
0000:7D80 5B POP BX get number of sectors read
0000:7D81 59 POP CX restore CX
0000:7D82 8BC3 MOV AX,BX number of sector to AX
0000:7D84 F7260B00 MUL WORD PTR [000B] multiply by sector size
0000:7D88 03F8 ADD DI,AX add to memory address
0000:7D8A 5A POP DX restore upper part of LBA
0000:7D8B 58 POP AX restore lower part of LBA
0000:7D8C 03C3 ADD AX,BX add number of sector just
0000:7D8E 83D200 ADC DX,+00 read to LBA
0000:7D91 2ACB SUB CL,BL decr requested num of sect
0000:7D93 7FAF JG READ_SECTOR jmp if not zero
0000:7D95 C3 RET return
Data not used.
0000:7D90 ........ ....1200 ........ ........ * .. *
Messages here.
0000:7D90 ........ ........ 4f532f32 20212120 * OS/2 !! *
0000:7Da0 53595330 31343735 0d0a0012 004f532f *SYS01475.....OS/*
0000:7Db0 32202121 20535953 30323032 350d0a00 *2 !! SYS02025...*
0000:7Dc0 12004f53 2f322021 21205359 53303230 *..OS/2 !! SYS020*
0000:7Dd0 32370d0a 00...... ........ ........ *27... *
OS/2 loader file name.
0000:7Dd0 ........ ..4f5332 424f4f54 20202020 * OS2BOOT *
Data not used.
0000:7De0 00000000 00000000 00000000 00000000 *................*
0000:7Df0 00000000 00000000 00000000 0000.... *.............. *
The last two bytes contain a 55AAH signature.
0000:7Df0 ........ ........ ........ ....55aa * U.*
/end/
--
\\===============\\=======================\\
\\ Hale Landis \\ 303-548-0567 \\
// Niwot, CO USA // landis@sugs.tware.com //
//===============//=======================//
|