add directory study
BIN
study/sabre/os/files/Booting/BIOSBootSpecsV1.01.pdf
Normal file
486
study/sabre/os/files/Booting/BIOS_SEG.txt
Normal file
@@ -0,0 +1,486 @@
|
||||
Format of BIOS Data Segment at segment 40h:
|
||||
{items in curly braces not documented by IBM}
|
||||
Offset Size Description
|
||||
00h WORD Base I/O address of 1st serial I/O port, zero if none
|
||||
02h WORD Base I/O address of 2nd serial I/O port, zero if none
|
||||
04h WORD Base I/O address of 3rd serial I/O port, zero if none
|
||||
06h WORD Base I/O address of 4th serial I/O port, zero if none
|
||||
Note: Above fields filled in turn by POST as it finds serial
|
||||
ports. POST never leaves gaps. DOS and BIOS serial device
|
||||
numbers may be redefined by re-assigning these fields.
|
||||
08h WORD Base I/O address of 1st parallel I/O port, zero if none
|
||||
0Ah WORD Base I/O address of 2nd parallel I/O port, zero if none
|
||||
0Ch WORD Base I/O address of 3rd parallel I/O port, zero if none
|
||||
0Eh WORD [non-PS] Base I/O address of 4th parallel I/O port, zero if none
|
||||
[PS] Segment of Extended BIOS Data Segment
|
||||
Note: Above fields filled in turn by POST as it finds
|
||||
parallel ports. POST never leaves gaps. DOS and BIOS
|
||||
parallel device numbers may de redefined by re-assigning
|
||||
these fields.
|
||||
10h WORD Installed hardware:
|
||||
bits 15-14: number of parallel devices
|
||||
bit 13: [Conv] Internal modem
|
||||
bit 12: reserved
|
||||
bits 11- 9: number of serial devices
|
||||
bit 8: reserved
|
||||
bits 7- 6: number of diskette drives minus one
|
||||
bits 5- 4: Initial video mode:
|
||||
00b = EGA,VGA,PGA
|
||||
01b = 40 x 25 color
|
||||
10b = 80 x 25 color
|
||||
11b = 80 x 25 mono
|
||||
bit 3: reserved
|
||||
bit 2: [PS] =1 if pointing device
|
||||
[non-PS] reserved
|
||||
bit 1: =1 if math co-processor
|
||||
bit 0: =1 if diskette available for boot
|
||||
12h BYTE [Conv] POST status
|
||||
[AT] {Manufacturing test initialisation flags}
|
||||
13h WORD Base memory size in kbytes (0-640)
|
||||
15h BYTE [AT] {Manufacturing test scratch pad}
|
||||
16h BYTE [AT] {Manufacturing test scratch pad}
|
||||
[PS/2 Mod 30] BIOS control flags
|
||||
17h BYTE Keyboard status flags 1:
|
||||
bit 7 =1 INSert active
|
||||
bit 6 =1 Caps Lock active
|
||||
bit 5 =1 Num Lock active
|
||||
bit 4 =1 Scroll Lock active
|
||||
bit 3 =1 either Alt pressed
|
||||
bit 2 =1 either Ctrl pressed
|
||||
bit 1 =1 Left Shift pressed
|
||||
bit 0 =1 Right Shift pressed
|
||||
18h BYTE Keyboard status flags 2:
|
||||
bit 7 =1 INSert pressed
|
||||
bit 6 =1 Caps Lock pressed
|
||||
bit 5 =1 Num Lock pressed
|
||||
bit 4 =1 Scroll Lock pressed
|
||||
bit 3 =1 Pause state active
|
||||
bit 2 =1 Sys Req pressed
|
||||
bit 1 =1 Left Alt pressed
|
||||
bit 0 =1 Left Ctrl pressed
|
||||
19h BYTE Keyboard: Alt-nnn keypad workspace
|
||||
1Ah WORD Keyboard: ptr to next character in keyboard buffer
|
||||
1Ch WORD Keyboard: ptr to first free slot in keyboard buffer
|
||||
1Eh 16 WORDs Keyboard circular buffer (but see 80h, 82h for override)
|
||||
3Eh BYTE Diskette recalibrate status:
|
||||
bit 7 =1 Diskette hardware interrupt occurred
|
||||
bits 6-4 reserved
|
||||
bit 3 =1 Recalibrate diskette 3
|
||||
bit 2 =1 Recalibrate diskette 2
|
||||
bit 1 =1 Recalibrate diskette 1
|
||||
bit 0 =1 Recalibrate diskette 0
|
||||
3Fh BYTE Diskette motor status:
|
||||
bit 7 =1 current operation is write or format
|
||||
=0 current operation is read or verify
|
||||
bit 6 reserved
|
||||
bits 5-4 diskette drive number selected (0-3)
|
||||
bit 3 =1 diskette 3 motor on
|
||||
bit 2 =1 diskette 2 motor on
|
||||
bit 1 =1 diskette 1 motor on
|
||||
bit 0 =1 diskette 0 motor on
|
||||
40h BYTE Diskette motor turn-off time-out count
|
||||
41h BYTE Diskette last operation status (0 = OK)
|
||||
bit 7 =1 drive not ready
|
||||
bit 6 =1 seek error
|
||||
bit 5 =1 general controller failure
|
||||
bits 4-0:
|
||||
00h no error
|
||||
01h invalid request
|
||||
02h address mark not found
|
||||
03h write-protect error
|
||||
04h sector not found
|
||||
06h diskette change line active
|
||||
08h DMA overrun
|
||||
09h DMA across 64k boundary
|
||||
0Ch media type unknown
|
||||
10h CRC error on read
|
||||
42h 7 BYTEs Diskette/Fixed disk status/command bytes
|
||||
49h BYTE Video current mode
|
||||
4Ah WORD Video columns on screen
|
||||
4Ch WORD Video page (regen buffer) size in bytes
|
||||
4Eh WORD Video current page start address in regen buffer
|
||||
50h 16 BYTEs Video cursor position (col, row) for eight pages, 0 based
|
||||
60h WORD Video cursor type, 6845 compatible, hi=startline, lo=endline
|
||||
62h BYTE Video current page number
|
||||
63h WORD Video CRT controller base address: color=03D4h, mono=03B4h
|
||||
65h BYTE Video current setting of mode select register 03D8h/03B8h
|
||||
66h BYTE Video current setting of CGA palette register 03D9h
|
||||
67h DWORD POST real mode re-entry point after certain resets
|
||||
6Bh BYTE POST last unexpected interrupt
|
||||
6Ch DWORD Timer ticks since midnight
|
||||
70h BYTE Timer overflow, non-zero if has counted past midnight
|
||||
71h BYTE Ctrl-Break flag: bit 7=1
|
||||
72h WORD POST reset flag:
|
||||
= 1234h if to bypass memory test (warm boot)
|
||||
= 4321h [PS/2 MCA only] if to preserve memory
|
||||
= 5678h [Conv] system suspended
|
||||
= 9ABCh [Conv] manufacturing test mode
|
||||
= ABCDh [Conv] POST loop mode
|
||||
= 64h Burn-in mode
|
||||
74h BYTE Fixed disk last operation status: {except ESDI drives}
|
||||
00h no error
|
||||
01h invalid function request
|
||||
02h address mark not found
|
||||
03h write protect error
|
||||
04h sector not found
|
||||
05h reset failed
|
||||
07h drive parameter activity failed
|
||||
08h DMA overrun
|
||||
09h DMA data boundary error
|
||||
0Ah bad sector flag detected
|
||||
0Bh bad track detected
|
||||
0Dh invalid number of sectors for Format
|
||||
0Eh control data address mark detected
|
||||
0Fh DMA arbitration level out of range
|
||||
10h uncorrectable ECC or CRC error
|
||||
11h ECC corrected data error
|
||||
20h general controller failed
|
||||
40h seek failed
|
||||
80h time out
|
||||
AAh drive not ready
|
||||
BBh undefined error
|
||||
CCh write fault on selected drive
|
||||
E0h status error/error register is zero
|
||||
FFh sense failed
|
||||
75h BYTE Fixed disk: number of fixed disk drives
|
||||
76h BYTE Fixed disk: control byte {IBM document only for XT}
|
||||
77h BYTE Fixed disk: I/O port offset {IBM document only for XT}
|
||||
78h 3 BYTEs Parallel devices 1-3 time-out counters
|
||||
7Bh BYTE parallel device 4 time-out counter [non-PS]
|
||||
bit 5 set if Virtual DMA Spec supported [PS] (see INT 4B)
|
||||
7Ch 4 BYTEs Serial devices 1-4 time-out counters
|
||||
80h WORD Keyboard buffer start as offset from segment 40h (normally 1Eh)
|
||||
82h WORD Keyboard buffer end+1 as offset from segment 40h (normally 3Eh)
|
||||
[XT BIOS dated 11/08/82 ends here]
|
||||
84h BYTE Video EGA/MCGA/VGA rows on screen minus one
|
||||
85h WORD Video EGA/MCGA/VGA character height in scan-lines
|
||||
87h BYTE Video EGA/VGA control: [MCGA: =00h]
|
||||
bit 7: =1 if not to clear RAM (see INT 10h, AH=00h)
|
||||
bits 6-5: RAM on adapter = (this field + 1) * 64K
|
||||
bit 4: reserved
|
||||
bit 3: =0 if EGA/VGA video system active, =1 if inactive
|
||||
bit 2: =1 if to wait for display enable (what means this?)
|
||||
bit 1: =0 for color or ECD monitor, =1 for mono monitor
|
||||
bit 0: =0 alphanumeric cursor emulation enabled, =1 not.
|
||||
When enabled, text mode cursor size (INT 10,AH=01h)
|
||||
settings looking like CGA ones are translated to
|
||||
equivalent EGA/VGA ones.
|
||||
88h BYTE Video EGA/VGA switches: [MCGA: reserved]
|
||||
bits 7-4: power-on state of feature connector bits 3-0
|
||||
bits 3-0: configuration switches 4-1 (=0 on, =1 off)
|
||||
Values as read:
|
||||
0h Pri MDA, Sec EGA+old color display 40 x 25
|
||||
1h Pri MDA, Sec EGA+old color display 80 x 25
|
||||
2h Pri MDA, Sec EGA+ECD normal mode (CGA emul)
|
||||
3h Pri MDA, Sec EGA+ECD enhanced mode
|
||||
4h Pri CGA 40 x 25, Sec EGA mono display
|
||||
5h Pri CGA 80 x 25, Sec EGA mono display
|
||||
6h Pri EGA+old color display 40 x 25, Sec MDA
|
||||
7h Pri EGA+old color display 80 x 25, Sec MDA
|
||||
8h Pri EGA+ECD normal mode (CGA emul), Sec MDA
|
||||
9h Pri EGA+ECD enhanced mode, Sec MDA
|
||||
Ah Pri EGA mono display, Sec CGA 40 x 25
|
||||
Bh Pri EGA mono display, Sec CGA 80 x 25
|
||||
When bit4 of 40h:89h is 0, VGA emulates 350-line EGA if
|
||||
this byte is x3h or x9h, otherwise emulates 200-line CGA in
|
||||
400-line double scan. VGA resets this byte to x9h after the
|
||||
mode set.
|
||||
89h BYTE Video MCGA/VGA mode-set option control:
|
||||
bits 7 and 4:
|
||||
0 0 350-line mode requested
|
||||
0 1 400-line mode at next mode set
|
||||
1 0 200-line mode requested
|
||||
1 1 reserved
|
||||
Apparently VGA BIOS mode set disregards bit 7 and uses
|
||||
byte 40h:88h to determine 200/350 selection when bit 4
|
||||
is zero. Presumably bit 7 is a convenience for other
|
||||
purposes. Bit 7 is reset to zero after the mode set.
|
||||
bit 6: =1 if display switching enabled, =0 if disabled
|
||||
bit 5: reserved
|
||||
bit 4: [VGA] =1 if to use 400-line mode at next mode set
|
||||
=0 if to emulate EGA at next mode set
|
||||
This bit set to 1 after the mode set.
|
||||
[MCGA] =1 use 400-line mode at next mode set
|
||||
=0 emulate CGA, digital monitor, 200 lines,
|
||||
8 x 8 text font at next mode set
|
||||
Bit unchanged by mode set.
|
||||
bit 3: =0 if default palette loading enabled at mode set
|
||||
bit 2: =1 if mono display, =0 if color display
|
||||
bit 1: =1 if gray scale summing enabled, =0 if disabled
|
||||
bit 0: [VGA] =1 if VGA active, =0 if not
|
||||
[MCGA] reserved, zero
|
||||
8Ah BYTE Video [MCGA/VGA]: index into Display Combination Code table
|
||||
8Bh BYTE Diskette media control [not XT]:
|
||||
bits 7-6: Last data rate set by controller:
|
||||
00=500kbps, 01=300kbps, 10=250kbps, 11=reserved
|
||||
bits 5-4: Last diskette drive step rate selected
|
||||
bits 3-2: {Data rate at start of operation}
|
||||
bits 1-0: reserved
|
||||
8Ch BYTE Fixed disk controller status [not XT]
|
||||
8Dh BYTE Fixed disk controller Error Status [not XT]
|
||||
8Eh BYTE Fixed disk Interrupt Control [not XT]
|
||||
8Fh BYTE Diskette controller information [not XT]:
|
||||
bit 7: reserved
|
||||
bit 6: =1 drive 1 determined
|
||||
bit 5: =1 drive 1 is multi-rate, valid if drive determined
|
||||
bit 4: =1 drive 1 supports 80 tracks, always valid
|
||||
bit 3: reserved
|
||||
bit 2: =1 drive 0 determined
|
||||
bit 1: =1 drive 0 is multi-rate, valid if drive determined
|
||||
bit 0: =1 drive 0 supports 80 tracks, always valid
|
||||
90h BYTE Diskette drive 0 media state
|
||||
91h BYTE Diskette drive 1 media state
|
||||
bits 7-6: Data rate: 00=500kbps, 01=300kbps, 10=250kbps
|
||||
bit 5: =1 if double stepping reqd (e.g. 360kB in 1.2MB)
|
||||
bit 4: =1 if media established
|
||||
bit 3: reserved
|
||||
bits 2-0: on exit from BIOS, contain:
|
||||
000 trying 360kB in 360kB
|
||||
001 trying 360kB in 1.2MB
|
||||
010 trying 1.2MB in 1.2MB
|
||||
011 360kB in 360kB established
|
||||
100 360kB in 1.2MB established
|
||||
101 1.2MB in 1.2MB established
|
||||
110 reserved
|
||||
111 all other formats/drives
|
||||
92h BYTE Diskette drive 0 media state at start of operation
|
||||
93h BYTE Diskette drive 1 media state at start of operation
|
||||
94h BYTE Diskette drive 0 current track number
|
||||
95h BYTE Diskette drive 1 current track number
|
||||
96h BYTE Keyboard status byte 3
|
||||
bit 7 =1 read-ID in progress
|
||||
bit 6 =1 last code read was first of two ID codes
|
||||
bit 5 =1 force Num Lock if read-ID and enhanced keyboard
|
||||
bit 4 =1 enhanced keyboard installed
|
||||
bit 3 =1 Right Alt pressed
|
||||
bit 2 =1 Right Ctrl pressed
|
||||
bit 1 =1 last code read was E0h
|
||||
bit 1 =1 last code read was E1h
|
||||
97h BYTE Keyboard status byte 2
|
||||
bit 7 =1 keyboard transmit error flag
|
||||
bit 6 =1 LED update in progress
|
||||
bit 5 =1 RESEND received from keyboard
|
||||
bit 4 =1 ACK received from keyboard
|
||||
bit 3 reserved, must be zero
|
||||
bit 2 Caps Lock LED
|
||||
bit 1 Num Lock LED
|
||||
bit 0 Scroll Lock LED
|
||||
98h DWORD Timer2: [AT, PS exc Mod 30] ptr to user wait-complete flag
|
||||
(see INT 15, AX=8300h)
|
||||
9Ch DWORD Timer2: [AT, PS exc Mod 30] user wait count in microseconds
|
||||
A0h BYTE Timer2: [AT, PS exc Mod 30] Wait active flag:
|
||||
bit 7 =1 wait time elapsed
|
||||
bits 6-1 reserved
|
||||
bit 0 =1 INT 15h, AH=86h has occurred
|
||||
A1h 7 BYTEs reserved for network adapters (oh really?)
|
||||
A4h DWORD [PS/2 Mod 30] Saved Fixed Disk Interrupt Vector
|
||||
A8h DWORD Video: EGA/MCGA/VGA ptr to Video Save Pointer Table (see below)
|
||||
ACh-AFh reserved
|
||||
B0h DWORD ptr to 3363 Optical disk driver or BIOS entry point.
|
||||
When 3363 BIOS present, the signature "OPTIC ",00h occurs 3
|
||||
bytes beyond this entry point.
|
||||
When 3363 BIOS and 3363 File System Driver present, the
|
||||
signature "FILE SYSTEM DRIVER",00h occurs 3 bytes beyond
|
||||
this entry point.
|
||||
B4h WORD reserved
|
||||
B6h 3 BYTEs reserved for POST?
|
||||
B9h 7 BYTEs ???
|
||||
C0h 14 BYTEs reserved
|
||||
CEh WORD count of days since last boot?
|
||||
D0h-EFh reserved
|
||||
F0h-FFh reserved for user
|
||||
100h BYTE Print Screen Status byte
|
||||
|
||||
Format of Extended BIOS Data Area (see 40:0Eh for ptr) [PS only]
|
||||
Offset Size Description
|
||||
00h BYTE Length of EBDA in kilobytes
|
||||
01h 15 BYTEs reserved
|
||||
17h BYTE Number of entries in POST error log (0-5)
|
||||
18h 5 WORDs POST error log (each word is a POST error number)
|
||||
19h-21h reserved
|
||||
22h DWORD Pointing Device Driver entry point
|
||||
26h BYTE Pointing Device Flags 1
|
||||
bit 7: =1 command in progress
|
||||
bit 6: =1 resend
|
||||
bit 5: =1 acknowledge
|
||||
bit 4: =1 error
|
||||
bit 3: =0 reserved
|
||||
bits 2-0: index count
|
||||
27h BYTE Pointing Device Flags 2
|
||||
bit 7: =1 device driver far call flag
|
||||
bits 6-3: reserved
|
||||
bits 2-0: package size
|
||||
28h 7 BYTEs Pointing Device Auxiliary Device Data
|
||||
2Fh BYTE reserved
|
||||
30h DWORD Vector for INT 07h stored here during 80387 interrupt
|
||||
34h DWORD Vector for INT 01h stored here during INT 07h emulation
|
||||
38h BYTE Scratchpad for 80287/80387 interrupt code
|
||||
39h WORD Timer3: Watchdog timer initial count
|
||||
3Bh BYTE ??? seen non-zero on Model 30
|
||||
3Ch BYTE ???
|
||||
3Dh 16 BYTEs Fixed Disk parameter table for drive 0 (oh really?)
|
||||
4Dh 16 BYTEs Fixed Disk parameter table for drive 1 (oh really?)
|
||||
Neither of above seen on any Model 30, 50, 60 yet.
|
||||
5Dh-6Bh ???
|
||||
6Ch BYTE Fixed disk: (=FFh on ESDI systems)
|
||||
bits 7-4: Channel number 00-0Fh
|
||||
bits 3-0: DMA arbitration level 00-0Eh
|
||||
6Dh and up: ??? seen non-zero on Model 60
|
||||
3F0h BYTE Fixed disk buffer (???!!!)
|
||||
|
||||
Format of Video Save Pointer Table [EGA/VGA/MCGA only]:
|
||||
Offset Size Description
|
||||
00h DWORD ptr to Video Parameter Table
|
||||
04h DWORD ptr to Parameter Dynamic Save Area, else 0 [EGA/VGA only]
|
||||
08h DWORD ptr to Alphanumeric Character Set Override, else 0
|
||||
0Ch DWORD ptr to Graphics Character Set Override, else 0
|
||||
10h DWORD [VGA only] ptr to Secondary Save Pointer Table, must be valid
|
||||
14h DWORD reserved, zero
|
||||
18h DWORD reserved, zero
|
||||
Note: table initially in ROM, copy to RAM to alter, then update 40h:A8h.
|
||||
|
||||
Format of Secondary Video Save Pointer Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h WORD Length of this table in bytes, including this word (1Ah)
|
||||
02h DWORD ptr to Display Combination Code Table, must be valid
|
||||
06h DWORD ptr to second Alphanumeric Character Set Override, else 0
|
||||
0Ah DWORD ptr to User Palette Profile Table, else 0
|
||||
0Eh DWORD reserved, zero
|
||||
12h DWORD reserved, zero
|
||||
16h DWORD reserved, zero
|
||||
Note: table initially in ROM, copy to RAM to alter, then alter Save Ptr Table.
|
||||
|
||||
Format of Video Parameter Table [EGA, VGA only]:
|
||||
An array of 23 [EGA] or 29 [VGA] elements, each element being 64 bytes long.
|
||||
Elements appear in the order:
|
||||
00h-03h Modes 00h-03h in 200-line CGA emulation mode
|
||||
04h-0Eh Modes 04h-0Eh
|
||||
0Fh-10h Modes 0Fh-10h when only 64kB RAM on adapter
|
||||
11h-12h Modes 0Fh-10h when >64kB RAM on adapter
|
||||
13h-16h Modes 00h-03h in 350-line mode
|
||||
17h VGA Modes 00h or 01h in 400-line mode
|
||||
18h VGA Modes 02h or 03h in 400-line mode
|
||||
19h VGA Mode 07h in 400-line mode
|
||||
1Ah-1Ch VGA Modes 11h-13h
|
||||
|
||||
Format of Video Parameter Table element [EGA, VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Columns on screen (see 40h:4Ah)
|
||||
01h BYTE Rows on screen minus one (see 40h:84h)
|
||||
02h BYTE Height of character in scan lines (see 40h:85h)
|
||||
03h WORD Size of video buffer (see 40h:4Ch)
|
||||
05h 4 BYTEs Values for Sequencer Registers 1-4
|
||||
09h BYTE Value for Miscellaneous Output Register
|
||||
0Ah 25 BYTEs Values for CRTC Registers 00h-18h
|
||||
23h 20 BYTEs Values for Attribute Controller Registers 00h-13h
|
||||
37h 9 BYTEs Values for Graphics Controller Registers 00h-08h
|
||||
|
||||
Format of Video Parameter Table [MCGA only] {guesswork from inspection}:
|
||||
- 16 triplet BYTEs of R,G,B DAC info for 16 colors;
|
||||
- An array of 11 elements, each element being 32 bytes long.
|
||||
Elements appear in the order:
|
||||
Modes 00h,01h in 200-line mode for digital displays
|
||||
Modes 00h,01h in 400-line mode for analog displays
|
||||
Modes 02h,03h in 200-line mode for digital displays
|
||||
Modes 02h,03h in 400-line mode for analog displays
|
||||
Modes 04h,05h in 200-line mode for digital displays
|
||||
Modes 04h,05h in 400-line mode for analog displays
|
||||
Mode 06h in 200-line mode for digital displays
|
||||
Mode 06h in 400-line mode for analog displays
|
||||
Mode 11h
|
||||
Mode 13h in 200-line mode for digital displays
|
||||
Mode 13h in 400-line mode for analog displays
|
||||
|
||||
Format of Video Parameter Table element [MCGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Columns on screen (see 40h:4Ah)
|
||||
01h BYTE Rows on screen minus one (see 40h:84h)
|
||||
02h BYTE Height of character in scan lines (see 40h:85h)
|
||||
03h WORD Size of video buffer (see 40h:4Ch)
|
||||
05h WORD ??? always zero
|
||||
07h 21 BYTEs Video data registers 00h-14h to port 3D5h indexed by 3D4h
|
||||
1Ch BYTE PEL Mask to port 3C6h
|
||||
1Dh BYTE CGA Mode Control to port 3D8h
|
||||
1Eh BYTE CGA Border Control to port 3D9h
|
||||
1Fh BYTE Extended Mode Control to port 3DDh
|
||||
|
||||
Format of Video Parameter Dynamic Save Area [EGA, VGA only]:
|
||||
Offset Size Description
|
||||
00h 16 BYTEs Last data written to Attribute Controller Palette Registers 0-15
|
||||
10h BYTE Last data written to Attribute Controller Overscan Register
|
||||
11h-FFh Reserved
|
||||
Note: Need for table was that EGA registers were write-only.
|
||||
Note: If default values (from the Video Parameter Table) are
|
||||
over-ridden at a mode set by the VGA User Palette Profile
|
||||
Table, then the Dynamic Save Area is updated with the
|
||||
default values, not the User Profile ones.
|
||||
|
||||
Format of Alphanumeric Character Set Override:
|
||||
Offset Size Description
|
||||
00h BYTE Length in bytes of each character in font table
|
||||
01h BYTE Character generator RAM bank to load, 0=normal
|
||||
02h WORD Number of characters in font table, normally 256
|
||||
04h WORD Code of first character in font table, normally 0
|
||||
06h DWORD ptr to font table
|
||||
0Ah BYTE Displayable rows (FFh=use maximum calculated value)
|
||||
0Bh BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Second Alphanumeric Character Set Override:
|
||||
Authorities differ, some say same as first override above, but IBM say:
|
||||
Offset Size Description
|
||||
00h BYTE Length in bytes of each character in font table
|
||||
01h BYTE Character generator RAM bank to load, normally non-zero
|
||||
02h BYTE reserved
|
||||
03h DWORD ptr to font table
|
||||
07h BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Graphics Character Set Override:
|
||||
Offset Size Description
|
||||
00h BYTE Number of displayable character rows
|
||||
01h WORD Length in bytes of each character in font table
|
||||
03h DWORD ptr to font table
|
||||
07h BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Display Combination Code Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Number of entries in the DCC table at offset 04h
|
||||
01h BYTE Version number
|
||||
02h BYTE Maximum display type code that can appear in DCC table
|
||||
03h BYTE reserved
|
||||
04h ARRAY OF 2 BYTEs Each pair of bytes gives a valid display combination
|
||||
Meaning of each byte:
|
||||
00h no display
|
||||
01h MDA with mono display
|
||||
02h CGA with color display
|
||||
03h reserved
|
||||
04h EGA with color display
|
||||
05h EGA with mono display
|
||||
06h Professional Graphics Controller
|
||||
07h VGA with mono display
|
||||
08h VGA with color display
|
||||
09h reserved
|
||||
0Ah MCGA with digital color display
|
||||
0Bh MCGA with analog mono display
|
||||
0Ch MCGA with analog color display
|
||||
FFh unrecognised video system
|
||||
|
||||
Format of User Palette Profile Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Underlining: 01h=enable in all alphanumeric modes
|
||||
00h=enable in monochrome alphanumeric modes only
|
||||
FFh=disable in all alphanumeric modes
|
||||
01h BYTE reserved
|
||||
02h WORD reserved
|
||||
04h WORD Number (0-17) of Attribute Controller registers in table
|
||||
06h WORD Index (0-16) of first Attribute Controller register in table
|
||||
08h DWORD ptr to table of Attribute Controller registers to override
|
||||
Table is an array of BYTEs.
|
||||
0Ch WORD Number (0-256) of video DAC Color registers in table
|
||||
0Eh WORD Index (0-255) of first video DAC Color register in table
|
||||
10h DWORD ptr to table of video DAC Color registers to override
|
||||
Table is ??? triplets ??? of BYTEs???
|
||||
14h BYTEs array of mode values to which this profile is to pertain
|
||||
BYTE FFh end of array
|
||||
59
study/sabre/os/files/Booting/BootSector.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<title>Operating Systems: The Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=7><b>The Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
The boot sector on a disk is always the first sector on the first track on the first head.
|
||||
When the computer is powered on (or reset), the BIOS starts up and does the POST. It initializes
|
||||
all of it's data, then it looks for a valid boot sector. First it looks at the A: drive, then
|
||||
it looks to C:. If it doesn't find it then interrupt 18h is called, which, on original IBM PCs,
|
||||
started the ROM BASIC. A valid
|
||||
boot sector (to the BIOS) is one that has 0AA55h at offset 510 in the boot sector.<p>
|
||||
|
||||
When the BIOS finds the boot sector, it reads that sector (512 bytes) off of the disk and into
|
||||
memory at 0:7C00h. Then it jumps to 0:7C00h and the boot sector code gets control. At this
|
||||
point, all that has been initialized is the BIOS data area (40h:0) and the BIOS interrupts
|
||||
(10h - 1Ah). At this point, memory is mostly unused, but not neccesarily cleared to 0.<p>
|
||||
|
||||
Below is an example shell that I use when writing boot sector code:
|
||||
|
||||
<pre>
|
||||
;Generic boot sector shell. Written by Chris Lattner 1995
|
||||
;Code+Data MUST be less than 510 bytes long!
|
||||
|
||||
_Text SEGMENT PUBLIC USE16
|
||||
assume CS:_Text, DS:_Text
|
||||
org 0
|
||||
|
||||
EntryPoint:
|
||||
db 0EAh ;jmp far SEG:OFS ;Currently we are at 0:7C00
|
||||
dw OFFSET AfterData, 7C0h ;This makes us be at 7C0:0
|
||||
|
||||
;Put any data here!
|
||||
|
||||
|
||||
AfterData:
|
||||
push CS
|
||||
pop DS ; update DS to be 7C0 instead of 0
|
||||
|
||||
;Put code here!
|
||||
|
||||
|
||||
jmp $ ; Hang out...
|
||||
|
||||
org 510 ; Make the file 512 bytes long
|
||||
dw 0AA55h ; Add the boot signature
|
||||
_Text ENDS
|
||||
END
|
||||
</pre>
|
||||
|
||||
To use this code, you must compile it with either MASM or TASM. Link it together as a COM file
|
||||
if you can (Tasm v4 complains about illegal COM entry point). Then write the 512 byte file in
|
||||
sector 1 of a floppy (With some suitable disk tool) to test it out... If you can't compile it
|
||||
as a COM file, compile it as an EXE, but only write out the last 512 bytes of the file (eg. skip
|
||||
the EXE file header). Pop the disk in, reset you computer, and watch the magic!
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1994-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Corrections and suggestions by <a href="mailto:murf@perftech.com">John Murphy</a><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
BIN
study/sabre/os/files/Booting/BootableCDFormat.doc
Normal file
79
study/sabre/os/files/Booting/CMOS_SEG.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
From: James Vahn
|
||||
Subj: Cmos
|
||||
____________________________________________________________________________
|
||||
|
||||
The standard AT CMOS addresses from 00h to 3Fh are easy,
|
||||
|
||||
; Read CMOS
|
||||
mov al,addr ; 'addr' ranges from 00h to 3Fh.
|
||||
out 70h,al ; wakes up the port.
|
||||
jmp $+2 ; a delay loop..
|
||||
in al,71h ; reads CMOS.
|
||||
|
||||
; Write CMOS
|
||||
mov al,addr ; 'addr' ranges from 00h to 3Fh.
|
||||
out 70h,al ; wakes up the port.
|
||||
jmp $+2 ; a delay loop..
|
||||
out 71h, value ; Writes 'value' from 00h to FFh.
|
||||
; note that 'addr' 10h to 20h are checksummed.
|
||||
|
||||
|
||||
Some CMOS info...
|
||||
|
||||
addr contents
|
||||
|
||||
00h Seconds
|
||||
01h Second Alarm
|
||||
02h Minutes
|
||||
03h Minute Alarm
|
||||
04h Hours
|
||||
05h Hour Alarm
|
||||
06h Day of the Week
|
||||
07h Day of the Month
|
||||
08h Month
|
||||
09h Year
|
||||
0Ah Status Register A
|
||||
0Bh Status Register B
|
||||
0Ch Status Register C
|
||||
0Dh Status Register D
|
||||
0Eh Diagnostic Status Byte
|
||||
0Fh Shutdown Status Byte
|
||||
10h Disk Drive Type for Drives A: and B:
|
||||
The drive-type bytes use bits 0:3 for the first
|
||||
drive and 4:7 for the other disk drive types.
|
||||
00h no drive present
|
||||
01h double sided 360k
|
||||
02h high capacity (1.2 meg)
|
||||
03h-0Fh reserved
|
||||
11h (AT):Reserved (PS/2):drive type for hard disk C:
|
||||
12h (PS/2):drive type for hard disk D:
|
||||
(AT, XT/286):hard disk type for drives C: and D:
|
||||
Format of drive-type entry for AT, XT/286:
|
||||
0 number of cyls in drive (0-1023 allowed)
|
||||
2 number of heads per drive (0-15 allowed)
|
||||
3 starting reduced write compensation (not used on AT)
|
||||
5 starting cylinder for write compensation
|
||||
7 max. ECC data burst length, XT only
|
||||
8 control byte
|
||||
Bit
|
||||
7 disable disk-access retries
|
||||
6 disable ECC retries
|
||||
5-4 reserved, set to zero
|
||||
3 more than 8 heads
|
||||
2-0 drive option on XT (not used by AT)
|
||||
9 timeout value for XT (not used by AT)
|
||||
12 landing zone cylinder number
|
||||
14 number of sectors per track (default 17, 0-17 allowed)
|
||||
13h Reserved
|
||||
14h Equipment Byte (corresponds to sw. 1 on PC and XT)
|
||||
15h-16h Base Memory Size (low,high)
|
||||
17h-18h Expansion Memory Size (low,high)
|
||||
19h-20h Reserved
|
||||
(PS/2) POS information Model 50 (60 and 80 use a 2k
|
||||
CMOS RAM that is not accessible through software)
|
||||
21h-2Dh Reserved (not checksumed)
|
||||
2Eh-2Fh Checksum of Bytes 10 Through 20 (low,high)
|
||||
30h-31h Exp. Memory Size as Det. by POST (low,high)
|
||||
32h Date Century Byte
|
||||
33h Information Flags (set during power-on)
|
||||
34h-3Fh Reserved - Put Your Name Here.
|
||||
480
study/sabre/os/files/Booting/LinuxBootSector.html
Normal file
@@ -0,0 +1,480 @@
|
||||
<title>Operating Systems: The Linux 2.0 Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=7><b>Example Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
This is the assembly source for the boot sector used by the Linux free operating system. If it looks unfamiliar for intel assembly, that's because it gets run through the standard C preprocessor (CPP) and has comments starting with '!' stripped off... enjoy! :)<p>
|
||||
|
||||
<pre>
|
||||
!
|
||||
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
|
||||
! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
|
||||
! versions of linux which compress the kernel
|
||||
!
|
||||
#include <linux/config.h>
|
||||
SYSSIZE = DEF_SYSSIZE
|
||||
!
|
||||
! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
|
||||
! modified by Drew Eckhardt
|
||||
! modified by Bruce Evans (bde)
|
||||
!
|
||||
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
|
||||
! itself out of the way to address 0x90000, and jumps there.
|
||||
!
|
||||
! bde - should not jump blindly, there may be systems with only 512K low
|
||||
! memory. Use int 0x12 to get the top of memory, etc.
|
||||
!
|
||||
! It then loads 'setup' directly after itself (0x90200), and the system
|
||||
! at 0x10000, using BIOS interrupts.
|
||||
!
|
||||
! NOTE! currently system is at most (8*65536-4096) bytes long. This should
|
||||
! be no problem, even in the future. I want to keep it simple. This 508 kB
|
||||
! kernel size should be enough, especially as this doesn't contain the
|
||||
! buffer cache as in minix (and especially now that the kernel is
|
||||
! compressed :-)
|
||||
!
|
||||
! The loader has been made as simple as possible, and continuous
|
||||
! read errors will result in a unbreakable loop. Reboot by hand. It
|
||||
! loads pretty fast by getting whole tracks at a time whenever possible.
|
||||
|
||||
.text
|
||||
|
||||
SETUPSECS = 4 ! nr of setup-sectors
|
||||
BOOTSEG = 0x07C0 ! original address of boot-sector
|
||||
INITSEG = DEF_INITSEG ! we move boot here - out of the way
|
||||
SETUPSEG = DEF_SETUPSEG ! setup starts here
|
||||
SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
|
||||
|
||||
! ROOT_DEV & SWAP_DEV are now written by "build".
|
||||
ROOT_DEV = 0
|
||||
SWAP_DEV = 0
|
||||
#ifndef SVGA_MODE
|
||||
#define SVGA_MODE ASK_VGA
|
||||
#endif
|
||||
#ifndef RAMDISK
|
||||
#define RAMDISK 0
|
||||
#endif
|
||||
#ifndef CONFIG_ROOT_RDONLY
|
||||
#define CONFIG_ROOT_RDONLY 1
|
||||
#endif
|
||||
|
||||
! ld86 requires an entry symbol. This may as well be the usual one.
|
||||
.globl _main
|
||||
_main:
|
||||
#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
|
||||
int 3
|
||||
#endif
|
||||
mov ax,#BOOTSEG
|
||||
mov ds,ax
|
||||
mov ax,#INITSEG
|
||||
mov es,ax
|
||||
mov cx,#256
|
||||
sub si,si
|
||||
sub di,di
|
||||
cld
|
||||
rep
|
||||
movsw
|
||||
jmpi go,INITSEG
|
||||
|
||||
! ax and es already contain INITSEG
|
||||
|
||||
go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
|
||||
! bootsect + length of setup + room for stack
|
||||
! 12 is disk parm size
|
||||
|
||||
! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
|
||||
! wouldn't have to worry about this if we checked the top of memory. Also
|
||||
! my BIOS can be configured to put the wini drive tables in high memory
|
||||
! instead of in the vector table. The old stack might have clobbered the
|
||||
! drive table.
|
||||
|
||||
mov ds,ax
|
||||
mov ss,ax ! put stack at INITSEG:0x4000-12.
|
||||
mov sp,di
|
||||
/*
|
||||
* Many BIOS's default disk parameter tables will not
|
||||
* recognize multi-sector reads beyond the maximum sector number
|
||||
* specified in the default diskette parameter tables - this may
|
||||
* mean 7 sectors in some cases.
|
||||
*
|
||||
* Since single sector reads are slow and out of the question,
|
||||
* we must take care of this by creating new parameter tables
|
||||
* (for the first disk) in RAM. We will set the maximum sector
|
||||
* count to 36 - the most we will encounter on an ED 2.88.
|
||||
*
|
||||
* High doesn't hurt. Low does.
|
||||
*
|
||||
* Segments are as follows: ds=es=ss=cs - INITSEG,
|
||||
* fs = 0, gs is unused.
|
||||
*/
|
||||
|
||||
! cx contains 0 from rep movsw above
|
||||
|
||||
mov fs,cx
|
||||
mov bx,#0x78 ! fs:bx is parameter table address
|
||||
push ds
|
||||
seg fs
|
||||
lds si,(bx) ! ds:si is source
|
||||
|
||||
mov cl,#6 ! copy 12 bytes
|
||||
cld
|
||||
push di
|
||||
|
||||
rep
|
||||
movsw
|
||||
|
||||
pop di
|
||||
pop ds
|
||||
|
||||
movb 4(di),*36 ! patch sector count
|
||||
|
||||
seg fs
|
||||
mov (bx),di
|
||||
seg fs
|
||||
mov 2(bx),es
|
||||
|
||||
! load the setup-sectors directly after the bootblock.
|
||||
! Note that 'es' is already set up.
|
||||
! Also cx is 0 from rep movsw above.
|
||||
|
||||
load_setup:
|
||||
xor ah,ah ! reset FDC
|
||||
xor dl,dl
|
||||
int 0x13
|
||||
|
||||
xor dx, dx ! drive 0, head 0
|
||||
mov cl,#0x02 ! sector 2, track 0
|
||||
mov bx,#0x0200 ! address = 512, in INITSEG
|
||||
mov ah,#0x02 ! service 2, nr of sectors
|
||||
mov al,setup_sects ! (assume all on head 0, track 0)
|
||||
int 0x13 ! read it
|
||||
jnc ok_load_setup ! ok - continue
|
||||
|
||||
push ax ! dump error code
|
||||
call print_nl
|
||||
mov bp, sp
|
||||
call print_hex
|
||||
pop ax
|
||||
|
||||
jmp load_setup
|
||||
|
||||
ok_load_setup:
|
||||
|
||||
! Get disk drive parameters, specifically nr of sectors/track
|
||||
|
||||
#if 0
|
||||
|
||||
! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
|
||||
! disks. It doesn't work for one of my BIOS's (1987 Award). It was
|
||||
! fatal not to check the error code.
|
||||
|
||||
xor dl,dl
|
||||
mov ah,#0x08 ! AH=8 is get drive parameters
|
||||
int 0x13
|
||||
xor ch,ch
|
||||
#else
|
||||
|
||||
! It seems that there is no BIOS call to get the number of sectors. Guess
|
||||
! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
|
||||
! 15 if sector 15 can be read. Otherwise guess 9.
|
||||
|
||||
mov si,#disksizes ! table of sizes to try
|
||||
|
||||
probe_loop:
|
||||
lodsb
|
||||
cbw ! extend to word
|
||||
mov sectors, ax
|
||||
cmp si,#disksizes+4
|
||||
jae got_sectors ! if all else fails, try 9
|
||||
xchg ax, cx ! cx = track and sector
|
||||
xor dx, dx ! drive 0, head 0
|
||||
xor bl, bl
|
||||
mov bh,setup_sects
|
||||
inc bh
|
||||
shl bh,#1 ! address after setup (es = cs)
|
||||
mov ax,#0x0201 ! service 2, 1 sector
|
||||
int 0x13
|
||||
jc probe_loop ! try next value
|
||||
|
||||
#endif
|
||||
|
||||
got_sectors:
|
||||
|
||||
! Restore es
|
||||
|
||||
mov ax,#INITSEG
|
||||
mov es,ax
|
||||
|
||||
! Print some inane message
|
||||
|
||||
mov ah,#0x03 ! read cursor pos
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
|
||||
mov cx,#9
|
||||
mov bx,#0x0007 ! page 0, attribute 7 (normal)
|
||||
mov bp,#msg1
|
||||
mov ax,#0x1301 ! write string, move cursor
|
||||
int 0x10
|
||||
|
||||
! ok, we've written the message, now
|
||||
! we want to load the system (at 0x10000)
|
||||
|
||||
mov ax,#SYSSEG
|
||||
mov es,ax ! segment of 0x010000
|
||||
call read_it
|
||||
call kill_motor
|
||||
call print_nl
|
||||
|
||||
! After that we check which root-device to use. If the device is
|
||||
! defined (!= 0), nothing is done and the given device is used.
|
||||
! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
|
||||
! depending on the number of sectors we pretend to know we have.
|
||||
|
||||
seg cs
|
||||
mov ax,root_dev
|
||||
or ax,ax
|
||||
jne root_defined
|
||||
seg cs
|
||||
mov bx,sectors
|
||||
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
|
||||
cmp bx,#15
|
||||
je root_defined
|
||||
mov al,#0x1c ! /dev/PS0 - 1.44Mb
|
||||
cmp bx,#18
|
||||
je root_defined
|
||||
mov al,#0x20 ! /dev/fd0H2880 - 2.88Mb
|
||||
cmp bx,#36
|
||||
je root_defined
|
||||
mov al,#0 ! /dev/fd0 - autodetect
|
||||
root_defined:
|
||||
seg cs
|
||||
mov root_dev,ax
|
||||
|
||||
! after that (everything loaded), we jump to
|
||||
! the setup-routine loaded directly after
|
||||
! the bootblock:
|
||||
|
||||
jmpi 0,SETUPSEG
|
||||
|
||||
! This routine loads the system at address 0x10000, making sure
|
||||
! no 64kB boundaries are crossed. We try to load it as fast as
|
||||
! possible, loading whole tracks whenever we can.
|
||||
!
|
||||
! in: es - starting address segment (normally 0x1000)
|
||||
!
|
||||
sread: .word 0 ! sectors read of current track
|
||||
head: .word 0 ! current head
|
||||
track: .word 0 ! current track
|
||||
|
||||
read_it:
|
||||
mov al,setup_sects
|
||||
inc al
|
||||
mov sread,al
|
||||
mov ax,es
|
||||
test ax,#0x0fff
|
||||
die: jne die ! es must be at 64kB boundary
|
||||
xor bx,bx ! bx is starting address within segment
|
||||
rp_read:
|
||||
#ifdef __BIG_KERNEL__
|
||||
#define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
|
||||
! NOTE: as86 can't assemble this
|
||||
CALL_HIGHLOAD_KLUDGE ! this is within setup.S
|
||||
#else
|
||||
mov ax,es
|
||||
sub ax,#SYSSEG
|
||||
#endif
|
||||
cmp ax,syssize ! have we loaded all yet?
|
||||
jbe ok1_read
|
||||
ret
|
||||
ok1_read:
|
||||
mov ax,sectors
|
||||
sub ax,sread
|
||||
mov cx,ax
|
||||
shl cx,#9
|
||||
add cx,bx
|
||||
jnc ok2_read
|
||||
je ok2_read
|
||||
xor ax,ax
|
||||
sub ax,bx
|
||||
shr ax,#9
|
||||
ok2_read:
|
||||
call read_track
|
||||
mov cx,ax
|
||||
add ax,sread
|
||||
cmp ax,sectors
|
||||
jne ok3_read
|
||||
mov ax,#1
|
||||
sub ax,head
|
||||
jne ok4_read
|
||||
inc track
|
||||
ok4_read:
|
||||
mov head,ax
|
||||
xor ax,ax
|
||||
ok3_read:
|
||||
mov sread,ax
|
||||
shl cx,#9
|
||||
add bx,cx
|
||||
jnc rp_read
|
||||
mov ax,es
|
||||
add ah,#0x10
|
||||
mov es,ax
|
||||
xor bx,bx
|
||||
jmp rp_read
|
||||
|
||||
read_track:
|
||||
pusha
|
||||
pusha
|
||||
mov ax, #0xe2e ! loading... message 2e = .
|
||||
mov bx, #7
|
||||
int 0x10
|
||||
popa
|
||||
|
||||
mov dx,track
|
||||
mov cx,sread
|
||||
inc cx
|
||||
mov ch,dl
|
||||
mov dx,head
|
||||
mov dh,dl
|
||||
and dx,#0x0100
|
||||
mov ah,#2
|
||||
|
||||
push dx ! save for error dump
|
||||
push cx
|
||||
push bx
|
||||
push ax
|
||||
|
||||
int 0x13
|
||||
jc bad_rt
|
||||
add sp, #8
|
||||
popa
|
||||
ret
|
||||
|
||||
bad_rt: push ax ! save error code
|
||||
call print_all ! ah = error, al = read
|
||||
|
||||
|
||||
xor ah,ah
|
||||
xor dl,dl
|
||||
int 0x13
|
||||
|
||||
|
||||
add sp, #10
|
||||
popa
|
||||
jmp read_track
|
||||
|
||||
/*
|
||||
* print_all is for debugging purposes.
|
||||
* It will print out all of the registers. The assumption is that this is
|
||||
* called from a routine, with a stack frame like
|
||||
* dx
|
||||
* cx
|
||||
* bx
|
||||
* ax
|
||||
* error
|
||||
* ret <- sp
|
||||
*
|
||||
*/
|
||||
|
||||
print_all:
|
||||
mov cx, #5 ! error code + 4 registers
|
||||
mov bp, sp
|
||||
|
||||
print_loop:
|
||||
push cx ! save count left
|
||||
call print_nl ! nl for readability
|
||||
|
||||
cmp cl, #5
|
||||
jae no_reg ! see if register name is needed
|
||||
|
||||
mov ax, #0xe05 + 'A - 1
|
||||
sub al, cl
|
||||
int 0x10
|
||||
|
||||
mov al, #'X
|
||||
int 0x10
|
||||
|
||||
mov al, #':
|
||||
int 0x10
|
||||
|
||||
no_reg:
|
||||
add bp, #2 ! next register
|
||||
call print_hex ! print it
|
||||
pop cx
|
||||
loop print_loop
|
||||
ret
|
||||
|
||||
print_nl:
|
||||
mov ax, #0xe0d ! CR
|
||||
int 0x10
|
||||
mov al, #0xa ! LF
|
||||
int 0x10
|
||||
ret
|
||||
|
||||
/*
|
||||
* print_hex is for debugging purposes, and prints the word
|
||||
* pointed to by ss:bp in hexadecimal.
|
||||
*/
|
||||
|
||||
print_hex:
|
||||
mov cx, #4 ! 4 hex digits
|
||||
mov dx, (bp) ! load word into dx
|
||||
print_digit:
|
||||
rol dx, #4 ! rotate so that lowest 4 bits are used
|
||||
mov ax, #0xe0f ! ah = request, al = mask for nybble
|
||||
and al, dl
|
||||
add al, #0x90 ! convert al to ascii hex (four instructions)
|
||||
daa
|
||||
adc al, #0x40
|
||||
daa
|
||||
int 0x10
|
||||
loop print_digit
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* This procedure turns off the floppy drive motor, so
|
||||
* that we enter the kernel in a known state, and
|
||||
* don't have to worry about it later.
|
||||
*/
|
||||
kill_motor:
|
||||
push dx
|
||||
mov dx,#0x3f2
|
||||
xor al, al
|
||||
outb
|
||||
pop dx
|
||||
ret
|
||||
|
||||
sectors:
|
||||
.word 0
|
||||
|
||||
disksizes:
|
||||
.byte 36,18,15,9
|
||||
|
||||
msg1:
|
||||
.byte 13,10
|
||||
.ascii "Loading"
|
||||
|
||||
.org 497
|
||||
setup_sects:
|
||||
.byte SETUPSECS
|
||||
root_flags:
|
||||
.word CONFIG_ROOT_RDONLY
|
||||
syssize:
|
||||
.word SYSSIZE
|
||||
swap_dev:
|
||||
.word SWAP_DEV
|
||||
ram_size:
|
||||
.word RAMDISK
|
||||
vid_mode:
|
||||
.word SVGA_MODE
|
||||
root_dev:
|
||||
.word ROOT_DEV
|
||||
boot_flag:
|
||||
.word 0xAA55
|
||||
|
||||
</pre>
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1995-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
20
study/sabre/os/files/Booting/MyBootSector.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<title>Operating Systems: My Experiences with the Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=6><b>My Experiences with the Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
When I first started playing with OS kind of topics, the first thing that I did was make a bootsector that I stuck on a floppy... This was very interesting, as I was basically crafting my own OS. Since then, I have been distracted to work on other things... and the code has been rotting on my hard drive.<p>
|
||||
|
||||
When I was doing a clean up of my drive, I noticed it, and being the good netizen that I am, I'm giving it away. Although I haven't tested it for more than 3 years now, I believe it does do some stuff... so if you'd like to play with it, scrap a floppy and copy the boot sector onto the disk.<p>
|
||||
|
||||
This also comes with a small set of utilities (and their source as well). These were originally written in Turbo Pascal (I'm sorry! Really I am! :) with a lot of inline assembler. If you don't have Turbo Pascal, you can either use the included EXE file or convert them to C. If you do port them to C, please send them my way and other people can use them.<p>
|
||||
|
||||
Oh, the catch... there's always a catch, isn't there? I haven't worked with this stuff for over 3 years now... Which means that I probably won't be able to do an adequate job explaining it... :) It is somewhat documented... and it has function names that are longer than a character. Other than that, I can't offer much support. There are some batch files in the source directory (<TT>BOOTSEC</TT>) for doing things like compiling it and copying it onto the disk. The tools directory (<TT>NEWFAT</TT>) has stuff the tools source and executables in it.<p>
|
||||
|
||||
Pulling back very old memories, I remember that I was just starting to implement a filesystem with program loading support... other than that, you're on your own. :) If you would like to contribute something back to this page, feel free to email it to me, and I'll put your stuff here (with full credits of course)... Anyways, download it below!<p>
|
||||
|
||||
<center><font size=6><a href="MyBootSector.zip">download</a></font></center>
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1994-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
272
study/sabre/os/files/Booting/PolyOS.html
Normal file
@@ -0,0 +1,272 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>AT&T Assembly from the Ground Up</TITLE>
|
||||
<META NAME="description" content="Code X software: Programming to a Higher Power, DJGPP and X11 Programming (binaries and source code), Linux and DOS (32-bit pmode), POV-Ray. Check out Code X for some cool games and X-Windows programs.">
|
||||
<META NAME="keywords" content="code x Code X codex CodeX games graphics djgpp DJGPP source code X11 x11 X-Windows x-windows programming linux Linux Jeff Weeks jeff weeks">
|
||||
<META NAME="GENERATOR" CONTENT = "I made this!">
|
||||
<META NAME="andrew_fursman" CONTENT="complete and utter looser">
|
||||
<META NAME="microsoft" CONTENT="lies and monopolies">
|
||||
</HEAD>
|
||||
|
||||
<U>
|
||||
<FONT SIZE=+3>W</FONT>RITING
|
||||
<FONT SIZE=+3>A</FONT>
|
||||
<FONT SIZE=+3>B</FONT>OOTSECTOR
|
||||
</U>
|
||||
<BR><FONT SIZE=-1>(c)1997 Jeff Weeks and Code X software</FONT><BR>
|
||||
<BR>
|
||||
|
||||
Writting your own boot sector is probably actually easier then you think.
|
||||
All you really need to know is how the Intel processor boots up. A valid boot
|
||||
sector has the code 0xAA55 at an offset of 510, and is located in the very
|
||||
first sector of the disk. Therefore, the BIOS simply checks drive 0 (A:)
|
||||
for this code. If not found, it then checks drive 128 (C:). If a valid boot
|
||||
sector is found, it is loaded into memory at location 0:07C00h.<BR>
|
||||
<BR>
|
||||
So, all you have to do is write a boot sector, assemble it into a plain binary
|
||||
file (their is no format or header to a boot sector), and write it to the
|
||||
first sector of your disk. The best way to do that would be to either use
|
||||
nasm (The netwide assembler can produce plain binary files) or assemble into a
|
||||
DOS .EXE and remove the first 512 bytes. You can also write your own program
|
||||
to write the bootsector to sector 1 of the disk using BIOS INT 13h AH=02h.<BR>
|
||||
<BR>
|
||||
Pretty simple eh? Well, in case you're still a little confused, here's a
|
||||
little bootsector from PolyOS that simply switches to protected mode,
|
||||
after checking that you have a 386+ computer. Actually, it even loads in
|
||||
the PolyFS superblock and checks if it's valid, but that's about it. Soon
|
||||
it'll load in the kernel and jump to it. The bootesctor was written with Nasm.
|
||||
<BR>
|
||||
|
||||
<PRE>
|
||||
; ------------------------------------------------------------------------
|
||||
; PolyOS boot loader code (c)1997 Jeff Weeks of Code X Software
|
||||
; ------------------------------------------------------------------------
|
||||
; This little bit of assembly is the boot loader for my operating system.
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0]
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SECTOR ONE: THE BOOT LOADER
|
||||
; ------------------------------------------------------------------------
|
||||
; This sector detects your processor. If a 386 is found, it loads the
|
||||
; kernel from the disk and executes it (atleast it will in the future :).
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
jmp start ; skip over our data and functions
|
||||
|
||||
; -------------------------------------
|
||||
; Data used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
bootdrv db 0
|
||||
bootmsg db 'Booting PolyOS (c)1997 Cipher of Code X',13,10,0
|
||||
loadmsg db 'Loading kernel',13,10,0
|
||||
jumpmsg db 'Jumping to kernel',13,10,0
|
||||
rebootmsg db 'Press any key to reboot',13,10,0
|
||||
|
||||
; these are used in the processor identification
|
||||
processormsg db 'Checking for 386+ processor: ',0
|
||||
need386 db 'Sorry... 386+ required!',13,10,0
|
||||
found386 db 'Excellent!',13,10,0
|
||||
|
||||
; these are used when entering protected mode
|
||||
a20msg db 'Setting A20 address line',13,10,0
|
||||
pmodemsg db 'Setting CR0 -> Entering PMode',13,10,0
|
||||
|
||||
; Here's the locations of my IDT and GDT. Remember, Intel's are
|
||||
; little endian processors, therefore, these are in reversed order.
|
||||
; Also note that lidt and lgdt accept a 32-bit address and 16-bit
|
||||
; limit, therefore, these are 48-bit variables.
|
||||
pIDT dw 7FFh ; limit of 256 IDT slots
|
||||
dd 0000h ; starting at 0000
|
||||
|
||||
pGDT dw 17FFh ; limit of 768 GDT slots
|
||||
dd 0800h ; starting at 0800h (after IDT)
|
||||
|
||||
; ------------------------------------------
|
||||
; Functions used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
detect_cpu:
|
||||
mov si, processormsg ; tell the user what we're doing
|
||||
call message
|
||||
|
||||
; test if 8088/8086 is present (flag bits 12-15 will be set)
|
||||
pushf ; save the flags original value
|
||||
|
||||
xor ah,ah ; ah = 0
|
||||
push ax ; copy ax into the flags
|
||||
popf ; with bits 12-15 clear
|
||||
|
||||
pushf ; Read flags back into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are set
|
||||
cmp ah,0f0h
|
||||
je no386 ; no 386 detected (8088/8086 present)
|
||||
|
||||
; check for a 286 (bits 12-15 are clear)
|
||||
mov ah,0f0h ; set bits 12-15
|
||||
push ax ; copy ax onto the flags
|
||||
popf
|
||||
|
||||
pushf ; copy the flags into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are clear
|
||||
jz no386 ; no 386 detected (80286 present)
|
||||
popf ; pop the original flags back
|
||||
|
||||
mov si, found386
|
||||
call message
|
||||
|
||||
ret ; no 8088/8086 or 286, so ateast 386
|
||||
no386:
|
||||
mov si,need386 ; tell the user the problem
|
||||
call message
|
||||
jmp reboot ; and reboot when key pressed
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
message: ; Dump ds:si to screen.
|
||||
lodsb ; load byte at ds:si into al
|
||||
or al,al ; test if character is 0 (end)
|
||||
jz done
|
||||
mov ah,0eh ; put character
|
||||
mov bx,0007 ; attribute
|
||||
int 0x10 ; call BIOS
|
||||
jmp message
|
||||
done:
|
||||
ret
|
||||
; ------------------------------------------------------------------
|
||||
getkey:
|
||||
mov ah, 0 ; wait for key
|
||||
int 016h
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
reboot:
|
||||
mov si, rebootmsg ; be polite, and say we're rebooting
|
||||
call message
|
||||
call getkey ; and even wait for a key :)
|
||||
|
||||
db 0EAh ; machine language to jump to FFFF:0000 (reboot)
|
||||
dw 0000h
|
||||
dw 0FFFFh
|
||||
; no ret required; we're rebooting! (Hey, I just saved a byte :)
|
||||
|
||||
; -------------------------------------------
|
||||
; The actual code of our boot loading process
|
||||
; ------------------------------------------------------------------------
|
||||
start:
|
||||
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
|
||||
mov ds,ax ; Therefore, we don't have to add 07C00h to all our data
|
||||
|
||||
mov [bootdrv], dl ; quickly save what drive we booted from
|
||||
|
||||
cli ; clear interrupts while we setup a stack
|
||||
mov ax,0x9000 ; this seems to be the typical place for a stack
|
||||
mov ss,ax
|
||||
mov sp,0xffff ; let's use the whole segment. Why not? We can :)
|
||||
sti ; put our interrupts back on
|
||||
|
||||
; Interestingly enough, apparently the processor will disable
|
||||
; interupts itself when you directly access the stack segment!
|
||||
; Atleast it does in protected mode, I'm not sure about real mode.
|
||||
|
||||
mov si,bootmsg ; display our startup message
|
||||
call message
|
||||
|
||||
call detect_cpu ; check if we've got a 386
|
||||
|
||||
.386 ; use 386 instructions from now on (I don't want to manually include
|
||||
; operand-size(66h) or address-size(67h) prefixes... it's annoying :)
|
||||
|
||||
mov si,loadmsg ; tell the user we're loading the kernel
|
||||
call message
|
||||
call getkey
|
||||
|
||||
read_me:
|
||||
; first, reset the disk controller
|
||||
xor ax, ax
|
||||
int 0x13
|
||||
jc reboot ; reboot on error
|
||||
|
||||
; then load in the PolyFS superblock
|
||||
mov ax,0x09000 ; superblock goes to 9000:0000 (above stack)
|
||||
mov es,ax
|
||||
xor bx,bx
|
||||
|
||||
; I could condense a few of these high/low 8-bit movs into one 16-bit
|
||||
; mov, but, for simplicity, I'll leave it as is, unless necessary.
|
||||
mov ax,0x0202 ; load one block (two sectors)
|
||||
mov ch,0 ; cylinder = 0
|
||||
mov cl,3 ; sector = 2 (starts at sector 1 not 0)
|
||||
mov dh,0 ; head = 0 = side one
|
||||
mov dl,[bootdrv] ; disk = what we booted from
|
||||
int 0x13 ; read it
|
||||
jc read_me ; if there's an error then we'll try again.
|
||||
; Often there is not error but requires a few
|
||||
; tries. Ofcourse, this may end up as an
|
||||
; infinite loop... but only on a bad disk...
|
||||
|
||||
; Check if we have a valid super block (BTW: ES still equals 0x9000)
|
||||
mov di, 0 ; offset of PolyFS magic signature
|
||||
mov si, polymagic ; offset of PolyFS magic to check for (in ds)
|
||||
cmpsw ; compare ES:[DI] with DS:[SI]
|
||||
jnz reboot ; reboot on error (otherwise, we've got a PolyFS)
|
||||
|
||||
; Ideally, we'd load the kernel right here
|
||||
|
||||
mov si, a20msg ; tell the user we're setting the A20 line
|
||||
call message
|
||||
|
||||
; set A20 line
|
||||
cli ; no more interuptions! :)
|
||||
xor cx, cx
|
||||
clear_buf:
|
||||
in al, 64h ; get input from keyboard status port
|
||||
test al, 02h ; test the buffer full flag
|
||||
loopnz clear_buf ; loop until buffer is empty
|
||||
mov al, 0D1h ; keyboard: write to output port
|
||||
out 64h, al ; output command to keyboard
|
||||
clear_buf2:
|
||||
in al, 64h ; wait 'till buffer is empty again
|
||||
test al, 02h
|
||||
loopnz clear_buf2
|
||||
mov al, 0dfh ; keyboard: set A20
|
||||
out 60h, al ; send it to the keyboard controller
|
||||
mov cx, 14h
|
||||
wait_kbc: ; this is approx. a 25uS delay to wait
|
||||
out 0edh, ax ; for the kb controler to execute our
|
||||
loop wait_kbc ; command.
|
||||
|
||||
; the A20 line is on now. Let's load in our ITD and GDT tables...
|
||||
; Ideally, there will actually be data in their locations (by loading
|
||||
; the kernel)
|
||||
lidt [pIDT]
|
||||
lgdt [pGDT]
|
||||
|
||||
; now let's enter pmode...
|
||||
mov si, pmodemsg
|
||||
call message
|
||||
call getkey
|
||||
|
||||
mov eax, cr0 ; load the control register in
|
||||
or al, 1 ; set bit 1: pmode bit
|
||||
mov cr0, eax ; copy it back to the control register
|
||||
jmp $+2 ; and clear the prefetch queue
|
||||
nop
|
||||
nop
|
||||
|
||||
; jump to the kernel that we've loaded in...
|
||||
; For now, we'll actually just reboot (this really doesn't
|
||||
; work in protected mode, but it does reboot :)
|
||||
db 0xEA
|
||||
dw 0x0000
|
||||
dw 0xFFFF
|
||||
|
||||
; The boot sector is supposed to have to have 0xAA55 at the end of
|
||||
; the sector (the word at 510 bytes) to be loaded by the BIOS...
|
||||
times 510-($-$$) db 0
|
||||
dw 0xAA55
|
||||
</PRE>
|
||||
</HTML>
|
||||
BIN
study/sabre/os/files/Booting/bootsec1.zip
Normal file
BIN
study/sabre/os/files/Booting/bootsec2.zip
Normal file
195
study/sabre/os/files/Booting/enableA20.s
Normal file
@@ -0,0 +1,195 @@
|
||||
;;
|
||||
;; enableA20.s (adapted from Visopsys OS-loader)
|
||||
;;
|
||||
;; Copyright (c) 2000, J. Andrew McLaughlin
|
||||
;; You're free to use this code in any manner you like, as long as this
|
||||
;; notice is included (and you give credit where it is due), and as long
|
||||
;; as you understand and accept that it comes with NO WARRANTY OF ANY KIND.
|
||||
;; Contact me at jamesamc@yahoo.com about any bugs or problems.
|
||||
;;
|
||||
|
||||
enableA20:
|
||||
;; This subroutine will enable the A20 address line in the keyboard
|
||||
;; controller. Takes no arguments. Returns 0 in EAX on success,
|
||||
;; -1 on failure. Written for use in 16-bit code, see lines marked
|
||||
;; with 32-BIT for use in 32-bit code.
|
||||
|
||||
pusha
|
||||
|
||||
;; Make sure interrupts are disabled
|
||||
cli
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt1:
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait1
|
||||
|
||||
;; Tell the controller we want to read the current status.
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait1
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Save the current value of (E)AX
|
||||
push AX ; 16-BIT
|
||||
;; push EAX ; 32-BIT
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait2:
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait2
|
||||
|
||||
;; Tell the controller we want to write the status byte again
|
||||
mov AL, 0D1h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready for the data
|
||||
.commandWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait3
|
||||
|
||||
;; Write the new value to port 60h. Remember we saved the old
|
||||
;; value on the stack
|
||||
pop AX ; 16-BIT
|
||||
;; pop EAX ; 32-BIT
|
||||
|
||||
;; Turn on the A20 enable bit
|
||||
or AL, 00000010b
|
||||
out 60h, AL
|
||||
|
||||
;; Finally, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait4:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait4
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait2:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait2
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on.
|
||||
jc .success
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt1
|
||||
|
||||
|
||||
;; Well, our initial attempt to set A20 has failed. Now we will
|
||||
;; try a backup method (which is supposedly not supported on many
|
||||
;; chipsets, but which seems to be the only method that works on
|
||||
;; other chipsets).
|
||||
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt2:
|
||||
;; Wait for the keyboard to be ready for another command
|
||||
.commandWait6:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait6
|
||||
|
||||
;; Tell the controller we want to turn on A20
|
||||
mov AL, 0DFh
|
||||
out 64h, AL
|
||||
|
||||
;; Again, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait7:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait7
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait3
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on, but we might warn
|
||||
;; that we had to use this alternate method
|
||||
jc .warn
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt2
|
||||
|
||||
|
||||
;; OK, we weren't able to set the A20 address line. Do you want
|
||||
;; to put an error message here?
|
||||
jmp .fail
|
||||
|
||||
|
||||
.warn:
|
||||
;; Here you may or may not want to print a warning message about
|
||||
;; the fact that we had to use the nonstandard alternate enabling
|
||||
;; method
|
||||
|
||||
.success:
|
||||
sti
|
||||
popa
|
||||
xor EAX, EAX
|
||||
ret
|
||||
|
||||
.fail:
|
||||
sti
|
||||
popa
|
||||
mov EAX, -1
|
||||
ret
|
||||
233
study/sabre/os/files/Booting/gbootsect.txt
Normal file
@@ -0,0 +1,233 @@
|
||||
Bootsector authoring by Gareth Owen
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
-=- gaz@athene.co.uk -=-
|
||||
|
||||
Requirements
|
||||
============
|
||||
During this article I assume that you have good knowledge of the
|
||||
assembly language and intel architecture.
|
||||
If not, read an assembly tutorial, they aren't hard to find...
|
||||
|
||||
Start
|
||||
=====
|
||||
|
||||
Creating your own bootsector is simpler than you may think,
|
||||
the only requirement is that the bootsector is 512 bytes long, and at
|
||||
offset 0x1FE (decimal=510), the word 0xAA55 is placed. This is the first
|
||||
thing the BIOS does when the PC boots up, it first looks on the first
|
||||
floppy drive at the first sector for 0xAA55 at the end, and if it finds it
|
||||
then it loads it into memory, and starts executing it, otherwise it trys the
|
||||
primary harddisk, and if that isn't found it just bombs out with an error.
|
||||
|
||||
You should place your boot sector at:
|
||||
Sector 1
|
||||
Cylinder 0
|
||||
Head 0
|
||||
|
||||
I recommend you start playing about with floppys first instead of your hard disk
|
||||
because the hard disk bootsector stores information about the file system if you
|
||||
are running DOS/Windows, if you overrite that, then you have just lost your
|
||||
hard disk contents :-)
|
||||
|
||||
The BIOS loads the bootsector at linear offset 0x7C00, the state of
|
||||
the registers are:
|
||||
|
||||
DL = Boot drive, 1h = floppy1, 80h = primary harddisk, etc
|
||||
CS = 0
|
||||
IP = 0x7c00
|
||||
|
||||
So instead of adding [ORG 7C00h] to the top of your file, you can add:
|
||||
|
||||
mov ax, 0x7C0
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
And that will set-up the segment registers so they point to the start of
|
||||
your bootsector..
|
||||
|
||||
Most boot sectors usually just store the boot drive, load the kernel
|
||||
from disk, and jump to it.. Some will also load protected mode.
|
||||
|
||||
Since most people find it easier looking at source code and figuring
|
||||
it out than reading documentation i have included sources for a boot
|
||||
sector and a boot sector writter.
|
||||
|
||||
Here is the bootsector...
|
||||
|
||||
;******************* START ************************
|
||||
|
||||
; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
|
||||
; This should be accompanied with an article explaining bootsectors
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0] ; Data offset = 0
|
||||
|
||||
jmp start ; skip over our data and functions, we cannot execute data :-),
|
||||
; well, you can, but i am not held responsible for the results :)
|
||||
|
||||
; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
|
||||
; This should be accompanied with an article explaining bootsectors
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0] ; Data offset = 0
|
||||
|
||||
jmp start ; skip over our data and functions, we cannot execute data :-),
|
||||
; well, you can, but i am not held responsible for the results :)
|
||||
|
||||
; -------------------------------------
|
||||
; Data used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
bootdrv db 0
|
||||
bootmsg db 'Gareth Owen',39,'s Boot Sector Example',13,10,0
|
||||
|
||||
rebootmsg db 'Press any key to reboot',13,10,0
|
||||
|
||||
; these are used in the processor identification
|
||||
processormsg db 'Checking for 386+ processor: ',0
|
||||
need386 db 'Sorry... 386+ required!',13,10,0
|
||||
found386 db 'Found!',13,10,0
|
||||
|
||||
whatever db 'Insert your code to do something here',13,10,0
|
||||
|
||||
;*******************************************
|
||||
; Functions we are going to use ...
|
||||
;*******************************************
|
||||
detect_cpu:
|
||||
mov si, processormsg ; tell the user what we're doing
|
||||
call message
|
||||
|
||||
; test if 8088/8086 is present (flag bits 12-15 will be set)
|
||||
pushf ; save the flags original value
|
||||
|
||||
xor ah,ah ; ah = 0
|
||||
push ax ; copy ax into the flags
|
||||
popf ; with bits 12-15 clear
|
||||
|
||||
pushf ; Read flags back into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are set
|
||||
cmp ah,0f0h
|
||||
je no386 ; no 386 detected (8088/8086 present)
|
||||
|
||||
; check for a 286 (bits 12-15 are clear)
|
||||
mov ah,0f0h ; set bits 12-15
|
||||
push ax ; copy ax onto the flags
|
||||
popf
|
||||
|
||||
pushf ; copy the flags into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are clear
|
||||
jz no386 ; no 386 detected (80286 present)
|
||||
popf ; pop the original flags back
|
||||
|
||||
mov si, found386
|
||||
call message
|
||||
|
||||
ret ; no 8088/8086 or 286, so ateast 386
|
||||
no386:
|
||||
mov si,need386 ; tell the user the problem
|
||||
call message
|
||||
jmp reboot ; and reboot when key pressed
|
||||
|
||||
; ********************************************************************
|
||||
message: ; Dump ds:si to screen.
|
||||
lodsb ; load byte at ds:si into al
|
||||
or al,al ; test if character is 0 (end)
|
||||
jz done
|
||||
mov ah,0eh ; put character
|
||||
mov bx,0007 ; attribute
|
||||
int 0x10 ; call BIOS
|
||||
jmp message
|
||||
done:
|
||||
ret
|
||||
; ********************************************************************
|
||||
getkey:
|
||||
mov ah, 0 ; wait for key
|
||||
int 016h
|
||||
ret
|
||||
|
||||
; ********************************************************************
|
||||
reboot:
|
||||
mov si, rebootmsg ; be polite, and say we're rebooting
|
||||
call message
|
||||
call getkey ; and even wait for a key :)
|
||||
|
||||
db 0EAh ; machine language to jump to FFFF:0000 (reboot)
|
||||
|
||||
dw 0000h
|
||||
dw 0FFFFh
|
||||
; no ret required; we're rebooting! (Hey, I just saved a byte :)
|
||||
|
||||
; *******************************************
|
||||
; The actual code of our boot loading process
|
||||
; *******************************************
|
||||
start:
|
||||
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
|
||||
mov ds,ax ; Therefore, we don't have to add 07C00h to all our
|
||||
data
|
||||
|
||||
mov [bootdrv], dl ; quickly save what drive we booted from
|
||||
|
||||
cli ; clear interrupts while we setup a stack
|
||||
mov ax,0x9000 ; this seems to be the typical place for a stack
|
||||
mov ss,ax
|
||||
mov sp,0xffff ; let's use the whole segment. Why not? We can :)
|
||||
sti ; put our interrupts back on
|
||||
|
||||
; Interestingly enough, apparently the processor will disable
|
||||
; interupts itself when you directly access the stack segment!
|
||||
; Atleast it does in protected mode, I'm not sure about real mode.
|
||||
|
||||
mov si,bootmsg ; display our startup message
|
||||
call message
|
||||
|
||||
call detect_cpu ; check if we've got a 386
|
||||
|
||||
.386 ; use 386 instructions from now on (I don't want to manually include
|
||||
; operand-size(66h) or address-size(67h) prefixes... it's annoying :)
|
||||
|
||||
mov si,whatever ; tell the user we're not doing anything interesting here
|
||||
call message
|
||||
call getkey
|
||||
|
||||
call reboot
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0xAA55
|
||||
|
||||
;******************** GBOOTSECT END *************************
|
||||
|
||||
Here is the code for writting the bootsector to a floppy disk.
|
||||
It has been compiled with DJGPP for DOS.
|
||||
It writes the file 'bootsect', onto Sector 1, Cylinder 0, Head 0 of
|
||||
the floppy drive.
|
||||
|
||||
//***************START****************
|
||||
#include <bios.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
FILE *in;
|
||||
unsigned char buffer[520];
|
||||
|
||||
if((in = fopen("bootsect", "rb"))==NULL)
|
||||
{
|
||||
printf("Error loading file\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fread(&buffer, 512, 1, in);
|
||||
|
||||
while(biosdisk(3, 0, 0, 0, 1, 1, buffer));
|
||||
|
||||
fclose(in);
|
||||
}
|
||||
//*************END****************************
|
||||
|
||||
Well, if you still don't understand something, then mail me
|
||||
at gaz@athene.co.uk and i'll help you out
|
||||
|
||||
- Gareth Owen
|
||||
7
study/sabre/os/files/Booting/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
272
study/sabre/os/files/Booting/mbr.txt
Normal file
@@ -0,0 +1,272 @@
|
||||
How It Works -- Master Boot Record
|
||||
|
||||
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
|
||||
|
||||
|
||||
MASTER BOOT RECORD
|
||||
|
||||
This article is a disassembly of a Master Boot Record (MBR). The
|
||||
MBR is the sector at cylinder 0, head 0, sector 1 of a hard disk.
|
||||
An MBR is created by the FDISK program. The FDISK program of all
|
||||
operating systems must create a functionally similar MBR. The MBR
|
||||
is first of what could be many partition sectors, each one
|
||||
containing a four entry partition table.
|
||||
|
||||
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 MBR program code starts at offset 0000.
|
||||
The MBR messages start at offset 008b.
|
||||
The partition table starts at offset 00be.
|
||||
The signature is at offset 00fe.
|
||||
|
||||
Here is a summary of what this thing does:
|
||||
|
||||
If an active partition is found, that partition's boot record
|
||||
is read into 0000:7c00 and the MBR code jumps to 0000:7c00
|
||||
with SI pointing to the partition table entry that describes
|
||||
the partition being booted. The boot record program uses this
|
||||
data to determine the drive being booted from and the location
|
||||
of the partition on the disk.
|
||||
|
||||
If no active partition table enty is found, ROM BASIC is
|
||||
entered via INT 18. All other errors cause a system hang, see
|
||||
label HANG.
|
||||
|
||||
NOTES (VERY IMPORTANT):
|
||||
|
||||
1) The first byte of an active partition table entry is 80.
|
||||
This byte is loaded into the DL register before INT 13 is
|
||||
called to read the boot sector. When INT 13 is called, DL is
|
||||
the BIOS device number. Because of this, the boot sector read
|
||||
by this MBR program can only be read from BIOS device number
|
||||
80 (the first hard disk). This is one of the reasons why it
|
||||
is usually not possible to boot from any other hard disk.
|
||||
|
||||
2) The MBR program uses the CHS based INT 13H AH=02H call to
|
||||
read the boot sector of the active partition. The location of
|
||||
the active partition's boot sector is in the partition table
|
||||
entry in CHS format. If the drive is >528MB, this CHS must be
|
||||
a translated CHS (or L-CHS, see my BIOS TYPES document).
|
||||
No addresses in LBA form are used (another reason why LBA
|
||||
doesn't solve the >528MB problem).
|
||||
|
||||
=====
|
||||
|
||||
Here is the entire MBR record (hex dump and ascii).
|
||||
|
||||
OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F *0123456789ABCDEF*
|
||||
000000 fa33c08e d0bc007c 8bf45007 501ffbfc *.3.....|..P.P...*
|
||||
000010 bf0006b9 0001f2a5 ea1d0600 00bebe07 *................*
|
||||
000020 b304803c 80740e80 3c00751c 83c610fe *...<.t..<.u.....*
|
||||
000030 cb75efcd 188b148b 4c028bee 83c610fe *.u......L.......*
|
||||
000040 cb741a80 3c0074f4 be8b06ac 3c00740b *.t..<.t.....<.t.*
|
||||
000050 56bb0700 b40ecd10 5eebf0eb febf0500 *V.......^.......*
|
||||
000060 bb007cb8 010257cd 135f730c 33c0cd13 *..|...W.._s.3...*
|
||||
000070 4f75edbe a306ebd3 bec206bf fe7d813d *Ou...........}.=*
|
||||
000080 55aa75c7 8bf5ea00 7c000049 6e76616c *U.u.....|..Inval*
|
||||
000090 69642070 61727469 74696f6e 20746162 *id partition tab*
|
||||
0000a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading*
|
||||
0000b0 206f7065 72617469 6e672073 79737465 * operating syste*
|
||||
0000c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat*
|
||||
0000d0 696e6720 73797374 656d0000 00000000 *ing system......*
|
||||
0000e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000f0 TO 0001af SAME AS ABOVE
|
||||
0001b0 00000000 00000000 00000000 00008001 *................*
|
||||
0001c0 0100060d fef83e00 00000678 0d000000 *......>....x....*
|
||||
0001d0 00000000 00000000 00000000 00000000 *................*
|
||||
0001e0 00000000 00000000 00000000 00000000 *................*
|
||||
0001f0 00000000 00000000 00000000 000055aa *..............U.*
|
||||
|
||||
=====
|
||||
|
||||
Here is the disassembly of the MBR...
|
||||
|
||||
This sector is initially loaded into memory at 0000:7c00 but
|
||||
it immediately relocates itself to 0000:0600.
|
||||
|
||||
BEGIN: NOW AT 0000:7C00, RELOCATE
|
||||
|
||||
0000:7C00 FA CLI disable int's
|
||||
0000:7C01 33C0 XOR AX,AX set stack seg to 0000
|
||||
0000:7C03 8ED0 MOV SS,AX
|
||||
0000:7C05 BC007C MOV SP,7C00 set stack ptr to 7c00
|
||||
0000:7C08 8BF4 MOV SI,SP SI now 7c00
|
||||
0000:7C0A 50 PUSH AX
|
||||
0000:7C0B 07 POP ES ES now 0000:7c00
|
||||
0000:7C0C 50 PUSH AX
|
||||
0000:7C0D 1F POP DS DS now 0000:7c00
|
||||
0000:7C0E FB STI allow int's
|
||||
0000:7C0F FC CLD clear direction
|
||||
0000:7C10 BF0006 MOV DI,0600 DI now 0600
|
||||
0000:7C13 B90001 MOV CX,0100 move 256 words (512 bytes)
|
||||
0000:7C16 F2 REPNZ move MBR from 0000:7c00
|
||||
0000:7C17 A5 MOVSW to 0000:0600
|
||||
0000:7C18 EA1D060000 JMP 0000:061D jmp to NEW_LOCATION
|
||||
|
||||
NEW_LOCATION: NOW AT 0000:0600
|
||||
|
||||
0000:061D BEBE07 MOV SI,07BE point to first table entry
|
||||
0000:0620 B304 MOV BL,04 there are 4 table entries
|
||||
|
||||
SEARCH_LOOP1: SEARCH FOR AN ACTIVE ENTRY
|
||||
|
||||
0000:0622 803C80 CMP BYTE PTR [SI],80 is this the active entry?
|
||||
0000:0625 740E JZ FOUND_ACTIVE yes
|
||||
0000:0627 803C00 CMP BYTE PTR [SI],00 is this an inactive entry?
|
||||
0000:062A 751C JNZ NOT_ACTIVE no
|
||||
0000:062C 83C610 ADD SI,+10 incr table ptr by 16
|
||||
0000:062F FECB DEC BL decr count
|
||||
0000:0631 75EF JNZ SEARCH_LOOP1 jmp if not end of table
|
||||
0000:0633 CD18 INT 18 GO TO ROM BASIC
|
||||
|
||||
FOUND_ACTIVE: FOUND THE ACTIVE ENTRY
|
||||
|
||||
0000:0635 8B14 MOV DX,[SI] set DH/DL for INT 13 call
|
||||
0000:0637 8B4C02 MOV CX,[SI+02] set CH/CL for INT 13 call
|
||||
0000:063A 8BEE MOV BP,SI save table ptr
|
||||
|
||||
SEARCH_LOOP2: MAKE SURE ONLY ONE ACTIVE ENTRY
|
||||
|
||||
0000:063C 83C610 ADD SI,+10 incr table ptr by 16
|
||||
0000:063F FECB DEC BL decr count
|
||||
0000:0641 741A JZ READ_BOOT jmp if end of table
|
||||
0000:0643 803C00 CMP BYTE PTR [SI],00 is this an inactive entry?
|
||||
0000:0646 74F4 JZ SEARCH_LOOP2 yes
|
||||
|
||||
NOT_ACTIVE: MORE THAN ONE ACTIVE ENTRY FOUND
|
||||
|
||||
0000:0648 BE8B06 MOV SI,068B display "Invld prttn tbl"
|
||||
|
||||
DISPLAY_MSG: DISPLAY MESSAGE LOOP
|
||||
|
||||
0000:064B AC LODSB get char of message
|
||||
0000:064C 3C00 CMP AL,00 end of message
|
||||
0000:064E 740B JZ HANG yes
|
||||
0000:0650 56 PUSH SI save SI
|
||||
0000:0651 BB0700 MOV BX,0007 screen attributes
|
||||
0000:0654 B40E MOV AH,0E output 1 char of message
|
||||
0000:0656 CD10 INT 10 to the display
|
||||
0000:0658 5E POP SI restore SI
|
||||
0000:0659 EBF0 JMP DISPLAY_MSG do it again
|
||||
|
||||
HANG: HANG THE SYSTEM LOOP
|
||||
|
||||
0000:065B EBFE JMP HANG sit and stay!
|
||||
|
||||
READ_BOOT: READ ACTIVE PARITION BOOT RECORD
|
||||
|
||||
0000:065D BF0500 MOV DI,0005 INT 13 retry count
|
||||
|
||||
INT13RTRY: INT 13 RETRY LOOP
|
||||
|
||||
0000:0660 BB007C MOV BX,7C00
|
||||
0000:0663 B80102 MOV AX,0201 read 1 sector
|
||||
0000:0666 57 PUSH DI save DI
|
||||
0000:0667 CD13 INT 13 read sector into 0000:7c00
|
||||
0000:0669 5F POP DI restore DI
|
||||
0000:066A 730C JNB INT13OK jmp if no INT 13
|
||||
0000:066C 33C0 XOR AX,AX call INT 13 and
|
||||
0000:066E CD13 INT 13 do disk reset
|
||||
0000:0670 4F DEC DI decr DI
|
||||
0000:0671 75ED JNZ INT13RTRY if not zero, try again
|
||||
0000:0673 BEA306 MOV SI,06A3 display "Errr ldng systm"
|
||||
0000:0676 EBD3 JMP DISPLAY_MSG jmp to display loop
|
||||
|
||||
INT13OK: INT 13 ERROR
|
||||
|
||||
0000:0678 BEC206 MOV SI,06C2 "missing op sys"
|
||||
0000:067B BFFE7D MOV DI,7DFE point to signature
|
||||
0000:067E 813D55AA CMP WORD PTR [DI],AA55 is signature correct?
|
||||
0000:0682 75C7 JNZ DISPLAY_MSG no
|
||||
0000:0684 8BF5 MOV SI,BP set SI
|
||||
0000:0686 EA007C0000 JMP 0000:7C00 JUMP TO THE BOOT SECTOR
|
||||
WITH SI POINTING TO
|
||||
PART TABLE ENTRY
|
||||
|
||||
Messages here.
|
||||
|
||||
0000:0680 ........ ........ ......49 6e76616c * Inval*
|
||||
0000:0690 69642070 61727469 74696f6e 20746162 *id partition tab*
|
||||
0000:06a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading*
|
||||
0000:06b0 206f7065 72617469 6e672073 79737465 * operating syste*
|
||||
0000:06c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat*
|
||||
0000:06d0 696e6720 73797374 656d00.. ........ *ing system. *
|
||||
|
||||
Data not used.
|
||||
|
||||
0000:06d0 ........ ........ ......00 00000000 * .....*
|
||||
0000:06e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:06f0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0700 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0710 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0720 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0730 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0740 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0750 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0760 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0770 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0780 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0790 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07a0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07b0 00000000 00000000 00000000 0000.... *............ *
|
||||
|
||||
The partition table starts at 0000:07be. Each partition table
|
||||
entry is 16 bytes. This table defines a single primary partition
|
||||
which is also an active (bootable) partition.
|
||||
|
||||
0000:07b0 ........ ........ ........ ....8001 * ....*
|
||||
0000:07c0 0100060d fef83e00 00000678 0d000000 *......>....x....*
|
||||
0000:07d0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07f0 00000000 00000000 00000000 0000.... *............ *
|
||||
|
||||
The last two bytes contain a 55AAH signature.
|
||||
|
||||
0000:07f0 ........ ........ ........ ....55aa *..............U.*
|
||||
|
||||
/end/
|
||||
--
|
||||
\\===============\\=======================\\
|
||||
\\ Hale Landis \\ 303-548-0567 \\
|
||||
// Niwot, CO USA // landis@sugs.tware.com //
|
||||
//===============//=======================//
|
||||
|
||||
261
study/sabre/os/files/Booting/nasmBoot.txt
Normal file
@@ -0,0 +1,261 @@
|
||||
========================================
|
||||
Daniels NASM bootstraps tutorial
|
||||
========================================
|
||||
|
||||
author: Daniel Marjam<61>ki (daniel.marjamaki@home.se)
|
||||
|
||||
|
||||
|
||||
Preface
|
||||
-------
|
||||
This tutorial is a guide for those who want to create
|
||||
their own bootstraps.
|
||||
|
||||
|
||||
The basics
|
||||
----------
|
||||
These are the rules that you must follow:
|
||||
- The BIOS will load your bootstrap to address 07C00h.
|
||||
Sadly, the segment and offset varies.
|
||||
- Bootstraps must be compiled as plain binary files.
|
||||
- The filesize for the plain binary file must be 512
|
||||
bytes.
|
||||
- The file must end with AA55h.
|
||||
|
||||
|
||||
A minimal bootstrap
|
||||
-------------------
|
||||
This bootstrap just hangs:
|
||||
|
||||
; HANG.ASM
|
||||
; A minimal bootstrap
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0 ; Fill the file with 0's
|
||||
dw 0AA55h ; End the file with AA55
|
||||
|
||||
The line starting with "times" is a command that only
|
||||
NASM understands. The line will insert 0's until the
|
||||
filesize is 510 bytes. The whole file will therefore be
|
||||
512 bytes.
|
||||
The last instruction puts AA55 at the end of the file.
|
||||
|
||||
To compile the bootstrap, use this command:
|
||||
nasm hang.asm -o hang.bin
|
||||
|
||||
If you want to test the bootstrap, you must first put it
|
||||
on the first sector on a floppy disk. You can for example
|
||||
use 'dd' or 'rawrite'.
|
||||
When the bootstrap is on the floppy, test it by
|
||||
restarting your computer with the floppy inserted. The
|
||||
computer should hang then.
|
||||
|
||||
|
||||
The memory problem
|
||||
------------------
|
||||
There is a memory problem.
|
||||
As I've written bootstraps are always loaded to address
|
||||
07C00. We don't know what segment and offset the BIOS has
|
||||
put us in. The segment can be anything between 0000 and
|
||||
07C0. This is a problem when we want to use variables.
|
||||
The solution is simple. Begin your bootstrap by jumping
|
||||
to your bootstrap, but jump to a known segment.
|
||||
|
||||
Here is an example:
|
||||
|
||||
; JUMP.ASM
|
||||
; Make a jump and then hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
If you compile and test this bootstrap, there will be no
|
||||
visible difference to the minimal bootstrap presented
|
||||
earlier. The computer will just hang.
|
||||
|
||||
|
||||
Some exercises
|
||||
--------------
|
||||
1. Create a bootstrap that outputs "====" on the screen,
|
||||
and then hangs. Tip: modify the jump.asm program.
|
||||
2. Create a bootstrap that outputs "Hello Cyberspace!"
|
||||
and hangs.
|
||||
3. Create a bootstrap that loads a program off the floppy
|
||||
disk and jumps to it.
|
||||
|
||||
|
||||
Solutions to the exercises
|
||||
--------------------------
|
||||
|
||||
1.
|
||||
|
||||
; 1.ASM
|
||||
; Print "====" on the screen and hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
mov ah, 9 ; Print "===="
|
||||
mov al, '=' ;
|
||||
mov bx, 7 ;
|
||||
mov cx, 4 ;
|
||||
int 10h ;
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
2.
|
||||
|
||||
; 2.ASM
|
||||
; Print "Hello Cyberspace!" on the screen and hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
; Declare the string that will be printed
|
||||
msg db 'Hello Cyberspace!'
|
||||
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
|
||||
mov si, msg ; Print msg
|
||||
print:
|
||||
lodsb ; AL=memory contents at DS:SI
|
||||
|
||||
cmp al, 0 ; If AL=0 then hang
|
||||
je hang
|
||||
|
||||
mov ah, 0Eh ; Print AL
|
||||
mov bx, 7
|
||||
int 10h
|
||||
|
||||
jmp print ; Print next character
|
||||
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
3.
|
||||
|
||||
; 3.ASM
|
||||
; Load a program off the disk and jump to it
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
|
||||
reset: ; Reset the floppy drive
|
||||
mov ax, 0 ;
|
||||
mov dl, 0 ; Drive=0 (=A)
|
||||
int 13h ;
|
||||
jc reset ; ERROR => reset again
|
||||
|
||||
|
||||
read:
|
||||
mov ax, 1000h ; ES:BX = 1000:0000
|
||||
mov es, ax ;
|
||||
mov bx, 0 ;
|
||||
|
||||
mov ah, 2 ; Load disk data to ES:BX
|
||||
mov al, 5 ; Load 5 sectors
|
||||
mov ch, 0 ; Cylinder=0
|
||||
mov cl, 2 ; Sector=2
|
||||
mov dh, 0 ; Head=0
|
||||
mov dl, 0 ; Drive=0
|
||||
int 13h ; Read!
|
||||
|
||||
jc read ; ERROR => Try again
|
||||
|
||||
|
||||
jmp 1000h:0000 ; Jump to the program
|
||||
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
|
||||
This is a small loadable program.
|
||||
|
||||
; PROG.ASM
|
||||
|
||||
mov ah, 9
|
||||
mov al, '='
|
||||
mov bx, 7
|
||||
mov cx, 10
|
||||
int 10h
|
||||
|
||||
hang:
|
||||
jmp hang
|
||||
|
||||
|
||||
This program creates a disk image file that contains both
|
||||
the bootstrap and the small loadable program.
|
||||
|
||||
; IMAGE.ASM
|
||||
; Disk image
|
||||
|
||||
%include '3.asm'
|
||||
%include 'prog.asm'
|
||||
|
||||
|
||||
|
||||
|
||||
Finally
|
||||
-------
|
||||
Thanks for reading.
|
||||
Email me any suggestions, comments, questions, ...
|
||||
If you don't use NASM and are having problems with the
|
||||
code, you should contact me. Together we can solve it.
|
||||
894
study/sabre/os/files/Booting/win95.asm
Normal file
@@ -0,0 +1,894 @@
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; Description: Heroic attempt to disassemble the Windows 95 Boot Sector.
|
||||
; Date: 16. Aug. 1998
|
||||
; Author: Mr. X
|
||||
; Email: unknown
|
||||
; Comment: This boot code is messy.
|
||||
; Status: PART I, II and III are now pretty much done.
|
||||
; Important: "SHLD EDX,EAX,16" This is a Microsoft Patent.
|
||||
; Also take a look at the "list near EOF"
|
||||
;
|
||||
; ---> CUT HERE IF YOU LIKE TO LISTEN TO ME <---
|
||||
;
|
||||
; This file will assemble into a fully functional (I hope) Win95B boot code.
|
||||
;
|
||||
; tasm win95 /m
|
||||
; tlink win95,win95.bin /t
|
||||
;
|
||||
; Ask someone for the proper dropper code...
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; AFTER DISASSEMBLY I have this impression:
|
||||
;
|
||||
; This is what Bill Gates said... when Win95 was going to be released:
|
||||
;
|
||||
; "Gates: OK, then we're ready to press the CD's and start shipping out
|
||||
; this new load of shit, but of course nobody will notice... harr harr.
|
||||
; Employee: Hey, Mr. Gates what about the Boot Sector?? We haven't
|
||||
; written the FAT32 support routines there yet...
|
||||
; Gates: Ah, that's right... anybody?? We have just 45 minutes...
|
||||
; Employee #2: Well, I think I can hack some shit together...
|
||||
; Gates: Fine, go for it... remember you have only 44 minutes...
|
||||
; Employee #2: I think I can do it.
|
||||
; Gates: Fine, then I'll just go home... We've made it!!"
|
||||
;
|
||||
; FUNNY?
|
||||
;
|
||||
; There is some really strange code in this boot record....
|
||||
;
|
||||
; I bet Bill Gates hired some crazy mother fucker to write this shit.
|
||||
; It seems like he had really tried to make the code fit within one sector.
|
||||
; But when it didn't hid just decided to use three instead...
|
||||
;
|
||||
; This is a typical microsoft solution, they mix stupid 8086 code... with
|
||||
; cheap solutions and then suddenly they use 386 code...
|
||||
;
|
||||
; And then there is the new FAT32 data structures where they have moved
|
||||
; the volume label, FileSystem ID and serial number down to make room for
|
||||
; some extended FAT32 variables... it sucks. Why not rearange the whole
|
||||
; structure... An OS would not try to interpret the shit anyway, because
|
||||
; the Partitioni Table SYSID has changed with FAT32.
|
||||
;
|
||||
; As I said... crazy mother fucker...
|
||||
;
|
||||
; Well, well... here's some of the stuff... with a mix of mine and sourcer's
|
||||
; comments...
|
||||
;
|
||||
; Another thing about TASM, which I use, of course I didn't buy it... I'm
|
||||
; have a shareware version ;) on a 30 year trial period.
|
||||
;
|
||||
; Back to what I was about to say again... When I use the brXXXX variables
|
||||
; in indexing with BP, TASM generates 16-bit offset in operands even when
|
||||
; they are less than 128... the Win95 code uses byte offsets (I'm not sure
|
||||
; if I'm expressing myself clear here). When I changed the code from:
|
||||
;
|
||||
; mov AX,[bp+brHPC] to mov AX,[bp+128], TASM did use the byte offset form...
|
||||
; This made my code a little less readable... but the comments should give
|
||||
; you an idea of what data is being accessed.
|
||||
;
|
||||
; Basically this boot sector code is 32 bit extension for a 16 bit patch to
|
||||
; an 8 bit boot sector originally coded for a 4 bit microprocessor, written
|
||||
; by a 2 bit company, that can't stand 1 bit of competition.
|
||||
;
|
||||
; ---> CUT HERE IF YOU DOES NOT LIKE TO LISTEN TO ME <---
|
||||
|
||||
.386C
|
||||
|
||||
CODE SEGMENT USE16
|
||||
|
||||
ASSUME CS:CODE, DS:CODE, SS:NOTHING
|
||||
|
||||
; BOOT RECORD - PART I - MAIN BOOT SECTOR CODE
|
||||
|
||||
; Just so I've said it - ASM opcodes are only readable when capitalized,
|
||||
; but I forgot to set the option in sourcer... so I wrote a small TP program
|
||||
; that capitalized everything but what's after the semicolon...
|
||||
|
||||
Win95b PROC FAR
|
||||
|
||||
JMP SkipData ; 0000h
|
||||
|
||||
brINT13Flag DB 90H ; 0002h - 0EH for INT13 AH=42 READ
|
||||
brOEM DB 'MSWIN4.1' ; 0003h - OEM ID - Windows 95B
|
||||
brBPS DW 512 ; 000Bh - Bytes per sector
|
||||
brSPC DB 8 ; 000Dh - Sector per cluster
|
||||
brResCount DW 32 ; 000Eh - Reserved sectors
|
||||
brFATs DB 2 ; 0010h - FAT copies
|
||||
brRootEntries DW 0 ; 0011h - Root directory entries
|
||||
brSectorCount DW 0 ; 0013h - Sectors in volume, < 32MB
|
||||
brMedia DB 0F8H ; 0015h - Media descriptor
|
||||
brSPF DW 0 ; 0016h - Sectors per FAT
|
||||
brSPH DW 63 ; 0018h - Sectors per head/track
|
||||
brHPC DW 128 ; 001Ah - Heads per cylinder
|
||||
brHidden DD 63 ; 001Ch - Hidden sectors
|
||||
brSectors DD 6305985 ; 0020h - Total number of sectors
|
||||
brSPF32 DD 6153 ; 0024h - Sector per FAT (FAT32)
|
||||
brFlags DW 0 ; 0028h - Flags (FAT32)
|
||||
brVersion DW 0 ; 002Ah - FS Version (FAT32)
|
||||
brRootCluster DD 2 ; 002Ch - Root start cluster (FAT32)
|
||||
brFSInfoSector DW 1 ; 0030h - FS Info Sector (FAT32)
|
||||
brBackupBoot DW 6 ; 0032h - Backup Boot Record
|
||||
brReserved DB 6 DUP (0) ; 0038h - Reserved
|
||||
brShitter DB 6 DUP (0) ; 003Bh - Unused filler??
|
||||
brDrive DB 80H ; 0040h - BIOS drive number
|
||||
brHeadTemp DB 00H ; 0041h - Head/temp number????
|
||||
brSignature DB 29H ; 0042h - Extended Boot Record sig.
|
||||
brSerialNum DD 404418EAH ; 0043h - Volume serial number
|
||||
brLabel DB 'HARDDISK ' ; 0047h - Volume label
|
||||
brFSID DB 'FAT32 ' ; 0052h - File System ID
|
||||
|
||||
SkipData:
|
||||
CLI
|
||||
XOR CX,CX
|
||||
MOV SS,CX ; SS=CX=0
|
||||
|
||||
; Set up stack 8 bytes below us, do you know why???
|
||||
; Yes, it's because somewhere in this code, the shitter who
|
||||
; wrote this... save the start of data area DWORD at 7C00H - 4 and
|
||||
; the value -1 at 7C00H - 8... cool?
|
||||
|
||||
MOV SP,7C00H - 8
|
||||
MOV ES,CX ; ES=CX=0
|
||||
MOV BP,78H
|
||||
|
||||
; Point DS:SI to INT 1E - DISKETTE PARAMS structure...
|
||||
|
||||
LDS SI,DWORD PTR SS:[BP]
|
||||
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
PUSH SS
|
||||
PUSH BP
|
||||
|
||||
MOV DI,522H
|
||||
|
||||
MOV SS:[BP],DI ; setup our INT 1E
|
||||
MOV SS:[BP+2],CX
|
||||
|
||||
; copy 11 bytes from old diskette parameter table into
|
||||
; es:522h, that is 0000:0522 or 0050:0022 - into the PrtScr/DOS area.
|
||||
; I assume that 0001-0021 is used for something else 0050:0000 I know
|
||||
; is the PrtScr flag byte.
|
||||
|
||||
MOV CL,11
|
||||
CLD
|
||||
REP MOVSB
|
||||
|
||||
MOV DS,CX ; DS=CX=0
|
||||
|
||||
MOV BP,7C00H ; point BP to start of us
|
||||
|
||||
MOV BYTE PTR [DI-2],0FH ; modify head settle time
|
||||
|
||||
MOV AX,SS:[BP+18H]
|
||||
|
||||
MOV [DI-7],AL ; modify sectors per track
|
||||
|
||||
; compare drive number with 0...
|
||||
; if greater than or equal... go to MBRReadError
|
||||
; I guess that lower than zero... must be -1 .. -128 (80H..FFH)
|
||||
; Which would mean Harddisk boot...
|
||||
|
||||
CMP SS:[BP+40H],CL ; Boot from diskette?
|
||||
JGE MBRReadError
|
||||
|
||||
MOV AX,CX ; AX=CX=0
|
||||
CWD ; DX=AX[15]-> (ZerO)
|
||||
|
||||
MOV BX,0700H ; Use 0000:0700 for sector
|
||||
; read buffer
|
||||
|
||||
CALL ReadSector ; load Master Boot Record
|
||||
JC MBRReadError ; error?
|
||||
|
||||
SUB BX,58 ; BX = 08C6h (700h - 3Ah)
|
||||
; point to "start" field
|
||||
|
||||
MOV EAX,DS:[7C1CH] ; load hidden sectors
|
||||
CheckMBR:
|
||||
CMP EAX,[BX] ; Is this our entry??
|
||||
|
||||
MOV DL,[BX-4] ; Put System ID in DL
|
||||
|
||||
JNZ NotOurs ; Jump if not our entry
|
||||
|
||||
; If system ID or "partition type", is 0Ch or 0Eh, ReadSector
|
||||
; will use INT13/42H...
|
||||
|
||||
OR DL,2 ; set bit 1, to allow for
|
||||
; types 0Ch or 0Eh to be
|
||||
; thought of as both 0Eh.
|
||||
|
||||
MOV SS:[BP+2],DL ; set brINT13Flag
|
||||
NotOurs:
|
||||
ADD BL,16 ; skip to next entry...
|
||||
JNB CheckMBR ; More entries?
|
||||
MBRReadError:
|
||||
MOV DI,2
|
||||
|
||||
; FAT32 - Is sector per FAT zero?
|
||||
|
||||
CMP WORD PTR SS:[BP+16H],0
|
||||
JNE ShowErrMsg1
|
||||
|
||||
; Put number of hidden sectors in DX:AX
|
||||
|
||||
MOV AX,WORD PTR SS:[BP+1CH]
|
||||
MOV DX,WORD PTR SS:[BP+1EH]
|
||||
|
||||
MOV CX,3 ; Boot Record is 3 sectors...
|
||||
|
||||
; Start loading reminder of Boot Record for FAT32
|
||||
LoadIt:
|
||||
DEC CX
|
||||
INC AX ; next Boot Record sector
|
||||
|
||||
JNZ Skipper ; AX wrap-around?
|
||||
INC DX ; Yes, inc DX too
|
||||
Skipper:
|
||||
MOV BX,7E00H ; into 0000:7E00
|
||||
|
||||
CALL ReadSectorX ; Read Sector
|
||||
JNC ReadOK ; no error?
|
||||
|
||||
MOV AL,0F8H ; what's this????
|
||||
|
||||
DEC DI
|
||||
JZ NoMore ; Jump if no more sectors
|
||||
|
||||
MOV AX,SS:[BP+32H] ; get backup boot sector
|
||||
XOR DX,DX
|
||||
|
||||
MOV CX,3
|
||||
CMP CX,AX ; compare backup BS num
|
||||
JA ShowErrMsg1 ; with 3 (or vice versa)
|
||||
|
||||
; if 3 is higher than
|
||||
; backup sector number,
|
||||
; Bill's oooutta here...
|
||||
|
||||
MOV SI,SS:[BP+0EH] ; SI = # of reserved sectors
|
||||
CMP CX,SI
|
||||
JAE ShowErrMsg1 ; same thing here... if 3 is
|
||||
; higher then the number of
|
||||
; reserved sectors... Bill's
|
||||
; gone
|
||||
|
||||
SUB SI,CX ; get number reserved sectors
|
||||
; excluding the three boot
|
||||
; sectors...
|
||||
|
||||
; add number of hidden sectors to DX:AX
|
||||
|
||||
ADD AX,WORD PTR SS:[BP+1CH]
|
||||
ADC DX,WORD PTR SS:[BP+1EH]
|
||||
|
||||
JMP LoadIt
|
||||
NoMore:
|
||||
JNC ShowErrMsg1 ; Jump if carry=0
|
||||
JMP ShowErrMsg2
|
||||
ReadOK:
|
||||
CMP WORD PTR SS:[BP+2AH],0
|
||||
JA ShowErrMsg1 ; Jump if not version 0.0?
|
||||
|
||||
JMP GOFAT32
|
||||
ShowErrMsg1:
|
||||
MOV SI,OFFSET ErrMsg1 + 7C00H
|
||||
PrintMessage:
|
||||
LODSB ; get msg Skip length
|
||||
|
||||
CBW
|
||||
ADD SI,AX ; Skip control data
|
||||
NextChar:
|
||||
LODSB ; get chacacter
|
||||
|
||||
TEST AL,AL
|
||||
JZ LastChar ; End of string?
|
||||
|
||||
CMP AL,-1
|
||||
JE SkipChar ; End of first part?
|
||||
|
||||
MOV AH,0EH ; TTY write character
|
||||
MOV BX,7
|
||||
INT 10H
|
||||
|
||||
JMP NextChar ; repeat write...
|
||||
SkipChar:
|
||||
MOV SI,OFFSET ErrMsg4 + 7C00H ; point to tail message
|
||||
JMP PrintMessage
|
||||
ShowErrMsg2:
|
||||
MOV SI,OFFSET ErrMsg2 + 7C00H
|
||||
JMP PrintMessage
|
||||
LastChar:
|
||||
CBW ; Ah, clever... save one byte, take
|
||||
; advantage of the fact that LODSB
|
||||
INT 16H ; returns the null-terminator.
|
||||
|
||||
POP SI ; restore the stack... why???
|
||||
POP DS ; the stack is killed at startup...
|
||||
POP DWORD PTR [SI]
|
||||
|
||||
INT 19H ; BIOS bootstrap loader...
|
||||
|
||||
Win95b ENDP
|
||||
|
||||
;==========================================================================
|
||||
; READ SECTOR
|
||||
;==========================================================================
|
||||
|
||||
ReadSector PROC NEAR
|
||||
|
||||
INC CX ; increase SECTOR COUNT
|
||||
ReadSectorX:
|
||||
|
||||
rsReadMore:
|
||||
PUSH SI
|
||||
PUSH DWORD PTR 0
|
||||
PUSH DX
|
||||
PUSH AX
|
||||
PUSH ES
|
||||
PUSH BX
|
||||
PUSH 1
|
||||
PUSH 10H
|
||||
|
||||
MOV SI,SP ; save stack pointer
|
||||
; for later use by LEA
|
||||
|
||||
PUSHA ; Save "all" registers
|
||||
|
||||
CMP BYTE PTR SS:[BP+2],0EH ; Use INT13 extensions?
|
||||
JNE rsOldINT13
|
||||
|
||||
MOV AH,42H ; Do ext INT13 READ
|
||||
JMP RSDiskIO
|
||||
rsOldINT13:
|
||||
XCHG CX,AX ; swap CX and AX
|
||||
XCHG DX,AX ; swap DX and AX
|
||||
XOR DX,DX ; clear DX
|
||||
|
||||
DIV WORD PTR SS:[BP+18H] ; div LBA_HI by sectors/track
|
||||
|
||||
XCHG CX,AX ; save result in CX and put
|
||||
; the LBA_LO in AX
|
||||
|
||||
DIV WORD PTR SS:[BP+18H] ; divide reminder and LBA_LO
|
||||
; by sectors/track too
|
||||
|
||||
INC DX ; make sector 1-based
|
||||
|
||||
XCHG CX,DX ; save it in CX and get the
|
||||
; result of the 1st division
|
||||
; in DX
|
||||
|
||||
DIV WORD PTR SS:[BP+1AH] ; divide this new result by
|
||||
; heads per cylinder
|
||||
|
||||
MOV DH,DL ; save Head of CHS in DH
|
||||
; head was in the reminder
|
||||
; after the division above
|
||||
|
||||
MOV CH,AL ; save LO cylinder in CH
|
||||
; cylinder was in the result
|
||||
; after the division above
|
||||
|
||||
ROR AH,2 ; rotate AH to make bits 8-9
|
||||
; of cylinder appear as bits
|
||||
; 6-7 in AH and...
|
||||
OR CL,AH ; or it with the sector num
|
||||
|
||||
MOV AX,201H ; setup for READ - 1 sector
|
||||
rsDiskIO:
|
||||
MOV DL,SS:[BP+40H] ; load drive number
|
||||
INT 13H ; call INT13
|
||||
|
||||
POPA ; Restore "all" registers
|
||||
|
||||
; the entry code pushed 12h bytes on the stack...
|
||||
; the last word pushed was 0001h, restore SP to point to it...
|
||||
|
||||
LEA SP,[SI+10H] ; Load effective addr
|
||||
|
||||
; Now, SI should contain 0001h
|
||||
|
||||
POP SI
|
||||
|
||||
; was there an error from INT13?
|
||||
|
||||
JC RSDone
|
||||
|
||||
INC AX ; increment LBA sector num
|
||||
JNZ rsSkip ; wrap-around?
|
||||
|
||||
INC DX ; yes raise high word too
|
||||
rsSkip:
|
||||
ADD BX,SS:[BP+0BH] ; increment by sector size
|
||||
|
||||
DEC CX ; decrement SECTOR COUNT
|
||||
JNZ rsReadMore ; Jump if more to read
|
||||
rsDone:
|
||||
RET
|
||||
|
||||
ReadSector ENDP
|
||||
|
||||
;============================================================================
|
||||
; DATA AREA FOR MESSAGES - IN "NORSK" NORWEGIAN
|
||||
;============================================================================
|
||||
|
||||
ErrMsg1 DB 03H ; Skip counter for message1
|
||||
ErrMsg2 DB 18H ; Skip counter for message2
|
||||
ErrMsg3 DB 01H ; Skip counter for message3
|
||||
ErrMsg4 DB 27H ; Skip counter for message4
|
||||
|
||||
DB 13,10,'Ugyldig systemdisk ',-1
|
||||
DB 13,10,'Disk I/U-feil ',-1
|
||||
DB 13,10,'Sett inn en annen disk, og trykk en tast',13,10,0
|
||||
|
||||
;============================================================================
|
||||
|
||||
DB 0,0 ; Padding?
|
||||
|
||||
; ROOT file names to search for...?
|
||||
|
||||
IO_SYS DB 'IO SYS'
|
||||
MSDOS_SYS DB 'MSDOS SYS'
|
||||
|
||||
DB 7EH,1,0 ; What is this?
|
||||
|
||||
WINBOOT_SYS DB 'WINBOOT SYS' ; When is this used?
|
||||
|
||||
DB 0,0 ; Padding?
|
||||
DW 0AA55H ; 1st Boot Signature
|
||||
|
||||
;
|
||||
; BOOT RECORD - PART II - FSINFO sector
|
||||
;
|
||||
DB 'RRaA' ; FAT32 Extension Signature
|
||||
|
||||
DB 480 DUP (0)
|
||||
|
||||
; FSINFO information...
|
||||
|
||||
DB 'rrAa' ; FAT32 FSINFO Signature
|
||||
|
||||
brFreeClusters DD 56990 ; I have 233431040 bytes free!
|
||||
brNextFree DD 466175 ; My next free cluster!
|
||||
DD 3 DUP (0) ; Reserved, acroding to FAT32API.HLP
|
||||
|
||||
DW ? ; word padding
|
||||
|
||||
DW 0AA55H ; 2nd Boot Signature
|
||||
;
|
||||
; BOOT RECORD - PART III - FAT32 specific code, I think? only Bill knows?
|
||||
;
|
||||
GOFAT32:
|
||||
CLI
|
||||
|
||||
; calculate total size of FAT area
|
||||
|
||||
MOVZX EAX,BYTE PTR SS:[BP+10H] ; number of FATs
|
||||
MOV ECX,SS:[BP+24H] ; sectors per FAT
|
||||
MUL ECX ; mul'em
|
||||
|
||||
; add hidden sectors
|
||||
|
||||
ADD EAX,SS:[BP+1CH]
|
||||
|
||||
; add reserved sectors
|
||||
|
||||
MOVZX EDX,WORD PTR SS:[BP+0EH]
|
||||
ADD EAX,EDX
|
||||
|
||||
XOR CX,CX ; clear CX for some reason...
|
||||
; By looking down the code, I can't
|
||||
; seem to find out why CX is cleared
|
||||
; It's set to 1 down there...
|
||||
; before it's ever used...
|
||||
|
||||
; EAX will now point to the start of the data area (cluster 2)
|
||||
; save start of data area below us at 0000:7BFC, or there around...
|
||||
|
||||
MOV SS:[BP-4],EAX
|
||||
|
||||
; Save another value to... This one is checked by GetFAT32Sector
|
||||
|
||||
MOV DWORD PTR SS:[BP-8],0FFFFFFFFH
|
||||
|
||||
; Oh... at Microsoft they take no chances... disable INTs again!
|
||||
; This is what I call proper software writing! Hail M$
|
||||
|
||||
CLI
|
||||
|
||||
; load Root Start Cluster in EAX
|
||||
|
||||
MOV EAX,SS:[BP+2CH]
|
||||
|
||||
; Is it cluster 2?
|
||||
|
||||
CMP EAX,2
|
||||
JB ShowErrMsg1 ; error if less than 2
|
||||
|
||||
; Is it an EOF marker or something above?
|
||||
|
||||
CMP EAX,0FFFFFF8H
|
||||
JAE ShowErrMsg1 ; error if it is
|
||||
|
||||
; Put upper 16-bits of cluster number into DX??
|
||||
|
||||
SHLD EDX,EAX,16
|
||||
|
||||
STI ; Puh. Safe again.
|
||||
GetRootCluster:
|
||||
PUSH DX
|
||||
PUSH AX
|
||||
|
||||
CLI ; Eh?
|
||||
|
||||
; clear upper 16-bits of cluster number, and of course move up the
|
||||
; lower bits...
|
||||
|
||||
SHL EAX,16
|
||||
|
||||
; shift lower 16-bits of cluster number back down, and at the same
|
||||
; time shift in the high 16-bits in top of EAX?
|
||||
|
||||
SHRD EAX,EDX,16
|
||||
|
||||
; make cluster number 0-based... "the way it's supposed to be"
|
||||
|
||||
SUB EAX,2
|
||||
|
||||
; put Sectors Per Cluster in EBX
|
||||
|
||||
MOVZX EBX,BYTE PTR SS:[BP+0DH]
|
||||
|
||||
; save it in SI too! Yippi
|
||||
|
||||
MOV SI,BX
|
||||
|
||||
; calculate relative sector of first part of root... right?
|
||||
|
||||
MUL EBX
|
||||
|
||||
; add the "start of data area" value we saved below us!
|
||||
|
||||
ADD EAX,SS:[BP-4]
|
||||
|
||||
; Maybe now, some shitter is trying to make DX:AX what EAX is??
|
||||
; Shift upper 16-bits of EAX into DX... and AX is lower bits...
|
||||
|
||||
SHLD EDX,EAX,10H
|
||||
|
||||
STI ; Enable interrupts
|
||||
GetRootSector:
|
||||
|
||||
; Use 0070:0000 as a directory buffer...
|
||||
|
||||
MOV BX,0700H
|
||||
MOV DI,BX
|
||||
|
||||
; read 1 sector
|
||||
|
||||
MOV CX,1
|
||||
|
||||
CALL ReadSectorX ; this shit should be pretty
|
||||
JC ShowErrMsg2 ; obvious...
|
||||
CheckEntry:
|
||||
CMP [DI],CH ; is the first entry of the
|
||||
JE EndOfRoot ; root empty???
|
||||
|
||||
MOV CL,11 ; the stupid CP/M filenames
|
||||
; are 11 bytes...
|
||||
PUSH SI
|
||||
|
||||
MOV SI,OFFSET IO_SYS + 7C00H
|
||||
|
||||
REPE CMPSB ; Is it IO.SYS?
|
||||
|
||||
POP SI
|
||||
|
||||
JZ FoundOS ; Yeah...
|
||||
|
||||
ADD DI,CX ; add what's left after CMPSB
|
||||
ADD DI,15H ; and then 21 more...
|
||||
|
||||
; Yeah, yeah, anyway... point to the next dir entry...
|
||||
; and check if it is above the last entry... INT13 increments
|
||||
; BX with 512 on the sector read, so it points past the sector.
|
||||
|
||||
CMP DI,BX
|
||||
JB CheckEntry ; Jump if below
|
||||
|
||||
; are there any more sectors in this cluster???
|
||||
|
||||
DEC SI
|
||||
JNZ GetRootSector ; yeap, read more
|
||||
|
||||
POP AX ; restore cluster number
|
||||
POP DX
|
||||
|
||||
; Get FAT value... "GetFAT32Value" will compare the value with
|
||||
; -8, and the JB below continues if below... that is, non-EOF/BAD
|
||||
; the "previous cluster" value is taken from DX:AX (as restored
|
||||
; above with POP).
|
||||
|
||||
CALL GetFAT32Value
|
||||
JB GetRootCluster
|
||||
|
||||
; if not end of root... go to GetRootCluster..
|
||||
|
||||
EndOfRoot: ; EOF/BAD cluster...
|
||||
ADD SP,4 ; clean up stack...
|
||||
JMP ShowErrMsg1 ; and print error message
|
||||
FoundOS:
|
||||
ADD SP,4 ; clean up...
|
||||
|
||||
|
||||
; Now... DI should point just above the IO.SYS name...
|
||||
|
||||
; SI would be set to DirEntry[14H] - starting cluster (HI)
|
||||
; DI would be set to DirEntry[1AH] - starting cluster (LO)
|
||||
|
||||
MOV SI,[DI+09H]
|
||||
MOV DI,[DI+0FH]
|
||||
|
||||
; copy FAT32 starting cluster upper 16-bits to AX
|
||||
|
||||
MOV AX,SI
|
||||
|
||||
CLI ; Disable interrupts
|
||||
|
||||
; shift cluster high into upper half of EAX and store lower half
|
||||
; from DI into AX
|
||||
|
||||
SHL EAX,10H
|
||||
MOV AX,DI
|
||||
|
||||
; cluster out of range??
|
||||
|
||||
CMP EAX,2 ; clusters start with 2
|
||||
JB InvalidCluster
|
||||
|
||||
CMP EAX,0FFFFFF8H ; cluster 0FFFFFF8 is EOF
|
||||
JAE InvalidCluster
|
||||
|
||||
DEC EAX ; make it 0-based...
|
||||
DEC EAX
|
||||
|
||||
; Multiply cluster number with "sectors per cluster"
|
||||
|
||||
MOVZX ECX,BYTE PTR SS:[BP+0DH]
|
||||
MUL ECX
|
||||
|
||||
; Add the "start of data area" value that was saved back there...
|
||||
|
||||
ADD EAX,SS:[BP-4]
|
||||
|
||||
; And for the N'th time, make DX:AX same as EAX - sector number.
|
||||
|
||||
SHLD EDX,EAX,10H
|
||||
|
||||
STI ; aha...
|
||||
|
||||
MOV BX,0700H ; IO.SYS loads here!
|
||||
|
||||
PUSH BX
|
||||
MOV CX,4 ; load 4 IO.SYS sectors
|
||||
CALL ReadSectorX ; 2K is minimum FAT32 cluster
|
||||
POP BX ; size anyway...
|
||||
|
||||
JC ShowErrMsg2 ; error...???
|
||||
|
||||
|
||||
; COMMENT:
|
||||
;
|
||||
; Now, there is enough code here... to read the entire IO.SYS
|
||||
; file into memory. This code has code to go through the FAT,
|
||||
; there is code to read cluster... bla bla. And still only 2K
|
||||
; of IO.SYS is read. If the entire file was read... IO.SYS would
|
||||
; not have to do this... well well.
|
||||
|
||||
; Is there a Mark Zibikowski in the room?
|
||||
|
||||
CMP WORD PTR [BX],'ZM' ; EXE signature...
|
||||
JNE InvalidCluster
|
||||
|
||||
; Is there a Barabara Jones in the room?
|
||||
|
||||
CMP WORD PTR DS:[0200H][BX],'JB' ; IO.SYS signature?
|
||||
JE ExecutIOSYS
|
||||
|
||||
; The above shit appear in the IO.SYS file at offsets 0 and 200h
|
||||
; The MZ is the usual EXE signature while the "BJ" is unknown to
|
||||
; me. Maybe they chose it because it translates to harmless code:
|
||||
;
|
||||
; INC DX - DEC DX, pretty dull if you ask me ;)
|
||||
;
|
||||
InvalidCluster:
|
||||
MOV SI,OFFSET ErrMsg3 + 7C00H
|
||||
JMP PrintMessage
|
||||
ExecutIOSYS:
|
||||
DB 0EAH ; Jump to IO.SYS at 0070:0200
|
||||
DW 0200H, 0070H
|
||||
|
||||
;==========================================================================
|
||||
; GET FAT32 VALUE
|
||||
;==========================================================================
|
||||
|
||||
GetFAT32Value PROC NEAR
|
||||
|
||||
ADD AX,AX ; Multiply DX:AX by 4,
|
||||
ADC DX,DX
|
||||
ADD AX,AX ; convert DX:AX from FAT32
|
||||
ADC DX,DX ; index value to offset
|
||||
|
||||
; DX:AX is passed on as the FAT offset to lookup...
|
||||
|
||||
CALL GetFAT32Sector ; read FAT sector
|
||||
|
||||
; the correct sector is returned... with DI as index...??
|
||||
; At least that's what the MOV below assumes...
|
||||
|
||||
CLI
|
||||
|
||||
MOV EAX,ES:[BX+DI] ; EAX = cluster value
|
||||
|
||||
; mask of top 4 bits of because Microsoft say it's reserved.
|
||||
|
||||
AND EAX,0FFFFFFFH
|
||||
|
||||
; Make DX:AX the cluster number too...
|
||||
|
||||
SHLD EDX,EAX,16 ; EAX[HI] into EDX[LO]
|
||||
|
||||
; Check for EOF/BAD
|
||||
|
||||
CMP EAX,0FFFFFF8H ; Is it the EOF marker?
|
||||
|
||||
STI ; return with ZF=1 if the
|
||||
; last cluster was read??
|
||||
RET
|
||||
|
||||
GetFAT32Value ENDP
|
||||
|
||||
;==========================================================================
|
||||
; GET FAT32 SECTOR
|
||||
;==========================================================================
|
||||
|
||||
; On entry DX:AX is the FAT offset in bytes...
|
||||
|
||||
GetFAT32Sector PROC NEAR
|
||||
|
||||
; When this is called 0070:0200 seems to be the buffer in ES:BX
|
||||
; but, the code below uses the DI value set down under here...
|
||||
|
||||
MOV DI,7E00H
|
||||
|
||||
CLI ; Disable interrupts
|
||||
|
||||
; make EAX the sector number again... move DX into top of EAX...
|
||||
|
||||
SHL EAX,16
|
||||
SHRD EAX,EDX,16
|
||||
|
||||
; move bytes per sector into ECX
|
||||
|
||||
MOVZX ECX,WORD PTR SS:[BP+0BH]
|
||||
|
||||
; divide EDX:EAX by BPS... EAX = sector, EDX = offset in sector...
|
||||
|
||||
XOR EDX,EDX
|
||||
DIV ECX
|
||||
|
||||
; Check FAT sector number agains... saved value on stack...
|
||||
; This one is initially -1 (also known as 0FFFFFFFFH)
|
||||
|
||||
CMP EAX,SS:[BP-8]
|
||||
JE LOC_30
|
||||
|
||||
; If sector is <> from -1, save this sector at 0000:7BF8
|
||||
|
||||
MOV SS:[BP-8],EAX
|
||||
|
||||
; add hidden sectors...
|
||||
|
||||
ADD EAX,SS:[BP+1CH]
|
||||
|
||||
; add reserved sectors too...
|
||||
|
||||
MOVZX ECX,WORD PTR SS:[BP+0EH]
|
||||
ADD EAX,ECX
|
||||
|
||||
; get FAT32 flags into EBX
|
||||
|
||||
MOVZX EBX,WORD PTR SS:[BP+28H]
|
||||
|
||||
; keep "Active FAT" bits 0-3
|
||||
|
||||
AND BX,0FH
|
||||
|
||||
; If zero, we're at the correct FAT
|
||||
|
||||
JZ CorrectFAT
|
||||
|
||||
; compare active FAT with number of FATs...
|
||||
|
||||
CMP BL,SS:[BP+10H]
|
||||
JAE ShowErrMsg1 ; oops... invalid active FAT
|
||||
|
||||
PUSH DX ; save DX for a while...
|
||||
|
||||
; save FAT sector in ECX
|
||||
|
||||
MOV ECX,EAX
|
||||
|
||||
; Put sectors per fat in EAX
|
||||
|
||||
MOV EAX,SS:[BP+24H]
|
||||
|
||||
; Multiply active FAT number with sectors per FAT
|
||||
|
||||
MUL EBX
|
||||
|
||||
; Add to first FAT sector number we already had...
|
||||
|
||||
ADD EAX,ECX
|
||||
|
||||
; NOW, EAX contains the correct FAT sector number.
|
||||
|
||||
POP DX
|
||||
CorrectFAT:
|
||||
PUSH DX
|
||||
|
||||
; And for the N'th time, make DX:AX same as EAX - sector number.
|
||||
|
||||
SHLD EDX,EAX,16
|
||||
|
||||
STI ; Enable interrupts
|
||||
|
||||
MOV BX,DI ; read FAT sector into
|
||||
; 0000:7E00
|
||||
|
||||
; They sucker who wrote this could have saved 1 byte by
|
||||
; saying XOR CX,CX instead of MOV CX,1 and called ReadSector
|
||||
; instead of ReadSectorX, because there is an INC CX at
|
||||
; ReadSector... haha...
|
||||
|
||||
MOV CX,1 ; 1 sector
|
||||
CALL ReadSectorX
|
||||
|
||||
POP DX
|
||||
|
||||
JC ShowErrMsg2
|
||||
LOC_30:
|
||||
STI ; Enable interrupts
|
||||
MOV BX,DX
|
||||
RET
|
||||
|
||||
GetFAT32Sector ENDP
|
||||
|
||||
; Properly align the sector's boot signature at the end of
|
||||
; the 3rd boot sect0r.
|
||||
|
||||
ORG 512 * 3 - 2
|
||||
|
||||
DW 0AA55H ; 3rd Boot Signature
|
||||
|
||||
CODE ENDS
|
||||
|
||||
END
|
||||
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; CONCLUSION - THE END - HASTA LA VISTA - SLUTT - DET VAR ALT FOR I DAG.
|
||||
;
|
||||
; OK, Folks. that was quite a bit of work. It got pretty simple after some
|
||||
; hours.
|
||||
;
|
||||
; I would like to thank the following people...
|
||||
;
|
||||
; * V Communications for Sourcer.
|
||||
; * Ralf Brown for the Interrupt List.
|
||||
; * Uriah Heep, The Who and Blind Guardian, for providing music.
|
||||
;
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
1000
study/sabre/os/files/Booting/x86Bootstrapping.html
Normal file
1579
study/sabre/os/files/Buses/ATA-2FAQ.txt
Normal file
BIN
study/sabre/os/files/Buses/ATA-2Specs.doc
Normal file
BIN
study/sabre/os/files/Buses/FC_AL_SPECS_130.pdf
Normal file
BIN
study/sabre/os/files/Buses/Plug&PlaySCSI.zip
Normal file
BIN
study/sabre/os/files/Buses/SCSI2Specs.zip
Normal file
BIN
study/sabre/os/files/Buses/Serial ATA 1.0 gold.pdf
Normal file
BIN
study/sabre/os/files/Buses/USB1.0Specs.zip
Normal file
BIN
study/sabre/os/files/Buses/ata3-r6.zip
Normal file
7
study/sabre/os/files/Buses/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
BIN
study/sabre/os/files/Communication/CP_Parallel.pdf
Normal file
BIN
study/sabre/os/files/Communication/CP_Parallel_ecp.pdf
Normal file
BIN
study/sabre/os/files/Communication/CP_Parallel_epp.pdf
Normal file
BIN
study/sabre/os/files/Communication/CP_serial.pdf
Normal file
7
study/sabre/os/files/Communication/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
403
study/sabre/os/files/Communication/parallel.txt
Normal file
@@ -0,0 +1,403 @@
|
||||
PC Parallel Port Mini-FAQ
|
||||
|
||||
By Kris Heidenstrom (kheidens@actrix.gen.nz), revision 7, 19960430
|
||||
|
||||
In no event shall the author be liable for any damages whatsoever
|
||||
for any loss relating to this document. Use it at your own risk!
|
||||
|
||||
1. INTRO
|
||||
|
||||
This is a six printed page mini-FAQ with basic information on the
|
||||
PC parallel port. Many subjects are not covered in detail. View
|
||||
on an 80-column monospaced screen with 8-column tab stops.
|
||||
Comments, corrections, suggestions to kheidens@actrix.gen.nz.
|
||||
|
||||
A parallel port links software to the real world. To software, the
|
||||
parallel port is three 8-bit registers occupying three consecutive
|
||||
addresses in the I/O space. To hardware, the port is a female 25-pin
|
||||
D-sub connector, carrying twelve latched outputs from the computer,
|
||||
accepting five inputs into the computer, with eight ground lines.
|
||||
|
||||
The normal function of the port is to transfer data to a parallel
|
||||
printer through the eight data pins, using the remaining signals as
|
||||
flow control and miscellaneous controls and indications.
|
||||
|
||||
The original port was implemented with TTL/LS logic. Modern ports
|
||||
are implemented in an ASIC or a combined serial/parallel port chip,
|
||||
but are backward compatible. Many modern ports are bidirectional
|
||||
and may have extended functionality (see section >> 5). The body
|
||||
of this document applies to standard and PS/2 ports only.
|
||||
|
||||
2. BIOS LPT PORT TABLE
|
||||
|
||||
A parallel port is identifed by its I/O base address, and also by its
|
||||
LPT port number. The BIOS power-on self-test checks specific I/O
|
||||
addresses for the presence of a parallel port, and builds a table of
|
||||
I/O addresses in the low memory BIOS data area, starting at address
|
||||
0040:0008 (or 0000:0408).
|
||||
|
||||
This table contains up to three 16-bit words (four on some BIOSes).
|
||||
Each entry gives the I/O base address of a parallel port. The first
|
||||
word is the I/O base address of LPT1, the second is LPT2, etc.
|
||||
If less than three ports were found, the remaining entries in the
|
||||
table are zero. DOS, and the BIOS printer functions (accessed via
|
||||
int 17h), use this table to translate an LPT port number to a
|
||||
physical port at a certain address.
|
||||
|
||||
The power-on self-test checks these addresses in a specific order,
|
||||
and addresses are put into the table as they are found, so the table
|
||||
will never have gaps. A particular I/O address does not necessarily
|
||||
always equate to the same specific LPT port number, although there
|
||||
are conventions.
|
||||
|
||||
2.1 ADDRESSING CONVENTIONS
|
||||
|
||||
The video card's parallel port is normally at 3BCh. This address is
|
||||
checked first by the BIOS, so if a port exists there, it will be LPT1.
|
||||
The BIOS then checks at 378h, then at 278h. AFAIK there is no
|
||||
standard address for a fourth port.
|
||||
|
||||
3. DIRECT HARDWARE ACCESS
|
||||
|
||||
The port consists of three 8-bit registers at adjacent addresses in
|
||||
the processor's I/O space. The registers are defined relative to
|
||||
the I/O base address, and are at IOBase+0, IOBase+1, and IOBase+2
|
||||
(for example if IOBase is 3BCh, then the registers are at 3BCh,
|
||||
3BDh, and 3BEh). Always use 8-bit I/O accesses on these registers.
|
||||
|
||||
3.1 DATA REGISTER
|
||||
|
||||
The data register is at IOBase+0. It may be read and written (using
|
||||
the IN and OUT instructions, or inportb() and outportb() or inp()
|
||||
and outp()). Writing a byte to this register causes the byte value
|
||||
to appear on pins 2 through 9 of the D-sub connector (unless the port
|
||||
is bidirectional and is set to input mode). The value will remain
|
||||
latched and stable until you write another value to the data
|
||||
register. Reading this register yields the state of those pins.
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
* . . . . . . . D7 (pin 9), 1=High, 0=Low
|
||||
. * . . . . . . D6 (pin 8), 1=High, 0=Low
|
||||
. . * . . . . . D5 (pin 7), 1=High, 0=Low
|
||||
. . . * . . . . D4 (pin 6), 1=High, 0=Low
|
||||
. . . . * . . . D3 (pin 5), 1=High, 0=Low
|
||||
. . . . . * . . D2 (pin 4), 1=High, 0=Low
|
||||
. . . . . . * . D1 (pin 3), 1=High, 0=Low
|
||||
. . . . . . . * D0 (pin 2), 1=High, 0=Low
|
||||
|
||||
3.2 STATUS REGISTER
|
||||
|
||||
The status register is at IOBase+1. It is read-only (writes will be
|
||||
ignored). Reading the port yields the state of the five status input
|
||||
pins on the parallel port connector at the time of the read access:
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
* . . . . . . . Busy . . (pin 11), high=0, low=1 (inverted)
|
||||
. * . . . . . . Ack . . (pin 10), high=1, low=0 (true)
|
||||
. . * . . . . . No paper (pin 12), high=1, low=0 (true)
|
||||
. . . * . . . . Selected (pin 13), high=1, low=0 (true)
|
||||
. . . . * . . . Error. . (pin 15), high=1, low=0 (true)
|
||||
. . . . . * * * Undefined
|
||||
|
||||
3.3 CONTROL REGISTER
|
||||
|
||||
The control register is at IOBase+2. It is read/write:
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
* * . . . . . . Unused (undefined on read, ignored on write)
|
||||
. . * . . . . . Bidirectional enable on PS/2 ports, see below
|
||||
. . . * . . . . Interrupt control, 1=enable, 0=disable
|
||||
. . . . * . . . Select . . (pin 17), 1=low, 0=high (inverted)
|
||||
. . . . . * . . Initialize (pin 16), 1=high, 0=low (true)
|
||||
. . . . . . * . Auto Feed (pin 14), 1=low, 0=high (inverted)
|
||||
. . . . . . . * Strobe . . (pin 1), 1=low, 0=high (inverted)
|
||||
|
||||
3.3.1 BIDIRECTIONAL CONTROL BIT (PS/2 PORTS)
|
||||
|
||||
See section >> 5.1 for details.
|
||||
|
||||
3.3.2 INTERRUPT ENABLE BIT
|
||||
|
||||
The parallel port interrupt was intended to be used for interrupt
|
||||
driven transmission of data to a parallel printer, but is not used
|
||||
by DOS and BIOS. Versions of OS/2 prior to Warp (3.0) did require
|
||||
the interrupt for printing, but from Warp onwards the interrupt is
|
||||
not required (though it can be used if the /IRQ switch is provided
|
||||
on the line in CONFIG.SYS, i.e. BASEDEV=PRINT0x.SYS /IRQ).
|
||||
|
||||
For experimenters, the interrupt facility is useful as a general
|
||||
purpose externally triggerable interrupt input. Beware though,
|
||||
not all cards support the parallel port interrupt.
|
||||
|
||||
The interrupt control bit controls a tristate buffer that drives the
|
||||
IRQ line. Setting the bit to '1' enables the buffer, and an IRQ will
|
||||
be triggered on each falling edge (high to low transition) of the Ack
|
||||
signal on pin 10 of the 25-pin connector. Disabling the interrupt
|
||||
allows other devices to use the IRQ line.
|
||||
|
||||
The actual IRQ number is either hardwired (by convention, the port at
|
||||
3BCh uses IRQ7) or jumper-selectable (IRQ5 is a common alternative).
|
||||
Sound cards, in particular, tend to use IRQ7 for their own purposes.
|
||||
|
||||
To use the IRQ you must also enable the interrupt via the interrupt
|
||||
mask register in the interrupt controller, at I/O address 21h, and
|
||||
your interrupt handler must send an EOI on exit. DOS technical
|
||||
programming references have notes on writing interrupt handlers.
|
||||
|
||||
3.3.3 PRINTER CONTROL BITS
|
||||
|
||||
The bottom four bits are latched and presented on the parallel port
|
||||
connector, much like the data register. Three of them are inverted,
|
||||
so writing a '1' will output a low voltage on the port pin for them.
|
||||
|
||||
These four outputs are open collector outputs with pullup resistors,
|
||||
so an external device can force them low (only) without stressing the
|
||||
driver in the PC, and they can even be used as inputs.
|
||||
|
||||
To use them as inputs, write 0100 binary to the bottom four bits of
|
||||
the control register. This sets the outputs all high, so they are
|
||||
pulled high by the pullup resistors (typically 4700 ohms). An
|
||||
external device can then pull them low, and you can read the pin
|
||||
states by reading the control register. Remember to allow for the
|
||||
inversion on three of the pins.
|
||||
|
||||
If you are using this technique, the control register is not strictly
|
||||
'read/write', because you may not read what you write (or wrote).
|
||||
|
||||
4 TRANSFERRING DATA VIA THE PARALLEL PORT
|
||||
|
||||
Many parallel ports are still the standard (send-only) type.
|
||||
Data can be transferred between such ports via a PC-to-PC parallel
|
||||
cable as used with INTERLNK, Laplink, and FastLynx, which links five
|
||||
data outputs from one end to the five status inputs on the other and
|
||||
vice versa (see section >> 4.1). Data is transferred four bits at a
|
||||
time using the fifth bits for handshaking. See section >> 4.2.
|
||||
Another method (which will also work with all port types) links eight
|
||||
data bits across to five status inputs and three control lines, which
|
||||
are used as inputs (see section >> 3.3.3). Other methods yielding a
|
||||
higher data rate can be used if both ports are bidirectional. The
|
||||
EPP and ECP have special hardware support for higher speeds (around
|
||||
1MB/s) and the ECP (see section >> 5.3) also supports high-speed data
|
||||
transfer using DMA.
|
||||
|
||||
4.1 FILE TRANSFER PROGRAM CABLES
|
||||
|
||||
The parallel-to-parallel cable is used by DOS's INTERLNK program.
|
||||
Laplink and FastLynx cables are the same. The pin-to-pin connection
|
||||
between two male 25-pin D-sub connectors is: 2-15, 3-13, 4-12, 5-10,
|
||||
6-11, and the reverse: 15-2, 13-3, 12-4, 10-5, and 11-6, and 25-25.
|
||||
This requires eleven wires. If you have spare wires, link some extra
|
||||
grounds together. Pins 18 to 25 inclusive are grounds. A very long
|
||||
cable may be unreliable; limit it to 5 metres, preferably less.
|
||||
|
||||
4.2 TRANSFERRING DATA USING STANDARD PARALLEL PORTS
|
||||
|
||||
These sample functions use the cable described above and work with
|
||||
any parallel port. Data is sent four bits at a time, using the
|
||||
fifth lines in each direction as data strobe and acknowledge
|
||||
respectively. This is sometimes called 'nibble mode'.
|
||||
|
||||
These sample functions send and receive a byte of data. One program
|
||||
must be the sender, the other must be the receiver. receive_byte()
|
||||
will be used only on the receiver. transmit_byte() will be used only
|
||||
on the sender, and will not return until the byte has been received
|
||||
and acknowledged by the receiver. input_value() is used on both
|
||||
sender and receiver. In a practical program like INTERLNK, protocols
|
||||
are required to control the data direction.
|
||||
|
||||
--------------------------- snip snip snip ---------------------------
|
||||
|
||||
static unsigned int lpt_base; /* Set to base I/O address */
|
||||
|
||||
/* Return input value as five-bit number. If input has changed since
|
||||
this function was last called, verify that the input is stable. */
|
||||
|
||||
unsigned int input_value(void) {
|
||||
static unsigned char last_value = 0xFF;
|
||||
auto unsigned char new1, new2;
|
||||
new1 = inportb(lpt_base + 1) & 0xF8;
|
||||
if (new1 != last_value) {
|
||||
while (1) {
|
||||
new2 = inportb(lpt_base + 1) & 0xF8;
|
||||
if (new2 == new1) /* Wait for stable value */
|
||||
break;
|
||||
new1 = new2;
|
||||
}
|
||||
last_value = new1;
|
||||
}
|
||||
return (last_value ^ 0x80) >> 3;
|
||||
}
|
||||
|
||||
/* Receive an 8-bit byte value, returns -1 if no data available yet */
|
||||
|
||||
signed int receive_byte(void) {
|
||||
unsigned int portvalue, bytevalue;
|
||||
portvalue = input_value(); /* Read input */
|
||||
if ((portvalue & 0x10) == 0)
|
||||
return -1; /* Await high flag */
|
||||
outportb(lpt_base, 0x10); /* Assert reverse flag */
|
||||
bytevalue = portvalue & 0x0F; /* Keep low nibble */
|
||||
do {
|
||||
portvalue = input_value();
|
||||
} while ((portvalue & 0x10) != 0); /* Await low flag */
|
||||
outportb(lpt_base, 0); /* Deassert reverse flag */
|
||||
bytevalue |= (portvalue << 4); /* High nibble */
|
||||
return bytevalue & 0xFF;
|
||||
}
|
||||
|
||||
/* Transmit an 8-bit byte value, won't return until value is sent */
|
||||
|
||||
void transmit_byte(unsigned int val) {
|
||||
val &= 0xFF;
|
||||
outportb(lpt_base, (val & 0x0F) | 0x10); /* Set nibble flag */
|
||||
while ((input_value() & 0x10) == 0)
|
||||
; /* Await returned flag high */
|
||||
outportb(lpt_base, val >> 4); /* Clear nibble flag */
|
||||
while ((input_value() & 0x10) != 0)
|
||||
; /* Await returned flag low */
|
||||
return;
|
||||
}
|
||||
|
||||
--------------------------- snip snip snip ---------------------------
|
||||
|
||||
5 SPECIAL PORTS
|
||||
|
||||
5.1 BIDIRECTIONAL PORTS (PS/2 AND COMPATIBLE)
|
||||
|
||||
The data register on bidirectional ports becomes an input port while
|
||||
input mode is selected. In this state, the outputs of the buffer that
|
||||
drives pins 2-9 of the 25-pin connector go into a high-impedance state
|
||||
and these pins become inputs which may be driven by an external device
|
||||
without stressing or damaging the driver. Values written to the data
|
||||
register are stored, but not asserted on the connector. Reading the
|
||||
data register yields the states of the pins at the time of the access.
|
||||
This allows data to be received (or transferred between two ports of
|
||||
this type) one byte at a time. This transfer mode is called byte mode.
|
||||
|
||||
Some parallel port cards may require a jumper change to allow input
|
||||
mode to be selected. Machines with a parallel port integrated on
|
||||
the motherboard may provide a BIOS setting to enable and disable
|
||||
bidirectional capability.
|
||||
|
||||
Bidirectional ports (PS/2 and compatible) use control register bit
|
||||
5 (see section >> 3.3) to enable input mode (input mode is enabled
|
||||
while this bit is set to 1). Other ports with input mode capability
|
||||
may enable input mode via a different signal, but I have no details.
|
||||
|
||||
5.2 SAMPLE PROGRAM - DISPLAY PORT TYPES
|
||||
|
||||
This program reports for LPT1, LPT2, and LPT3 whether the port exists
|
||||
and whether input mode is enabled by setting the bidirectional control
|
||||
bit in the control register. This only works on some bidirectional
|
||||
ports, so the program will report 'non-bidirectional or in standard
|
||||
mode' for ports that are bidirectional or enhanced, if input mode is
|
||||
not controlled by control register bit 5.
|
||||
|
||||
This program was written for Borland C. Change outportb() to outp()
|
||||
and inportb() to inp() for Microsoft C, I think. Save this code to
|
||||
BIDIR.C and compile with:
|
||||
|
||||
bcc -I<include_path> -L<library_path> bidir.c
|
||||
|
||||
--------------------------- snip snip snip ---------------------------
|
||||
|
||||
#include <dos.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The following function returns the I/O base address of the nominated
|
||||
parallel port. The input value must be 1 to 3. If the return value
|
||||
is zero, the specified port does not exist. */
|
||||
|
||||
unsigned int get_lptport_iobase(unsigned int lptport_num) {
|
||||
return *((unsigned int far *)MK_FP(0x40, 6) + lptport_num);
|
||||
}
|
||||
|
||||
/* Checks whether the port's data register retains data, returns 1 if
|
||||
so, 0 if not. The data register retains data on non-bidirectional
|
||||
ports, but on bidirectional ports in high impedance (tri-state)
|
||||
mode, the data register will not retain data. */
|
||||
|
||||
unsigned int test_retention(unsigned int iobase) {
|
||||
outportb(iobase, 0x55); /* Write a new value */
|
||||
(void) inportb(iobase); /* Delay */
|
||||
if (inportb(iobase) != 0x55) {
|
||||
return 0; /* Did not retain data */
|
||||
}
|
||||
outportb(iobase, 0xAA); /* Write another new value */
|
||||
(void) inportb(iobase); /* Delay */
|
||||
if (inportb(iobase) != 0xAA) {
|
||||
return 0; /* Did not retain data */
|
||||
}
|
||||
return 1; /* Retained data alright */
|
||||
}
|
||||
|
||||
void report_port_type(unsigned int portnum) {
|
||||
unsigned int iobase, oldctrl, oldval;
|
||||
iobase = get_lptport_iobase(portnum);
|
||||
if (iobase == 0) {
|
||||
printf("LPT%d does not exist\n", portnum);
|
||||
return;
|
||||
}
|
||||
oldctrl = inportb(iobase+2);
|
||||
outportb(iobase+2, oldctrl & 0xDF); /* Bidir off */
|
||||
(void) inportb(iobase); /* Delay */
|
||||
oldval = inportb(iobase); /* Keep old data */
|
||||
if (test_retention(iobase) == 0) {
|
||||
printf("LPT%d is faulty or set to input mode\n", portnum);
|
||||
outportb(iobase+2, oldctrl);
|
||||
outportb(iobase, oldval);
|
||||
return;
|
||||
}
|
||||
outportb(iobase+2, oldctrl | 0x20); /* Bidir on for some ports */
|
||||
if (test_retention(iobase))
|
||||
printf("LPT%d is non-bidirectional or in standard mode\n", portnum);
|
||||
else
|
||||
printf("LPT%d is bidirectional using control port bit 5\n", portnum);
|
||||
outportb(iobase+2, oldctrl); /* Put it back */
|
||||
outportb(iobase, oldval); /* Restore data */
|
||||
return;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
unsigned int portnum;
|
||||
for (portnum = 1; portnum < 4; ++portnum)
|
||||
report_port_type(portnum);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
--------------------------- snip snip snip ---------------------------
|
||||
|
||||
5.3 ENHANCED PORTS
|
||||
|
||||
The major types of parallel ports are:
|
||||
|
||||
Name Bidir? DMA?
|
||||
---- ------ ----
|
||||
Standard No No
|
||||
Bidirectional (PS/2) Yes No
|
||||
EPP (Enhanced Parallel Port) Yes(*) No
|
||||
ECP (Extended Capabilities Port) Yes(*) Yes
|
||||
|
||||
The PS/2 bidirectional port is a standard port with input mode
|
||||
capability, enabled via bit 5 of the control register, see sections
|
||||
>> 5.1 and >> 3.3.
|
||||
|
||||
The EPP (Enhanced Parallel Port) and ECP (Extended Capabilities Port)
|
||||
are described in the IEEE 1284 standard of 1994, which gives the
|
||||
physical, I/O and BIOS interfaces. Both are backward-compatible with
|
||||
the original parallel port, and add special modes which include
|
||||
bidirectional data transfer capability. These modes support fast
|
||||
data transfer between computers and printers and between computers,
|
||||
and support multiple printers or other peripherals on the same port.
|
||||
In their enhanced modes, they re-define the control and status lines
|
||||
of the parallel port connector, using it as a slow multiplexed
|
||||
parallel bus. The ECP supports DMA (direct memory access) for
|
||||
automated high-speed data transfer.
|
||||
|
||||
A very thorough and good reference on all port types is at:
|
||||
|
||||
http://www.fapo.com/1284int.htm.
|
||||
|
||||
End of the PC Parallel Port Mini-FAQ version 7
|
||||
|
||||
3323
study/sabre/os/files/Communication/ser_port.txt
Normal file
BIN
study/sabre/os/files/Disk/82077AA_FloppyControllerDatasheet.pdf
Normal file
476
study/sabre/os/files/Disk/CDROM.txt
Normal file
@@ -0,0 +1,476 @@
|
||||
|
||||
CD-ROM Technical Summary
|
||||
From Plastic Pits to "Fantasia"
|
||||
|
||||
Andy Poggio
|
||||
March 1988
|
||||
|
||||
|
||||
Abstract
|
||||
|
||||
This summary describes how information is encoded on Compact Disc (CD)
|
||||
beginning with the physical pits and going up through higher levels of
|
||||
data encoding to the structured multimedia information that is
|
||||
possible with programs like HyperCard. This discussion is much
|
||||
broader than any single standards document, e.g. the CD-Audio Red
|
||||
Book, while omitting much of the detail needed only by drive
|
||||
manufacturers.
|
||||
|
||||
|
||||
Salient Characteristics
|
||||
|
||||
1. High information density -- With the density achievable using
|
||||
optical encoding, the CD can contain some 540 megabytes of data on a
|
||||
disc less than five inches in diameter.
|
||||
|
||||
2. Low unit cost -- Because CDs are manufactured by a well-developed
|
||||
process similar to that used to stamp out LP records, unit cost in
|
||||
large quantities is less than two dollars.
|
||||
|
||||
3. Read only medium -- CD-ROM is read only; it cannot be written on
|
||||
or erased. It is an electronic publishing, distribution, and access
|
||||
medium; it cannot replace magnetic disks.
|
||||
|
||||
4. Modest random access performance -- Due to optical read head mass
|
||||
and data encoding methods, random access ("seek time") performance of
|
||||
CD is better than floppies but not as good as magnetic hard disks.
|
||||
|
||||
5. Robust, removable medium -- The CD itself is comprised mostly of,
|
||||
and completely coated by, durable plastic. This fact and the data
|
||||
encoding method allow the CD to be resistant to scratches and other
|
||||
handling damage. Media lifetime is expected to be long, well beyond
|
||||
that of magnetic media such as tape. In addition, the optical servo
|
||||
scanning mechanism allows CDs to be removed from their drives.
|
||||
|
||||
6. Multimedia storage -- Because all CD data is stored digitally, it
|
||||
is inherently multimedia in that it can store text, images, graphics,
|
||||
sound, and any other information expressed in digital form. Its only
|
||||
limit in this area is the rate at which data can be read from the
|
||||
disc, currently about 150 KBytes/second. This is sufficient for all
|
||||
but uncompressed, full motion color video.
|
||||
|
||||
|
||||
CD Data Hierarchy
|
||||
|
||||
Storing data on a CD may be thought of as occurring through a data
|
||||
encoding hierarchy with each level built upon the previous one. At
|
||||
the lowest level, data is physically stored as pits on the disc. It
|
||||
is actually encoded by several low-level mechanisms to provide high
|
||||
storage density and reliable data recovery. At the next level, it
|
||||
organized into tracks which may be digital audio or CD-ROM. The High
|
||||
Sierra specification then defines a file system built on CD-ROM
|
||||
tracks. Finally, applications like HyperCard specify a content format
|
||||
for files.
|
||||
|
||||
|
||||
The Physical Medium
|
||||
|
||||
The Compact Disc itself is a thin plastic disk some 12 cm. in
|
||||
diameter. Information is encoded in a plastic-encased spiral track
|
||||
contained on the top of the disk. The spiral track is read optically
|
||||
by a noncontact head which scans approximately radially as the disk
|
||||
spins just above it. The spiral is scanned at a constant linear
|
||||
velocity thus assuring a constant data rate. This requires the disc
|
||||
to rotate at a decreasing rate as the spiral is scanned from its
|
||||
beginning near the center of the disc to its end near the disc
|
||||
circumference.
|
||||
|
||||
The spiral track contains shallow depressions, called pits, in a
|
||||
reflective layer. Binary information is encoded by the lengths of
|
||||
these pits and the lengths of the areas between them, called land.
|
||||
During reading, a low power laser beam from the optical head is
|
||||
focused on the spiral layer and is reflected back into the head. Due
|
||||
to the optical characteristics of the plastic disc and the wavelength
|
||||
of light used, the quantity of reflected light varies depending on
|
||||
whether the beam is on land or on a pit. The modulated, reflected
|
||||
light is converted to a radio frequency, raw data signal by a
|
||||
photodetector in the optical head.
|
||||
|
||||
|
||||
Low-level Data Encoding
|
||||
|
||||
To ensure accurate recovery, the disc data must be encoded to optimize
|
||||
the analog-to-digital conversion process that the radio frequency
|
||||
signal must undergo. Goals of the low level data encoding include:
|
||||
|
||||
1. High information density. This requires encoding that makes the
|
||||
best possible use of the high, but limited, resolution of the laser
|
||||
beam and read head optics.
|
||||
|
||||
2. Minimum intersymbol interference. This requires making the
|
||||
minimum run length, i.e. the minimum number of consecutive zero bits
|
||||
or one bits, as large as possible.
|
||||
|
||||
3. Self-clocking. To avoid a separate timing track, the data should
|
||||
be encoded so as to allow the clock signal to be regenerated from the
|
||||
data signal. This requires limiting the maximum run length of the
|
||||
data so that data transitions will regenerate the clock.
|
||||
|
||||
4. Low digital sum value (the number of one bits minus the number of
|
||||
zero bits). This minimizes the low frequency and DC content of the
|
||||
data signal which permits optimal servo system operation.
|
||||
|
||||
A straightforward encoding would be to simply to encode zero bits as
|
||||
land and one bits as pits. However, this does not meet goal (1) as
|
||||
well as the encoding scheme actually used. The current CD scheme
|
||||
encodes one bits as transitions from pit to land or land to pit and
|
||||
zero bits as constant pit or constant land.
|
||||
|
||||
To meet goals (2) to (4), it is not possible to encode arbitrary
|
||||
binary data. For example, the integer 0 expressed as thirty-two bits
|
||||
of zero would have too long a run length to satisfy goal (3). To
|
||||
accommodate these goals, each eight-bit byte of actual data is encoded
|
||||
as fourteen bits of channel data. There are many more combinations of
|
||||
fourteen bits (16,384) than there are of eight bits (256). To encode
|
||||
the eight-bit combinations, 256 combinations of fourteen bits are
|
||||
chosen that meet the goals. This encoding is referred to as
|
||||
Eight-to-Fourteen Modulation (EFM) coding.
|
||||
|
||||
If fourteen channel bits were concatenated with another set of
|
||||
fourteen channel bits, once again the above goals may not be met. To
|
||||
avoid this possibility, three merging bits are included between each
|
||||
set of fourteen channel bits. These merging bits carry no information
|
||||
but are chosen to limit run length, keep data signal DC content low,
|
||||
etc. Thus, an eight bit byte of actual data is encoded into a total
|
||||
of seventeen channel bits: fourteen EFM bits and three merging bits.
|
||||
|
||||
To achieve a reliable self-clocking system, periodic synchronization
|
||||
is necessary. Thus, data is broken up into individual frames each
|
||||
beginning with a synchronization pattern. Each frame also contains
|
||||
twenty-four data bytes, eight error correction bytes, a control and
|
||||
display byte (carrying the subcoding channels), and merging bits
|
||||
separating them all. Each frame is arranged as follows:
|
||||
|
||||
Sync Pattern 24 + 3 channel bits
|
||||
Control and Display byte 14 + 3
|
||||
Data bytes 12 * (14 + 3)
|
||||
Error Correction bytes 4 * (14 + 3)
|
||||
Data bytes 12 * (14 + 3)
|
||||
Error Correction bytes 4 * (14 + 3)
|
||||
|
||||
TOTAL 588 channel bits
|
||||
|
||||
Thus, 192 actual data bits (24 bytes) are encoded as 588 channel bits.
|
||||
|
||||
Editorial: A CD physically has a single spiral track about 3 miles
|
||||
long. CDs spin at about 500 RPM when reading near the center down to
|
||||
about 250 RPM when reading near the circumference.
|
||||
|
||||
Disc with a 'c' or disk with a 'k'? A usage has emerged for these
|
||||
terms: disk is used for eraseable disks (e.g. magnetic disks) while
|
||||
disc is used for read-only (e.g. CD-ROM discs). One would presumably
|
||||
call a frisbee a disc.
|
||||
|
||||
|
||||
First Level Error Correction
|
||||
|
||||
Data errors can arise from production defects in the disk itself,
|
||||
defects arising from subsequent damage to the disk, or jarring during
|
||||
reading. A significant characteristic of these errors is that they
|
||||
often occur in long bursts. This could be due, for example, to a
|
||||
relatively wide mark on the disc that is opaque to the laser beam used
|
||||
to read the disc. A system with two logical components called the
|
||||
Cross Interleave Reed-Solomon Coding (CIRC) is employed for error
|
||||
correction. The cross interleave component breaks up the long error
|
||||
bursts into many short errors; the Reed-Solomon component provides the
|
||||
error correction.
|
||||
|
||||
As each frame is read from the disc, it is first decoded from fourteen
|
||||
channel bits (the three merging bits are ignored) into eight-bit data
|
||||
bytes. Then, the bytes from each frame (twenty-four data bytes and
|
||||
eight error correction bytes) are passed to the first Reed-Solomon
|
||||
decoder which uses four of the error correction bytes and is able to
|
||||
correct one byte in error out of the 32. If there are no
|
||||
uncorrectable errors, the data is simply passed along. If there are
|
||||
errors, the data is marked as being in error at this stage of
|
||||
decoding.
|
||||
|
||||
The twenty-four data bytes and four remaining error correction bytes
|
||||
are then passed through unequal delays before going through another
|
||||
Reed-Solomon decoder. These unequal delays result in an interleaving
|
||||
of the data that spreads long error bursts among many different passes
|
||||
through the second decoder. The delays are such that error bursts up
|
||||
to 450 bytes long can be completely corrected. The second
|
||||
Reed-Solomon decoder uses the last four error correction bytes to
|
||||
correct any remaining errors in the twenty-four data bytes. At this
|
||||
point, the data goes through a de-interleaving process to restore the
|
||||
correct byte order.
|
||||
|
||||
|
||||
Subcoding Channels and Blocks
|
||||
|
||||
The eight-bit control and display byte in each frame carries the
|
||||
subcoding channels. A subcoding block consists of 98 subcoding bytes,
|
||||
and thus 98 of the 588-bit frames. A block then can contain 2352
|
||||
bytes of data. Seventy-five blocks are read each second. With this
|
||||
information, it is now straightforward to calculate that the CD data
|
||||
rate is in fact correct for CD digital audio (CD-DA):
|
||||
|
||||
Required CD digital audio data rate: 44.1 K samples per second * 16
|
||||
bits per sample * 2 channels = 1,411,200 bits/sec.
|
||||
|
||||
CD data rate: 8 bits per byte * 24 bytes per frame * 98 frames per
|
||||
subcoding block * 75 subcoding blocks per second = 1,411,200 bits/sec.
|
||||
|
||||
The eight subcoding channels are labeled P through W and are encoded
|
||||
one bit for each channel in a control and display byte. Channel P is
|
||||
used as a simple music track separator. Channel Q is used for control
|
||||
purposes and encodes information like track number, track type, and
|
||||
location (minute, second, and frame number). During the lead-in track
|
||||
of the disc, channel Q encodes a table of contents for the disk giving
|
||||
track number and starting location. Standards have been proposed that
|
||||
would use the remaining channels for line graphics and ASCII character
|
||||
strings, but these are seldom used.
|
||||
|
||||
|
||||
Track Types
|
||||
|
||||
Tracks can have two types as specified in the control bit field of
|
||||
subchannel Q. The first type is CD digital audio (CD-DA) tracks. The
|
||||
two-channel audio is sampled at 44.1 Khz with sixteen bit linear
|
||||
sampling encoded as twos complement numbers. The sixteen bit samples
|
||||
are separated into two eight-bit bytes; the bytes from each channel
|
||||
alternate on the disc. Variations for audio tracks include
|
||||
pre-emphasis and four track recording.
|
||||
|
||||
The other type of track specified by the subchannel Q control bit
|
||||
field is the data track. These must conform to the CD-ROM standard
|
||||
described below. In general, a disc can have a mix of CD digital
|
||||
audio tracks and a CD-ROM track, but the CD-ROM track must come first.
|
||||
|
||||
Editorial: This first level error correction (the only type used for
|
||||
CD Audio data) is extremely powerful. The CD specification allows for
|
||||
discs to have up to 220 raw errors per second. Every one of these
|
||||
errors is (almost always) perfectly corrected by the CIRC scheme for a
|
||||
net error rate of zero. For example, our tests using Apple's CD-ROM
|
||||
drive (which also plays audio) show that raw error rates are around
|
||||
50-100 per second these days. Of course, these are perfectly
|
||||
corrected, meaning that the original data is perfectly recovered. We
|
||||
have tested flawed discs with raw rates up to 300 per second. Net
|
||||
errors on all of these discs? Zero! I would expect a typical audio
|
||||
CD player to perform similarly. Thus I expect this raw error rate to
|
||||
have no audible consequences.
|
||||
|
||||
So why did I say "almost always" corrected above? Because a
|
||||
sufficiently bad flaw may produce uncorrectable errors. These very
|
||||
unusual errors are "concealed" by the player rather than corrected.
|
||||
Note that this concealment is likely to be less noticeable than even a
|
||||
single scratch on an LP. Such a flaw might be a really opaque finger
|
||||
smudge; CDs do merit careful handling. On the two (and only two)
|
||||
occasions I have found these, I simply sprayed on a little Windex
|
||||
glass cleaner and wiped it off using radial strokes. This restored
|
||||
the CDs to zero net errors.
|
||||
|
||||
One can argue about the quality of the process of conversion of analog
|
||||
music to and from digital representation, but in the digital domain
|
||||
CDs are really very, very good.
|
||||
|
||||
|
||||
CD-ROM Data Tracks
|
||||
|
||||
Each CD-ROM data track is divided into individually addressable blocks
|
||||
of 2352 data bytes, i.e. one subcoding block or 98 frames. A header
|
||||
in each block contains the block address and the mode of the block.
|
||||
The block address is identical to the encoding of minute, second, and
|
||||
frame number in subcode channel Q. The modes defined in the CD-ROM
|
||||
specification are:
|
||||
|
||||
Mode 0 -- all data bytes are zero.
|
||||
|
||||
Mode 1 -- (CD-ROM Data):
|
||||
Sync Field - 12 bytes
|
||||
Header Field - 4
|
||||
User Data Field - 2048
|
||||
Error Detection Code - 4
|
||||
Reserved - 8
|
||||
Error Correction - 276
|
||||
|
||||
Mode 2 -- (CD Audio or Other Data):
|
||||
Sync Field - 12 bytes
|
||||
Header Field - 4
|
||||
User Data Field - 2048
|
||||
Auxiliary Data Field - 288
|
||||
|
||||
Thus, mode 1 defines separately addressable, physical 2K byte data
|
||||
blocks making CD-ROM look at this level very similar to other digital
|
||||
mass storage devices.
|
||||
|
||||
|
||||
Second Level Error Correction
|
||||
|
||||
An uncorrected error in audio data typically results in a brief, often
|
||||
inaudible click during listening at worst. An uncorrected error in
|
||||
other kinds of data, for example program code, may render a CD
|
||||
unusable. For this reason, CD-ROM defines a second level of error
|
||||
detection and error correction (EDC/ECC) for mode 1 data. The
|
||||
information for the EDC/ECC occupies most of the auxiliary data field.
|
||||
|
||||
The error detection code is a cyclic redundancy check (CRC) on the
|
||||
sync, header, and user data. It occupies the first four bytes of the
|
||||
auxiliary data field and provides a very high probability that
|
||||
uncorrected errors will be detected. The error correction code is
|
||||
essentially the same as the first level error correction in that
|
||||
interleaving and Reed-Solomon coding are used. It occupies the final
|
||||
276 bytes of the auxiliary data field.
|
||||
|
||||
Editorial: This extra level of error correction for CD-ROM blocks is
|
||||
one of the many reasons that CD-ROM drives are much more expensive
|
||||
than consumer audio players. To perform this error correction quickly
|
||||
requires substantial extra computing power (sometimes a dedicated
|
||||
microprocessor) in the drive.
|
||||
|
||||
This is also one reason that consumer players like the Magnavoxes
|
||||
which claim to be CD-ROM compatible (with their digital output jack on
|
||||
the back) are useless for that purpose. They have no way of dealing
|
||||
with the CD-ROM error correction. They also have no way for a
|
||||
computer to tell them where to seek.
|
||||
|
||||
Another reason that CD-ROM drives are more expensive is that they are
|
||||
built to be a computer peripheral rather than a consumer device, i.e.
|
||||
like a combination race car/truck rather than a family sedan. One
|
||||
story, probably apocryphal but not far from the truth, has it that a
|
||||
major Japanese manufacturer tested some consumer audio players to
|
||||
simulate computer use: they made them seek (move the optical head)
|
||||
from the inside of the CD to the outside and back again. These are
|
||||
called maximum seeks. The story says they managed to do this for
|
||||
about 24 hours before they broke down. A CD-ROM drive needs to be
|
||||
several orders of magnitude more robust. Fast and strong don't come
|
||||
cheap.
|
||||
|
||||
|
||||
The High Sierra File System Standard
|
||||
|
||||
Built on top of the addressable 2K blocks that the CD-ROM
|
||||
specification defines, the next higher level of data encoding is a
|
||||
file system that permits logical organization of the data on the CD.
|
||||
This can be a native file system like the Macintosh Hierarchical File
|
||||
System (HFS). Another alternative is the High Sierra (also known as
|
||||
the ISO 9660) file standard, recently approved by the National
|
||||
Information Standards Organization (NISO) and the International
|
||||
Standards Organization (ISO), which defines a file system carefully
|
||||
tuned to CD characteristics. In particular:
|
||||
|
||||
1. CDs have modest seek time and high capacity. As a result, the
|
||||
High Sierra standard makes tradeoffs that reduce the number of seeks
|
||||
needed to read a file at the expense of space efficiency.
|
||||
|
||||
2. CDs are read-only. Thus, concerns like space allocation, file
|
||||
deletion, and the like are not addressed in the specification.
|
||||
|
||||
For High Sierra file systems, each individual CD is a volume. Several
|
||||
CDs may be grouped together in a volume set and there is a mechanism
|
||||
for subsequent volumes in a set to update preceding ones. Volumes can
|
||||
contain standard file structures, coded character set file structures
|
||||
for character encoding other than ASCII, or boot records. Boot
|
||||
records can contain either data or program code that may be needed by
|
||||
systems or applications.
|
||||
|
||||
|
||||
High Sierra Directories and Files
|
||||
|
||||
The file system is a hierarchical one in which directories may contain
|
||||
files or other directories. Each volume has a root directory which
|
||||
serves as an ancestor to all other directories or files in the volume.
|
||||
This dictates an overall tree structure for the volume.
|
||||
|
||||
A typical disadvantage in hierarchical systems is that to read a file
|
||||
(which must be a leaf of the hierarchy tree) given its full path name,
|
||||
it is necessary to begin at the root directory and search through each
|
||||
of its ancestral directories until the entry for the file is found.
|
||||
For example, given the path name
|
||||
|
||||
Wine Regions:America:California:Mendocino
|
||||
|
||||
three directories (the first three components of the path name) would
|
||||
need to be searched. Typically, a separate seek would be required for
|
||||
each directory. This would result in relatively poor performance.
|
||||
|
||||
To avoid this, High Sierra specifies that each volume contain a path
|
||||
table in addition to its directories and files. The path table
|
||||
describes the directory hierarchy in a compact form that may be cached
|
||||
in computer memory for optimum performance. The path table contains
|
||||
entries for the volume's directories in a breadth-first order;
|
||||
directories with a common parent are listed in lexicographic order.
|
||||
Each entry contains only the location of the directory it describes,
|
||||
its name, and the location in the path table of its parent. This
|
||||
mechanism allows any directory to be accessed with only a single CD
|
||||
seek.
|
||||
|
||||
Directories contain more detailed information than the path table.
|
||||
Each directory entry contains:
|
||||
|
||||
Directory or file location.
|
||||
File length.
|
||||
Date and time of creation.
|
||||
Name of the file.
|
||||
Flags:
|
||||
Whether the entry is for a file or a directory.
|
||||
Whether or not it is an associated file.
|
||||
Whether or not it has records.
|
||||
Whether or not it has read protection.
|
||||
Whether or not it has subsequent extents.
|
||||
Interleave structure of the file.
|
||||
|
||||
Interleaving may be used, for example, to meet realtime requirements
|
||||
for multiple files whose contents must be presented simultaneously.
|
||||
This would happen if a file containing graphic images were interleaved
|
||||
with a file containing compressed sound that describes the images.
|
||||
|
||||
Files themselves are recorded in contiguous (or interleaved) blocks on
|
||||
the disc. The read-only nature of CD permits this contiguous
|
||||
recording in a straightforward manner. A file may also be recorded in
|
||||
a series of noncontiguous extents with a directory entry for each
|
||||
extent.
|
||||
|
||||
The specification does not favor any particular computer architecture.
|
||||
In particular all significant, multibyte numbers are recorded twice,
|
||||
once with the most significant byte first and once with the least
|
||||
significant byte first.
|
||||
|
||||
|
||||
Multimedia Information
|
||||
|
||||
Using the file system are applications that create and portray
|
||||
multimedia information. While it is true that a CD can store anything
|
||||
that a magnetic disk can store (and usually much more of it), CDs will
|
||||
be used more for storing information than for storing programs. It is
|
||||
the very large storage capacity of CDs coupled with their low cost
|
||||
that opens up the possibilities for interactive, multimedia
|
||||
information to be used in a multitude of ways.
|
||||
|
||||
Programs like HyperCard, with it's ease of authoring and broad
|
||||
extensibility, are very useful for this purpose. Hypercard stacks,
|
||||
with related information such as color images and sound, can be easily
|
||||
and inexpensively stored on CDs despite their possibly very large
|
||||
size.
|
||||
|
||||
Editorial: The High Sierra file system gets its name from the location
|
||||
of the first meeting on it: the High Sierra Hotel at Lake Tahoe. It
|
||||
is much more commonly referred to as ISO 9660, though the two
|
||||
specifications are slightly different.
|
||||
|
||||
It has gotten very easy and inexpensive to make a CD-ROM disc (or
|
||||
audio CD). For example, you can now take a Macintosh hard disk and
|
||||
send it with $1500 to one of several CD pressers. They will send you
|
||||
back your hard disk and 100 CDs with exactly the same content as
|
||||
what's on your disk. This is the easy way to make CDs with capacity
|
||||
up to the size of your hard disk (Apple's go up to 160 megabytes).
|
||||
True, this is not a full CD but CDs don't need to be full. If you
|
||||
have just 10 megabytes and need 100 copies, CDs may be the best way to
|
||||
go.
|
||||
|
||||
If you are buying a CD-ROM drive, there are several factors you might
|
||||
consider in making your choice. Two factors NOT to consider are
|
||||
capacity and data rate. The capacity of all CD-ROM drives is
|
||||
determined solely by the CD they are reading. Though you will see a
|
||||
range of numbers in manufacturers' specs (e.g. 540, 550, 600, and 650
|
||||
Mbytes), any drive can read any disc and so they are all fundamentally
|
||||
the same. All CD-ROM drives read data at a net 150 Kbytes/sec for
|
||||
CD-ROM data. Other data rates you may see may include error
|
||||
correction data (not included in the net rate) or may be a mode 2 data
|
||||
rate (faster than mode 1). All drives will be the same in all of
|
||||
these specs.
|
||||
|
||||
|
||||
End of article.
|
||||
|
||||
2415
study/sabre/os/files/Disk/CHSTranslation.txt
Normal file
28
study/sabre/os/files/Disk/DOSSector2PhysicalSector.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
From nntp.teleport.com!newsfeed.direct.ca!hunter.premier.net!news.mathworks.com!newsfeed.internetmci.com!vixen.cso.uiuc.edu!prairienet.org!dkrull Sun Aug 11 14:38:51 1996
|
||||
Path: nntp.teleport.com!newsfeed.direct.ca!hunter.premier.net!news.mathworks.com!newsfeed.internetmci.com!vixen.cso.uiuc.edu!prairienet.org!dkrull
|
||||
From: dkrull@prairienet.org (Don Krull)
|
||||
Newsgroups: comp.lang.asm.x86
|
||||
Subject: Re: DOS Sector => Physical Sector
|
||||
Date: 5 Aug 1996 11:41:54 GMT
|
||||
Organization: University of Illinois at Urbana
|
||||
Lines: 14
|
||||
Message-ID: <4u4mm2$2kn@vixen.cso.uiuc.edu>
|
||||
References: <4tiluk$d8c@josie.abo.fi>
|
||||
Reply-To: dkrull@prairienet.org (Don Krull)
|
||||
NNTP-Posting-Host: firefly.prairienet.org
|
||||
|
||||
|
||||
In a previous article, bhallstr@abo.fi asks:
|
||||
|
||||
> Does anyone have a formula for converting DOS Sectors to
|
||||
> Physical Sectors (Head, Cylinder, Sector) such as used in
|
||||
> INT 13h?
|
||||
|
||||
DOS_sector_num = BIOS_sector_num - 1 + Head_num*Sectors_per_track
|
||||
+ Track_num*Sectors_per_track*Total_heads
|
||||
|
||||
BIOS_sector_num = 1 + (DOS_sector_num MOD Sectors_per_track)
|
||||
|
||||
Don
|
||||
--
|
||||
|
||||
BIN
study/sabre/os/files/Disk/DeviceBaySpecsV0.90.pdf
Normal file
410
study/sabre/os/files/Disk/FLOPPY.TXT
Normal file
@@ -0,0 +1,410 @@
|
||||
NEC <20>PD765 - Floppy Disk Controller - 8272A
|
||||
|
||||
PS/2 FDC Diskette Status Register A at 3F0h
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> 3F0h PS/2 Disk Status Register A (read-only)
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> direction
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> write protect
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> index
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> head 1 select
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> track 0
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> step
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> second drive installed
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> interrupt pending
|
||||
|
||||
PS/2 FDC Diskette Status Register B at 3F1h
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> 3F1h PS/2 Disk Status Register B (read-only)
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> motor enable 0
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> motor enable 1
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> write enable
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> read data (toggles w/positive transition in -RD DATA)
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> write data (toggles w/positive transition in WR DATA)
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> drive select
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> reserved
|
||||
|
||||
FDC Digital Output Register at 3F2h (all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> port 3F2h (write only)
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> floppy drive select (0=A, 1=B, 2=floppy C, ...)
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = FDC enable, 0 = hold FDC at reset
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = DMA & I/O interface enabled (reserved PS/2)
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = turn floppy drive A motor on
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = turn floppy drive B motor on
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = turn floppy drive C motor on; (reserved PS/2)
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 = turn floppy drive D motor on; (reserved PS/2)
|
||||
|
||||
- used to control drive motors, drive selection, and feature enable
|
||||
- PS/2 only uses bit 0 for floppy drive select; bit 1 is reserved
|
||||
- PS/2 only uses bits 5 & 4 for motor enable; bits 7&6 are reserved
|
||||
- all DOR bits are cleared during controller reset
|
||||
|
||||
FDC Main Status Register at 3F4h (all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> port 3F4h (read only)
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> floppy drive 0 in seek mode/busy
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> floppy drive 1 in seek mode/busy
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> floppy drive 2 in seek mode/busy (reserved PS/2)
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> floppy drive 3 in seek mode/busy (reserved PS/2)
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDC read or write command in progress
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDC is in non-DMA mode
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O direction; 1 = FDC to CPU; 0 = CPU to FDC
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> data reg ready for I/O to/from CPU (request for master)
|
||||
|
||||
FDC Command Status Register 0 at 3F5h (all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> Command Status Register 0 at port 3F5h
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> unit selected at interrupt (0=A, 1=B, 2=...)
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> head number at interrupt (head 0 or 1)
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> not ready on read/write or SS access to head 1
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> equipment check (see note)
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> set to 1 when FDD completes a seek command
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> last command status (see below)
|
||||
|
||||
Bits
|
||||
76 Last Command Status
|
||||
00 command terminated successfully
|
||||
01 command execution started but terminated abnormally
|
||||
10 invalid command issued
|
||||
11 command terminated abnormally due to a change in state of
|
||||
the Ready Signal from the FDC (reserved on PS/2)
|
||||
|
||||
- equipment check can occur if FDD signals a fault or track zero is
|
||||
not found after 77 steps on a recalibrate command
|
||||
- PS/2 only uses bits 1-0 for drive (values are 01b and 10b)
|
||||
|
||||
FDC Command Status Register 1 at 3F5h (all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> Command Status Register 1 at port 3F5h
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> FDC cannot find ID address mark (see reg 2)
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> write protect detected during write
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDC cannot find sector ID
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> unused (always zero)
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> over-run; FDC not serviced in reasonable time
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> data error (CRC) in ID field or data field
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> unused (always zero)
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> end of cylinder; sector# greater than sectors/track
|
||||
|
||||
- bit 0 of Status Register 1 and bit 4 of Status Register 2 are
|
||||
related and mimic each other
|
||||
|
||||
FDC Command Status Register 2 at 3F5h (all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> Command Status Register 2 at port 3F5h
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> missing address mark in data field
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bad cylinder, ID not found and Cyl Id=FFh
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> scan command failed, sector not found in cylinder
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> scan command equal condition satisfied
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> wrong cylinder detected
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CRC error detected in sector data
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sector with deleted data address mark detected
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> unused (always zero)
|
||||
|
||||
- bit 0 of Status Register 1 and bit 4 of Status Register 2 are
|
||||
related and mimic each other
|
||||
|
||||
FDC Command Status Register 3 at 3F5h (FDD status, all systems)
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> Floppy Disk Drive Status at port 3F5h
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD unit selected status (0=A, 1=B, 2=...)
|
||||
<20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD side head select status (0=head 0, 1=head 1)
|
||||
<20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD two sided status signal
|
||||
<20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD track zero status signal
|
||||
<20> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD ready status signal
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD write protect status signal
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD fault status signal
|
||||
|
||||
PS/2 FDC Digital Input Register at 3F7h
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> 3F7h PS/2 Digital Input Register (read only)
|
||||
<20> <20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD> high density select
|
||||
<20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> reserved
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> diskette change
|
||||
|
||||
PS/2 FDC Configuration Control Register at 3F7h
|
||||
|
||||
<09>7<EFBFBD>6<EFBFBD>5<EFBFBD>4<EFBFBD>3<EFBFBD>2<EFBFBD>1<EFBFBD>0<EFBFBD> 3F7h PS/2 Config. Control Register (write only)
|
||||
<20> <20> <20> <20> <20> <20> <20><><EFBFBD><EFBFBD><EFBFBD> DRC1, DRC0 (see below)
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> reserved
|
||||
|
||||
DRC1 DRC0
|
||||
0 0 500000 bit per second mode
|
||||
0 1 reserved
|
||||
1 0 250000 bit per second mode
|
||||
1 1 reserved
|
||||
|
||||
|
||||
- Digital Input Register is used to sense the state of the
|
||||
(-diskette change) and the (-high density select) signals
|
||||
- Configuration Control Register is used to set the transfer rate
|
||||
|
||||
|
||||
FDC Programming Considerations
|
||||
|
||||
Three phases of command execution:
|
||||
|
||||
1. Command phase; commands are sent from the CPU to the FDC via
|
||||
port 3F5h; bit 6 of the Status Register at 3F4h must be zero
|
||||
2. Execution phase; FDC executes instruction & generates INT 6
|
||||
3. Result phase; status and other information is available to CPU;
|
||||
INT 6 sets bit 7 of BIOS Data Area location 40:3E which can
|
||||
be polled for completion status
|
||||
|
||||
|
||||
Example of a read operation:
|
||||
|
||||
1. turn disk motor on and set delay time for drive spin up
|
||||
2. perform seek operation; wait for disk interrupt
|
||||
3. prepare DMA chip to move data to memory
|
||||
4. send read command and wait for transfer complete interrupt
|
||||
5. read status information
|
||||
6. turn disk motor off
|
||||
|
||||
|
||||
Floppy Diskette Controller Operations (15 commands)
|
||||
|
||||
Read Data D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF SK 0 0 1 1 0
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: data length (if cmd byte 5==0)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Read Deleted Data D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF SK 0 1 1 0 0
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: data length (if cmd byte 5==0)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Write Data D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF 0 0 0 1 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: data length (if cmd byte 5==0)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Write Deleted Data D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF 0 0 1 0 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: data length (if cmd byte 5==0)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Read a Track D7 D6 D5 D4 D3 D2 D1 D0
|
||||
(Diagnostic)
|
||||
command byte 0: 0 MF SK 0 0 0 1 0
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: data length (if cmd byte 5==0)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Read ID D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: 0 MF 0 0 1 0 1 0
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Format a Track D7 D6 D5 D4 D3 D2 D1 D0
|
||||
(Write Sector IDs)
|
||||
command byte 0: 0 MF 0 0 1 1 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: bytes per sector
|
||||
command byte 3: sectors per track
|
||||
command byte 4: gap 3 length
|
||||
command byte 5: filler pattern to write in each byte
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Scan Equal D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF SK 1 0 0 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: scan test (1=scan contiguous, 2=scan alternate)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Scan Low or Equal D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF SK 1 1 0 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: scan test (1=scan contiguous, 2=scan alternate)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Scan High or Equal D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: MT MF SK 1 1 1 0 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: cylinder number
|
||||
command byte 3: head number
|
||||
command byte 4: sector number
|
||||
command byte 5: bytes per sector
|
||||
command byte 6: end of track (last sector in track)
|
||||
command byte 7: gap 3 length
|
||||
command byte 8: scan test (1=scan contiguous, 2=scan alternate)
|
||||
result byte 0: status register 0
|
||||
result byte 1: status register 1
|
||||
result byte 2: status register 2
|
||||
result byte 3: cylinder number
|
||||
result byte 4: head number
|
||||
result byte 5: sector number
|
||||
result byte 6: bytes per sector
|
||||
|
||||
Recalibrate D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: 0 0 0 0 0 1 1 1
|
||||
command byte 1: ? ? ? ? ? 0 US1 US0
|
||||
returns nothing
|
||||
|
||||
Sense Interrupt D7 D6 D5 D4 D3 D2 D1 D0
|
||||
Status
|
||||
command byte 0: 0 0 0 0 1 0 0 0
|
||||
result byte 0: status register 0
|
||||
result byte 1: present cylinder number
|
||||
|
||||
Specify Step & D7 D6 D5 D4 D3 D2 D1 D0
|
||||
Head Load
|
||||
command byte 0: 0 0 0 0 0 0 1 1
|
||||
command byte 1: step rate time <20> head unload time
|
||||
command byte 2: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>head load time<6D><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ND
|
||||
returns nothing
|
||||
|
||||
Sense Drive D7 D6 D5 D4 D3 D2 D1 D0
|
||||
Status
|
||||
command byte 0: 0 0 0 0 0 1 0 0
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
result byte 0: status register 3
|
||||
|
||||
Seek D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: 0 0 0 0 1 1 1 1
|
||||
command byte 1: ? ? ? ? ? HD US1 US0
|
||||
command byte 2: new cylinder number
|
||||
returns nothing
|
||||
|
||||
<20>PD765 Version D7 D6 D5 D4 D3 D2 D1 D0
|
||||
|
||||
command byte 0: ? ? ? 1 0 0 0 0
|
||||
result byte 0: status register 0
|
||||
90h = <20>PD765B; 80h = <20>PD765A or <20>PD765A-2
|
||||
|
||||
Invalid Command
|
||||
|
||||
result byte 0: status register 0 (value of 80h)
|
||||
|
||||
|
||||
Key to Abbreviations
|
||||
HD = Head Number Selected SK = SKip Deleted-data address mark
|
||||
MT = Multi-Track US0 = drive select bit 0
|
||||
MF = MFM mode US1 = drive select bit 1
|
||||
ND = Non-DMA mode
|
||||
|
||||
Head Load Time = 2 to 254ms in 2ms increments
|
||||
Head Unload Time = 16 to 240ms in 16ms increments
|
||||
Step Rate Time = 1 to 16ms in 1ms increments
|
||||
|
||||
|
||||
- PS/2 systems use the 8272A diskette controller which is software
|
||||
and port compatible with the NEC <20>PD765
|
||||
- accessed through ports 3F0h-3F7h; NEC <20>PD765 is accessed through
|
||||
ports 3F2h, 3F4h and 3F5h; the 8272A uses ports 3F0h, 3F1h,
|
||||
3F2h, 3F4h, 3F5h and 3F7h
|
||||
- data, command and status registers are all accessed through
|
||||
port 3F5h a register stack with one address presented to the bus
|
||||
- bit 7 of BIOS Data Area byte 40:3E can be polled to determine
|
||||
if a disk operation has completed; this bit is set by the
|
||||
interrupt handler when the operation has completed; it should
|
||||
be reset before continuing on with the next FDC operation
|
||||
16
study/sabre/os/files/Disk/FloppyMediaIDs.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
These are from the Gospel according to Saint Peter:
|
||||
|
||||
Format Size Cyls Heads Sec/Trk FATs Sec/FAT Sec/Root Media
|
||||
160K 5 1/4 40 1 8 2 ? ? FE
|
||||
180K 5 1/4 40 1 9 2 ? 4 FC
|
||||
320K 5 1/4 40 2 8 2 ? ? FF
|
||||
360K 5 1/4 40 2 9 2 4 7 FD
|
||||
1.2M 5 1/4 80 2 15 2 14 14 F9
|
||||
720K 3 1/2 80 2 9 2 6 7 F9
|
||||
1.44M 3 1/2 80 2 18 2 18 14 F0
|
||||
2.88M 3 1/2 80 2 36 2 ? ? ?
|
||||
|
||||
Does anybody have the straight poop on the 2.88M variety? (I could
|
||||
care less about the double-density, 5 1/4" formats.)
|
||||
|
||||
raster@indirect.com
|
||||
14
study/sabre/os/files/Disk/FloppySerialNumbers.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
>Does anyone know how DOS generates serial-numbers for floppies?
|
||||
|
||||
Here are the details of the volume serial number:
|
||||
|
||||
The first part of the serial number is equal to the sum of the time
|
||||
(seconds and hundredths of a second) and the date (month and day); The
|
||||
second part of the serial number is equal to the sum of the time (hours
|
||||
and minutes) and date (year), where all numbers are in hex. For
|
||||
example, if the diskette is formatted at 8:32:43.65 on 7/21/1991, the
|
||||
first part of the serial number will be 2B41+0715, or 3256; the second
|
||||
part of the serial number will be 0820+07C7, or 0FE7.
|
||||
|
||||
Hope that this is of some help.
|
||||
Ray
|
||||
298
study/sabre/os/files/Disk/HDTECH01.txt
Normal file
@@ -0,0 +1,298 @@
|
||||
From: datarec@inforamp.net (Nicholas Majors)
|
||||
Subject: Chapter 1 - Technicians' Guide to Hard Disks (REPOST)
|
||||
Date: 25 Mar 1995 18:45:09 GMT
|
||||
|
||||
|
||||
========================================================================
|
||||
Chapter 1 - TECHNICIANS' GUIDE TO PC HARD DISK SUBSYSTEMS
|
||||
========================================================================
|
||||
copyright (c) 1992, 1995
|
||||
|
||||
Nicholas Majors,
|
||||
|
||||
DATA RECOVERY LABS
|
||||
(division of Data Recovery Services Inc) Voice : 1-416-510-6990
|
||||
1315 Lawrence Avenue East - Unit 502 FAX : 1-416-510-6992
|
||||
Don Mills, Ontario, Canada M3A 3R3 Email : datarec@the-wire.com
|
||||
========================================================================
|
||||
|
||||
INTRODUCTION :
|
||||
|
||||
This booklet (now electronic) is published as a service of Data
|
||||
Recovery Labs. Its purpose is to provide the fundamental knowledge of
|
||||
concepts and terminology that is necessary to deal with the
|
||||
complexities of hard disk subsystems. It is not a technical reference
|
||||
guide and should not replace original documentation made available by
|
||||
manufacturers.
|
||||
|
||||
Every day we meet and deal with technicians and support personnel who
|
||||
install, upgrade and maintain hard drives, without knowing exactly
|
||||
what they are and how they work. Gaining a working knowledge of disk
|
||||
subsystems is not a simple task and requires much study - and -
|
||||
experience. Don't expect any book, training course, or manual to make
|
||||
you into an expert. However, if you read and understand most of this
|
||||
material, you will be off to a fine start.
|
||||
|
||||
The principal author is Nick Majors. He has been in the industry
|
||||
since 1979, designing and developing hardware and operating system
|
||||
enhancements and performance tools. He is an experienced machine
|
||||
language programmer and has provided technical training to support
|
||||
personnel for some of Canada's leading banks, corporations, government
|
||||
departments and PC service organizations. He is Manager of Technical
|
||||
Services for Data Recovery Labs which he founded in 1989.
|
||||
|
||||
While this booklet deals primarily with PC and PC compatible
|
||||
platforms, there is much information to benefit support personnel with
|
||||
other hardware platforms.
|
||||
|
||||
Every effort has been made to ensure accuracy, but misprints and
|
||||
ambiguities may still remain, so please use caution.
|
||||
|
||||
========================================================================
|
||||
HISTORY AND OVERVIEW :
|
||||
|
||||
The original IBM PC, introduced in 1981, did not support any type of
|
||||
hard drive. Program code in the BIOS did not recognize any such
|
||||
device and early versions of DOS precluded mass storage by limiting
|
||||
the maximum number of directory entries. This is not surprising when
|
||||
you consider that the original 4.77 MHz PC came with 16 K of RAM,
|
||||
expandable to 64 K on the motherboard. Even floppy drives and a disk
|
||||
operating system were options to upgrade the built in cassette
|
||||
recorder port and ROM basic.
|
||||
|
||||
To utilize a hard drive in a PC requires:
|
||||
|
||||
- a Hardware IRQ (interrupt request)
|
||||
- I/O port addresses for the controller
|
||||
- a DMA channel (now optional)
|
||||
- low level program code
|
||||
- a physical interface to the bus (expansion slot or built-in)
|
||||
- operating system support
|
||||
- sufficient power and cooling
|
||||
|
||||
After DOS 2 introduced the sub-directory system and support for mass
|
||||
storage devices, companies started selling hard drives for the PC.
|
||||
These were external cabinets that contained the disk itself, a
|
||||
controller card, and a dedicated power supply (since the PC's 63.5 watts
|
||||
were insufficient). Migrating from other architectures, these units
|
||||
connected to the PC through cabling to an 8 bit adapter card that
|
||||
plugged into an available expansion slot. These subsystems were
|
||||
configured to use one of the available IRQ's, DMA channels, a range of
|
||||
I/O ports, and program code that was made available through a device
|
||||
driver loaded into memory after startup (booting from a floppy).
|
||||
|
||||
In 1983, the IBM XT (eXTended) was unveiled with its built-in 10 MB
|
||||
fixed disk. IBM worked with a company (Xebec, I think) to take the
|
||||
controller components normally located in the external cabinet and
|
||||
build them right onto a bus interface card, creating what we commonly
|
||||
call the "hard disk controller".
|
||||
|
||||
Program code was provided by a ROM chip on the controller card which
|
||||
supplemented subroutines in the BIOS, and the internal power supply
|
||||
was upgraded to 135 watts to provide power for the internally mounted
|
||||
drive.
|
||||
|
||||
The XT design utilized :
|
||||
|
||||
- IRQ 5
|
||||
- I/O port addresses 320-32f
|
||||
- DMA channel 3
|
||||
- Program Code from adapter ROM at c8000
|
||||
- DOS 2.0 or higher
|
||||
|
||||
Several companies started manufacturing and selling similar
|
||||
drive/controller packages with various improvements including higher
|
||||
capacities, superior performance and built-in floppy controller
|
||||
components on the same card (to save an expansion slot). These third
|
||||
party subsystems could even be added to an original PC, so long as the
|
||||
internal power supply was also upgraded.
|
||||
|
||||
In 1984, the IBM AT (Advanced Technology) brought a complete overhaul
|
||||
to hard disk systems. Program code was included in the motherboard ROM
|
||||
BIOS, eliminating the need for a ROM chip on the new 16 bit controller
|
||||
card, and a higher quality drive improved access times. The system
|
||||
included use of newly added higher IRQ's, eliminated the use of DMA
|
||||
for hard drives, and changed the range of I/O addresses.
|
||||
|
||||
The AT design utilized :
|
||||
|
||||
- IRQ 14
|
||||
- I/O port addresses 1f0-1f8
|
||||
- DMA channel - none
|
||||
- Program Code from motherboard ROM BIOS
|
||||
- DOS 2.0 or higher
|
||||
|
||||
Hardware configuration details for the AT, including hard disk
|
||||
parameters, were stored in a low power CMOS chip connected to a small
|
||||
battery, eliminating many of the motherboard configuration dip
|
||||
switches and jumpers. The battery allowed information to be
|
||||
maintained while the computer was turned off and information could be
|
||||
changed by running a setup program from disk.
|
||||
|
||||
The original AT supported 14 different drive types, recognizing
|
||||
specific hard disks ranging from 10 to 112 MB. Any drive with
|
||||
physical parameters that did not match one of these types needed a ROM
|
||||
extension on the controller card or a device driver loaded during
|
||||
boot-up.
|
||||
|
||||
DOS versions prior to 4.0 (or 3.31) did not support partitions larger
|
||||
than 32 MB no matter how big a drive was. This was because of sector
|
||||
numbering that could not exceed 16 bit values (up to 65,536 sectors).
|
||||
To make a larger partition required the use of special software like
|
||||
Ontrack's Disk Manager. This software was so popular that many drive
|
||||
manufacturers shipped it with their product. Unfortunately, while
|
||||
this offered one of the better solutions, it did pose compatibility
|
||||
problems for many disk utilities because, in effect, you had a non-DOS
|
||||
partition.
|
||||
|
||||
Many people opted instead to divide their drives into 32 MB partitions
|
||||
creating a C: D: E: etc. up to the physical capacity. Prior to DOS
|
||||
3.3, even this was not possible, because DOS did not recognize
|
||||
extended partitions!
|
||||
|
||||
The number of drive types supported by CMOS has expanded to over 40
|
||||
and most current BIOS's provide a user definable type to allow
|
||||
parameters to match any drive. Most PC's today still rely on this
|
||||
original CMOS drive type scheme to configure and control hard disks,
|
||||
though many architectures and BIOS's have changed how the information
|
||||
is stored and updated.
|
||||
|
||||
This inherently creates certain limiting factors, including a problem
|
||||
with more than two hard drives and BIOS/OS limits to recognizing more
|
||||
than 1024 cylinders, 16 heads and 63 sectors per track. Various
|
||||
technologies must be used to translate non-compliant physical
|
||||
geometries into logical parameters recognized by the system to
|
||||
maintain compatibility with operating system and utility programs that
|
||||
are tied to these limits.
|
||||
|
||||
With each sector holding 512 bytes of data this allows for drives no
|
||||
larger than 504 MB.
|
||||
(1024 X 16 X 63 = 1,032,192 sectors X 512 = 528,482,304 bytes)
|
||||
|
||||
To understand this limit, we have to examine how hard drives are
|
||||
accessed by a PC.
|
||||
|
||||
Primarily, I/O commands are sent to the controller via a range of
|
||||
reserved port addresses. This is a very complicated and tedious
|
||||
process and the ROM BIOS includes a subroutine (INT 13) to perform
|
||||
these tasks for you. The DOS operating system then has certain
|
||||
functions that further simplify the process. They include INT 25/26
|
||||
functions to read and write absolute sectors to the drive as well as
|
||||
higher level functions (INT 21) to Open files, Close files, Write data
|
||||
to files, etc. Most programs rely on these DOS functions to control
|
||||
access to hard drives and DOS in turn calls the INT 13 BIOS
|
||||
subroutines which do the actual I/O commands.
|
||||
|
||||
All of these subroutines are assembly language code that are loaded
|
||||
into memory from either your BIOS chip(s) or Operating System files at
|
||||
startup.
|
||||
|
||||
Assembly language routines store and manipulate values in registers
|
||||
within the CPU. The lowest common denominator for INTEL based PC's is
|
||||
16 bit registers. Any program or routine that wants to be backward
|
||||
compatible, must use these base registers whether run on an 8088 or a
|
||||
Pentium. This basic INT 13 is the backbone of PC compatibility and
|
||||
uses 16 bit registers in the following way:
|
||||
|
||||
DX - 8 bits for head number - 8 bits for drive number
|
||||
CX - 10 bits for cylinder number and 6 bits for sector number
|
||||
|
||||
The largest 10 bit number possible is 1023 hence the limit on cylinder
|
||||
numbers (from 0-1023) and the largest 6 bit number is 63 (from 1-63)
|
||||
allowing 63 sectors per track.
|
||||
|
||||
But note - the DX register allows a maximum of 255 heads, not the 16
|
||||
that original specifications called for. This is what allows various
|
||||
translation schemes to deal with drives up to 8 GB while remaining INT
|
||||
13 compatible.
|
||||
|
||||
If the DX register allows 8 bits for drive number, shouldn't it be
|
||||
able to control 255 drives instead of only two?
|
||||
|
||||
When the INT 13 sends commands to your controller, it must know the
|
||||
physical geometry of the drive in question. During initialization of
|
||||
the PC, values for disk types are read from CMOS and stored into an
|
||||
area of RAM called the BIOS DATA AREA. Pointers to those entries are
|
||||
stored in the Interrupt Vector Table (at addresses 0:104h and 0:118h).
|
||||
The table only reserved pointers for two drives, so even if your CMOS
|
||||
held more values, the standard routines wouldn't know how to deal with
|
||||
them.
|
||||
|
||||
Why were the INT 13 routines so limited? They were written at a time
|
||||
when 10 and 20 MB drives were the norm, and 120 MB was unbelievable.
|
||||
They were designed to communicate with a specific controller
|
||||
interface, the ST412/506 standard (WD1003 controller), and the specs
|
||||
for passing parameters included only 10 bits for cylinders number, 4
|
||||
bits for head number and a single bit for drive number.
|
||||
|
||||
Some of these limitations have been overcome in the past by replacing
|
||||
the PC's INT 13 sub- routines with code that could recognize and deal
|
||||
with different devices. That's why virtually all SCSI adapter cards
|
||||
include a ROM chip and you must set the drive type to ZERO. In
|
||||
effect, no standard drives installed for the motherboard BIOS to
|
||||
control.
|
||||
|
||||
NetWare and other advanced Operating Systems use the drive type only
|
||||
long enough to boot- up and then replace the INT 13 code with their
|
||||
own device drivers. You then need to load a different .DSK file
|
||||
written specifically for each type of controller.
|
||||
|
||||
In the past couple of years, many motherboard and controller BIOS's
|
||||
have been enhanced to deal with ever increasing demands, but the
|
||||
process of establishing new standards has led to continuing confusion
|
||||
and compatibility problems.
|
||||
|
||||
========================================================================
|
||||
END OF CHAPTER 1
|
||||
========================================================================
|
||||
|
||||
COMING SOON - CHAPTER 2 - Inside Hard Drives and Controllers :
|
||||
- Parts and Components
|
||||
- also suggestions for must reading material
|
||||
|
||||
========================================================================
|
||||
NOTICES & PERSONAL RANTS :
|
||||
========================================================================
|
||||
|
||||
INTERNET APOLOGIES : The original artiticle, offering this booklet, was
|
||||
posted Jan. 29, 1995. I have had lots of replies, BUT - all kinds of
|
||||
people insist on replying by follow-up articles instead of private
|
||||
Mail. This proved downright embarrassing! I only wanted E-MAIL
|
||||
responses. Sorry for the clutter!
|
||||
|
||||
DISTRIBUTION : Chapters 1-2 will be sent by E-Mail to some 2,700
|
||||
people who requested it and is being posted to various News groups.
|
||||
The work to maintain a mailing list is much more trouble than it's
|
||||
worth, therefore - future chapters will be posted to a select number of
|
||||
New Groups and Bulletin Boards.
|
||||
|
||||
Files can be obtained by ftp. Look for "hdtech??.txt"
|
||||
|
||||
ftp site: archive.umich.edu in /msdos/info/disk
|
||||
|
||||
mirror : wuarchive.wustl.edu in /systems/ibmpc/umich.edu/info/disk
|
||||
(Note - This mirror is not always up to date)
|
||||
|
||||
ftp site: ftp.wi.leidenuniv.nl in /pub/faqs
|
||||
|
||||
Also Daniel Tauritz has a home page with links to this document plus a
|
||||
number of hard drive FAQs:
|
||||
|
||||
http://www.wi.leidenuniv.nl/~dtauritz/ata.html
|
||||
|
||||
If anyone specifically requires E-mail, send me a note with "e-mail
|
||||
please" as the subject. I will be glad to accommodate them, assuming
|
||||
it's a manageable number. I cannot provide hard copy or S-Mail.
|
||||
|
||||
RIGHTS : This material is copyright (C) 1992,1995 by Nicholas Majors
|
||||
and Data Recovery Labs. Feel free to distribute it as either hard
|
||||
copy, electronically, or by BBS - with full copyright credit to both.
|
||||
|
||||
COMMENTS & CRITICISM : I look forward to receiving suggestions,
|
||||
improvements, additions, (and yes even compliments) to this material.
|
||||
Please bear in mind who this has been written for - tech support
|
||||
personnel, not end-users and not engineers or hardware designers.
|
||||
|
||||
========================================================================
|
||||
|
||||
|
||||
476
study/sabre/os/files/Disk/HDTECH02.txt
Normal file
@@ -0,0 +1,476 @@
|
||||
From: datarec@inforamp.net (Nicholas Majors)
|
||||
Subject: Chapter 2 - Technicians' Guide to Hard Disks
|
||||
Date: 25 Mar 1995 18:40:54 GMT
|
||||
|
||||
|
||||
|
||||
========================================================================
|
||||
Chapter 2 - TECHNICIANS' GUIDE TO PC HARD DISK SUBSYSTEMS
|
||||
========================================================================
|
||||
copyright (c) 1992, 1995
|
||||
|
||||
Nicholas Majors,
|
||||
|
||||
DATA RECOVERY LABS
|
||||
(division of Data Recovery Services Inc) Voice : 1-416-510-6990
|
||||
1315 Lawrence Avenue East - Unit 502 FAX : 1-416-510-6992
|
||||
Don Mills, Ontario, Canada M3A 3R3 Email : datarec@the-wire.com
|
||||
========================================================================
|
||||
|
||||
Before we consider how to install, configure and maintain hard drives,
|
||||
we need a basic understanding of drive construction and design concepts.
|
||||
This chapter examines in some detail the parts and functional components
|
||||
of hard drive subsystems.
|
||||
|
||||
(Note : A number of acronyms are used throughout this chapter and the
|
||||
glossary for this booklet is not yet available. Therefore, I have
|
||||
attached a brief set of definitions for some of the terminology.)
|
||||
|
||||
HARD DRIVES AND CONTROLLERS:
|
||||
|
||||
A hard drive subsystem is comprised of the following components:
|
||||
|
||||
1. The Hard Disk, with one or more boards (PCB) attached.
|
||||
2. A Controller Mechanism, either on the hard disk PCB or on the bus
|
||||
adapter within the PC.
|
||||
3. Bus Adapter for interfacing the controller to the host PC.
|
||||
4. Cables and Connectors to link it all together.
|
||||
|
||||
========================================================================
|
||||
THE HARD DISK:
|
||||
|
||||
Within a sealed enclosure (Head Disk Assembly or HDA) are one or more
|
||||
rigid platters that are "fixed" or non-removable. These are coated
|
||||
with magnetically sensitized material and data can be written to and
|
||||
read from the surface by means of electromagnetic read/write heads.
|
||||
When powered up, the platters are constantly rotating (except for
|
||||
certain pre-programmed sleep modes) and the heads are moved back and
|
||||
forth across the surface to access different locations. This is a
|
||||
sealed unit which should not be opened, except by qualified personnel in
|
||||
a controlled, dust free environment.
|
||||
|
||||
The circuit board(s) attached to the outside of the HDA provide the
|
||||
electronics needed for physical control of the motors within the sealed
|
||||
unit. They interface the source of electrical power and control signals
|
||||
to the disk assembly through various connectors and cables. Most boards
|
||||
have some jumpers, dip switches and/or resistors that are used for
|
||||
configuration purposes.
|
||||
|
||||
Functionally, these PCB's are separate from the Hard Disk Controller,
|
||||
but many of the newer drives (IDE and SCSI) embed the controller chip
|
||||
directly onto this board (as opposed to having it on the Bus adapter).
|
||||
|
||||
INSIDE THE HDA - PARTS OF A HARD DISK:
|
||||
|
||||
1. Disk Platter(s), separated by spacers and held together by a clamp.
|
||||
2. Spindle shaft onto which platters are mounted.
|
||||
3. Spindle motor for rotating the platters.
|
||||
4. Electromagnetic read/write heads (usually, one per surface).
|
||||
5. Access arms or armatures from which the heads are suspended.
|
||||
6. Actuator for moving the arms (with heads attached).
|
||||
7. Preamplifier circuitry to maximize read/write signals.
|
||||
8. Air filter and pressure vent.
|
||||
|
||||
The Platters:
|
||||
|
||||
Most platters or disks are made of an aluminum alloy, though ceramic or
|
||||
glass platters can also be found. The diameter is normally 2 1/2", 3
|
||||
1/2" or 5 1/4" with a hole in the center for mounting onto the spindle
|
||||
shaft. Thickness of the media can vary from less than 1/32 of an inch
|
||||
to about 1/8 of an inch.
|
||||
|
||||
During manufacture the platters are coated with a magnetizable material.
|
||||
Older drives used a ferrite compound applied by squirting a solution
|
||||
onto the surface and rotating at high speeds to distribute the material
|
||||
by centrifugal force. This process left a rust colored ferrite layer
|
||||
which was then hardened, polished and coated with a lubricant.
|
||||
|
||||
Newer drives apply the magnetic layer by plating a thin metal film onto
|
||||
the surface through galvanization or sputtering. These surfaces have a
|
||||
shiny chrome-like appearance.
|
||||
|
||||
Spindle and Spindle Motors:
|
||||
|
||||
Most drives have several platters that are separated by disk spacers and
|
||||
clamped to a rotating spindle that turns the platters in unison. A
|
||||
direct drive, brushless spindle motor is built into the spindle or
|
||||
mounted directly below it. (Sometimes this motor is visible from outside
|
||||
of the sealed enclosure.) The spindle, and consequently the platters,
|
||||
are rotated at a constant speed, usually 3,600 RPM, though newer models
|
||||
have increased that to 4800, 5400, or 7,200.
|
||||
|
||||
The spindle motor receives control signals through a closed loop
|
||||
feedback system that stabilizes to a constant rotation speed. Control
|
||||
signals come from information written onto the surface(s) during
|
||||
manufacture or with older drives, from physical sensors.
|
||||
|
||||
Read/Write Heads:
|
||||
|
||||
Since both sides of each platter are coated to provide separate
|
||||
surfaces, there is normally one electromagnetic read/write head for each
|
||||
side of each platter. Therefore, a drive with 4 platters would have 8
|
||||
sides and 8 heads. Some drives use one side as a dedicated surface for
|
||||
control signals leaving an odd number (5,7,etc.) of heads for actual
|
||||
use.
|
||||
|
||||
Each head is mounted onto the end of an access arm and these arms (one
|
||||
per surface) are moved in unison under the control of a single actuator
|
||||
mechanism. When one head is over track 143, all the heads on all other
|
||||
sides should be at the same location over their respective surfaces.
|
||||
|
||||
Generally speaking, only one of the heads is active at any given time.
|
||||
There are some drives that can read or write from two or more heads at a
|
||||
time, but while this has been common with main frame drives, it
|
||||
represents a major design change for personal computers and the
|
||||
technology is not yet widely used.
|
||||
|
||||
The spinning disk(s) create an air cushion over which the heads float.
|
||||
Depending on design, this air buffer ranges from 2 to 15 microns. By
|
||||
contrast, a smoke particle or finger print is about 30 microns in size!
|
||||
|
||||
The heads are not supposed to come into contact with the surface during
|
||||
rotation. Only when powered off should the heads come to rest on the
|
||||
surface, but this should be over a specific area of the surface,
|
||||
reserved for that purpose. Most drives built since the late 1980's
|
||||
employ an automatic parking feature which moves the heads to this
|
||||
designated region and may even lock the heads there until powered up.
|
||||
|
||||
Head Actuators:
|
||||
|
||||
The head actuator is the positioning mechanism used to move the arms and
|
||||
consequently the heads, back and forth over the surface. Once again,
|
||||
earlier drives used a different method than is now common.
|
||||
|
||||
Originally, head positioning was controlled by a stepper motor that
|
||||
rotated in either direction by reacting to stepper pulses and moving the
|
||||
head assembly back and forth by means of a "rack and pinion" or by
|
||||
spooling and unspooling a band attached to the actuator arms. Each
|
||||
pulse moved the assembly over the surface in predefined steps or
|
||||
detents. Each step represented a track location and data was expected
|
||||
to be under the head. This design, still used for floppy drives, is not
|
||||
suitable for current drive densities and is prone to alignment problems
|
||||
caused by friction, wear and tear, heat deformation, and lack of
|
||||
feedback information needed for correcting positioning error.
|
||||
|
||||
The more common voice coil actuator controls the movement of a coil
|
||||
toward or away from a permanent magnet based upon the amount of current
|
||||
flowing through it. The armatures are attached to this coil and move in
|
||||
and out over the surface with it. This is a very precise method, but
|
||||
also very sensitive. Any variation in the current can cause the head
|
||||
assembly to change position and there are no pre-defined positions.
|
||||
Inherently this is an analog system, with the exact amount of movement
|
||||
controlled by the exact amount of current applied.
|
||||
|
||||
The actual position of the coil is determined by servo (or indexing)
|
||||
information, which is written to the drive by the manufacturer.
|
||||
Location is adjusted to different tracks by reading and reacting to
|
||||
these control signals.
|
||||
|
||||
Internal Electronics:
|
||||
|
||||
There is surprisingly little circuitry found within the sealed HDA.
|
||||
There are electrical and control wires for the spindle and head actuator
|
||||
motors and the head assembly has flex cables with a preamplifier chip
|
||||
often built onto it. This chip takes pulses from the heads (as close to
|
||||
the source as possible) and cleans up and amplifies these signals before
|
||||
transmission to components outside of the housing.
|
||||
|
||||
Air Filtering and Ventilation:
|
||||
|
||||
Minor wear of internal components and occasional contact of the heads
|
||||
with the surface can cause microscopic particles to be loosened within
|
||||
the HDA. A permanent air filter is mounted within the air stream to
|
||||
remove these particles before they can cause damage to delicate
|
||||
mechanisms.
|
||||
|
||||
Most drives also have a small vent to allow for minor air exchange from
|
||||
outside of the housing. This allows for equalization of air pressure so
|
||||
drives can be used in different environments without risk of imploding
|
||||
or exploding.
|
||||
|
||||
========================================================================
|
||||
CONTROLLERS AND BUS ADAPTERS:
|
||||
|
||||
The hard disk controller provides the logical link between a hard disk
|
||||
unit and the program code within the host computer. It reacts to
|
||||
requests from the computer by sending seek, read, write, and control
|
||||
signals to the drive and must interpret and control the flow of data.
|
||||
|
||||
Data moving to and from the drive includes sector ID's, positioning
|
||||
information and timing or clock signals. The controller must encode,
|
||||
decode and separate this control information from actual data written to
|
||||
or read from the drive.
|
||||
|
||||
Also, data is sent to and from the drive serially, in bit format, but
|
||||
the CPU wants to recieve at least a byte (8 bits) at a time. The
|
||||
controller must take bits (8 - 16 - or 32 at a time) and assemble them
|
||||
into bytes, words, and doublewords that can be transferred to/from the
|
||||
computer.
|
||||
|
||||
"OUR INDUSTRY MUST LOVE STANDARDS - WE HAVE THOUSANDS OF THEM!"
|
||||
|
||||
And so it is with hard disk controllers.
|
||||
|
||||
Controllers can be categorized in several different ways, by :
|
||||
|
||||
Basic computer design (PC/XT vs AT-286-386-486,etc)
|
||||
- as mentioned in the first chapter, standard AT controllers use
|
||||
different I/O addresses, IRQ and employ PIO as opposed to DMA.
|
||||
|
||||
Bus Architecture (8-16 bit ISA, 32 bit MCA/EISA/VLB/PCI, etc.)
|
||||
- The adapter must be designed to interface with and use features of
|
||||
available expansion spots in the host computer.
|
||||
|
||||
Controller Card vs Adapter
|
||||
- The expansion board that plugs into the PC is commonly referred to
|
||||
as a controller card, but for many drives (primarily IDE and SCSI)
|
||||
the controller mechanism is built directly onto the drive PCB and
|
||||
the expansion board in the PC (or built into motherboard) is
|
||||
actually a Host/Bus adapter.
|
||||
|
||||
TROUBLESHOOTING TIP - If the BIOS reports "HDD CONTROLLER FAILURE" don't
|
||||
assume the problem is with your AT/IO board. It might well be the drive
|
||||
PCB that has failed.
|
||||
|
||||
Controller/Drive Interface
|
||||
- Both drive and controller must communicate in the same 'language'
|
||||
and several different standards for electrical properties and
|
||||
logical meaning of signals have been established. These
|
||||
include ST506/412, ESDI, SCSI, IDE(ATA/XTA) and EIDE(ATA2).
|
||||
|
||||
Data Encoding Method
|
||||
- Determines how densely data can be packed onto a track. MFM
|
||||
encoding is sufficient for only 17 x 512 byte sectors per track.
|
||||
RLL permits up to 27 and variations of ARLL allow 34 or more
|
||||
sectors per track. This recording density is a major determinant
|
||||
of storage capacity, and with rotation speed and interleave are
|
||||
critical factors for true data transfer capability.
|
||||
|
||||
Support for Translation
|
||||
- Some controllers present different logical parameters to the PC
|
||||
than the actual physical geometry of the drive.
|
||||
|
||||
Need for ROM Extension or Software Device Driver
|
||||
- Additional program code is used to provide support for hard drives
|
||||
when none exists (as in PC/XTs), to implement translation schemes
|
||||
(as in ST506/RLL and ESDI designs), allow for non-standard devices
|
||||
or features (SCSI), or for a combination of these (EIDE).
|
||||
|
||||
|
||||
Below is a quick list of the major combinations that have been used in
|
||||
PCs past and present. While I am sure many others could be added, these
|
||||
are the ones I have come across over the years.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Computer Bus Connection Interface Encoding Translate ROM
|
||||
------------------------------------------------------------------------
|
||||
PC/XT 8 bit ISA Controller ST506/412 MFM NO YES
|
||||
PC/XT 8 bit ISA Controller ST506/412 RLL OPTION YES
|
||||
AT 16 bit ISA Controller ST506/412 MFM NO NO
|
||||
AT 16 bit MCA Controller ST506/412 MFM NO NO
|
||||
AT 16 bit ISA Controller ST506/412 RLL OPTION YES
|
||||
AT 16 bit MCA Controller ST506/412 RLL YES YES
|
||||
AT 16 bit ISA Controller * ESDI (10 Mbps) RLL OPTION YES
|
||||
AT 16 bit ISA Controller * ESDI (24 Mbps) ARLL OPTION YES
|
||||
AT 16 bit MCA Controller ** ESDI (PS/2) RLL,ARLL YES YES
|
||||
PC/XT 8 bit ISA Adapter SCSI RLL YES YES
|
||||
AT 16 bit ISA Adapter SCSI RLL,ARLL YES YES
|
||||
AT ?? bit MCA Adapter *** SCSI RLL,ARLL YES YES
|
||||
AT 32 bit EISA Adapter SCSI RLL,ARLL YES YES
|
||||
AT 32 bit VLB Adapter SCSI RLL,ARLL YES YES
|
||||
AT 32 bit PCI Adapter SCSI RLL,ARLL YES YES
|
||||
PC/XT 8 bit ISA Adapter IDE / XTA RLL OPTION YES
|
||||
AT 16 Bit ISA Adapter IDE / ATA RLL,ARLL OPTION NO
|
||||
AT 32 Bit VLB Adapter EIDE / ATA2 ARLL OPTION YES
|
||||
AT 32 Bit PCI Adapter EIDE / ATA2 ARLL OPTION YES
|
||||
|
||||
* ESDI drives have some of the controller logic built onto
|
||||
the hard drive PCB and some on the controller card.
|
||||
** PS/2 ESDI uses the same physical interface as other ESDI
|
||||
devices, but supports additional features specific to their
|
||||
implementation.
|
||||
*** 16 bit? 32 bit? Who knows? I have never been sure.
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Not to mention hundreds of other combinations to support different
|
||||
interleaves, track buffers, hardware caching, bus mastering, error
|
||||
correction schemes, SCSI I-II-III, optional floppy control, ESDI to SCSI
|
||||
converters, ST506 to SCSI converters (etc., etc., etc.).
|
||||
|
||||
So, what does all this mean to you?
|
||||
|
||||
Specifically, don't be surprised if the drive you have in your left
|
||||
hand, does not work correctly with the controller / adapter you have in
|
||||
your right hand. Also, if controllers are changed it may affect
|
||||
performance as well as the ability to access previously recorded data.
|
||||
|
||||
========================================================================
|
||||
END OF CHAPTER 2
|
||||
========================================================================
|
||||
|
||||
How to deal with some of this confusion will be addressed in
|
||||
CHAPTER 3 - Installing and Configuring Hard Drives.
|
||||
|
||||
========================================================================
|
||||
ADDITIONAL READING MATERIAL:
|
||||
========================================================================
|
||||
|
||||
I have always had difficulty finding appropriate reading material to
|
||||
recommend, but there are a few sources that I consider a must for
|
||||
technicians and support personnel.
|
||||
|
||||
First, a number of Internet Newsgroups have exceptional FAQ's
|
||||
(Frequently Asked Questions) which are updated and posted on a regular
|
||||
basis. These include:
|
||||
|
||||
"YET ANOTHER ATA-2/FAST-ATA/EIDE FAQ"
|
||||
by John Wehman and Peter Herweijer
|
||||
Newsgroup : comp.sys.ibm.hardware.storage
|
||||
|
||||
"BIOS TYPES"
|
||||
by Hale Landis
|
||||
Newsgroup : comp.sys.ibm.hardware.storage
|
||||
|
||||
"SCSI FAQ - 2 Parts"
|
||||
by Gary A. Field
|
||||
Newsgroup : comp.periphs.scsi
|
||||
|
||||
While bookstores are full of titles, most of them simply provide a
|
||||
rehash of basics. The following two books are an important part of my
|
||||
library because they cover much more than the usual:
|
||||
|
||||
"THE INDISPENSABLE PC HARDWARE BOOK" by Hans-Peter Messmer (1994)
|
||||
Addison-Wesley Publishing Company,
|
||||
ISBN - 0-201-62424-9
|
||||
|
||||
"THE UNDOCUMENTED PC" by Frank Van Gilluwe (1994)
|
||||
Addison-Wesley Publishing Company,
|
||||
ISBN - 0-201-62277-7
|
||||
|
||||
Other books well worth the read include:
|
||||
|
||||
"THE HARD DISK SURVIVAL GUIDE" by Mark Minasi (1991)
|
||||
Sybex Inc.,
|
||||
ISBN - 0-89588-799-1
|
||||
A little dated, but full of useful information. Hopefully there is a
|
||||
revised and updated version.
|
||||
|
||||
"OFFICIAL SPINRITE II AND HARD DISK COMPANION" by J. M. Goodman, (1990)
|
||||
IDG Books Worldwide, Inc.,
|
||||
ISBN - 878058-08-8
|
||||
Current advances are not covered, but great explanation of drive basics.
|
||||
|
||||
"HARD DRIVE BIBLE" by Martin Bodo (1993)
|
||||
Corporate Systems Center (CSC)
|
||||
My copy is the sixth edition from April, 1993. The first 50 pages of
|
||||
the book should be of interest (though not always clearly organized).
|
||||
The balance of the book (150 pages) is a listing of drive types and
|
||||
jumper settings. It's quite good, but keeping something like that
|
||||
updated is virtually impossible.
|
||||
|
||||
WARNING - DO NOT BUY - "The Data Recovery Bible" by Pamela Kane.
|
||||
Poorly organized material, most of which has nothing to do with data
|
||||
recovery. Waste of a good title if you ask me!
|
||||
|
||||
========================================================================
|
||||
ACRONYM DEFINITIONS:
|
||||
========================================================================
|
||||
|
||||
IRQ (Interrupt Request) - Lines on the bus used to signal hardware
|
||||
interrupts.
|
||||
|
||||
I/O (Input Output) - Peripherals accessible by the CPU through registers
|
||||
at specific I/O addresses (or I/O ports).
|
||||
|
||||
PIO (Programmed Input Output) - Exchange of data between memory and
|
||||
peripherals by means of Input Output commands.
|
||||
|
||||
DMA (Dynamic Memory Access) - Transferring data directly between memory
|
||||
and peripherals without going through the CPU.
|
||||
|
||||
BUS ARCHITECTURES:
|
||||
|
||||
ISA (Industry Standard Architecture) - 8 bit and 16 bit expansion slots
|
||||
used by PC, XT, and AT designs. Often called IBM Standard Architecture.
|
||||
|
||||
EISA (Extended Industry Standard Architecture) - Developed by several
|
||||
independent manufacturers (Compaq, AST, Zenith, Tandy, etc.) to
|
||||
standardize 32 bit operation and combat IBM's MCA.
|
||||
|
||||
MCA (Micro Channel Architecture) - Expansion bus introduced by IBM in
|
||||
1987, used by some (but not all) PS/2 models.
|
||||
|
||||
PCI (Peripheral Component Interconnect) - High speed bus developed by
|
||||
Intel to support the demands of Pentium and 486 based computers.
|
||||
|
||||
VLB (VESA Local Bus) - High speed, 32 bit extension to the ISA bus
|
||||
promoted by the VESA (Video Electronics Standards Association).
|
||||
|
||||
DRIVE INTERFACES:
|
||||
|
||||
ST506/412 - Standard interface used on XT and AT drives and controllers.
|
||||
Originally developed by Seagate Technologies to support their ST506
|
||||
(5 MB) and ST412 (10 MB) drives. The entire controller mechanism is
|
||||
located on a controller card and communications between the drive and
|
||||
controller flow over 2 ribbon cables - one for drive control and one for
|
||||
data.
|
||||
|
||||
ESDI (Enhanced Small Device Interface) - Developed by Maxtor in the
|
||||
early 1980's as an upgrade and improvement to the ST506 design. While
|
||||
the drive does not have an embedded controller, one of the most critical
|
||||
functions ,encoding-decoding, is performed on the drive. This allows
|
||||
for faster communications and higher drive capacities. Uses the same
|
||||
cabling as ST506 interface, but carries different signals on each line.
|
||||
|
||||
SCSI (Small Computer System Interface) - Based on an original design by
|
||||
Shugart Associates, SCSI is not specifically a drive interface, but a
|
||||
method of allowing different devices to communicate with a PC. For hard
|
||||
drives the entire controller is built onto the drive PCB, allowing for
|
||||
very high speed transfers to and from the drive. Fully interpreted,
|
||||
parallel data is then transferred to and from the PC by way of a single
|
||||
cable through a bus interface that has configured the device as a hard
|
||||
drive.
|
||||
|
||||
IDE (Integrated Drive Electronics) - A technology pioneered by Compaq
|
||||
and Conner that embedded a controller onto the hard disk PCB while
|
||||
maintaining compatibility with the register level commands sent by the
|
||||
computer's INT 13 routines. IDE drives are configured and appear to the
|
||||
computer like standard ST506 drives.
|
||||
|
||||
ATA (AT Attachment) - Implementation of the IDE design with a 16 bit AT
|
||||
style controller on board the drive.
|
||||
|
||||
XTA (XT Attachment) - Rarely used implementation of IDE with an
|
||||
integrated 8 bit XT controller.
|
||||
|
||||
ATA-2 - Enhancement to the AT Attachment standard to provide for
|
||||
considerable performance improvement and more sophisticated drive
|
||||
identification.
|
||||
|
||||
EIDE (Enhanced IDE) and FAST-ATA - Various implementations of the ATA-2
|
||||
standard as marketed by Western Digital (EIDE) and Seagate/Quantum
|
||||
(FAST-ATA).
|
||||
|
||||
DATA ENCODING SCHEMES
|
||||
|
||||
MFM (Modified Frequency Modulation) - Common technique used to encode
|
||||
the magnetic fluxes recorded on a drive into data. Still used on floppy
|
||||
drives and most original XT and AT systems. Notice that most drive
|
||||
types supported by the motherboard BIOS have 17 sectors per track. This
|
||||
is the standard density for MFM encoding.
|
||||
|
||||
RLL (Run Length Limited) - Encoding method that allows 50% more
|
||||
information to be recorded on a track than MFM. Accomplished by
|
||||
recording larger representations for every byte, but able to pack them
|
||||
more tightly onto the surface, because of fewer actual flux changes.
|
||||
Often called 2,7 RLL because the recording scheme involves patterns with
|
||||
no more than 7 successive zeros and no less than two.
|
||||
|
||||
ARLL (Advanced Run Length Limited) - More complex yet powerful
|
||||
derivatives of the RLL scheme. Include 1,7 and 3,9 encoding. Most
|
||||
every new drive made today uses some form of RLL or ARLL encoding.
|
||||
|
||||
========================================================================
|
||||
|
||||
|
||||
|
||||
200
study/sabre/os/files/Disk/HD_PORTS.asm
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
; Reading the harddisk using ports!
|
||||
; +-------------------------------+ by qark
|
||||
;
|
||||
;
|
||||
; This took me months to get working but I finally managed it.
|
||||
;
|
||||
; This code only works for the 286+ so you must detect for 8088's somewhere
|
||||
; in your code.
|
||||
;
|
||||
; Technical Information on the ports:
|
||||
; Port Read/Write Misc
|
||||
; ------ ------------ -------------------------------------------------
|
||||
; 1f0 r/w data register, the bytes are written/read here
|
||||
; 1f1 r error register (look these values up yourself)
|
||||
; 1f2 r/w sector count, how many sectors to read/write
|
||||
; 1f3 r/w sector number, the actual sector wanted
|
||||
; 1f4 r/w cylinder low, cylinders is 0-1024
|
||||
; 1f5 r/w cylinder high, this makes up the rest of the 1024
|
||||
; 1f6 r/w drive/head
|
||||
; bit 7 = 1
|
||||
; bit 6 = 0
|
||||
; bit 5 = 1
|
||||
; bit 4 = 0 drive 0 select
|
||||
; = 1 drive 1 select
|
||||
; bit 3-0 head select bits
|
||||
; 1f7 r status register
|
||||
; bit 7 = 1 controller is executing a command
|
||||
; bit 6 = 1 drive is ready
|
||||
; bit 5 = 1 write fault
|
||||
; bit 4 = 1 seek complete
|
||||
; bit 3 = 1 sector buffer requires servicing
|
||||
; bit 2 = 1 disk data read corrected
|
||||
; bit 1 = 1 index - set to 1 each revolution
|
||||
; bit 0 = 1 previous command ended in an error
|
||||
; 1f7 w command register
|
||||
; commands:
|
||||
; 50h format track
|
||||
; 20h read sectors with retry
|
||||
; 21h read sectors without retry
|
||||
; 22h read long with retry
|
||||
; 23h read long without retry
|
||||
; 30h write sectors with retry
|
||||
; 31h write sectors without retry
|
||||
; 32h write long with retry
|
||||
; 33h write long without retry
|
||||
;
|
||||
; Most of these should work on even non-IDE hard disks.
|
||||
; This code is for reading, the code for writing is the next article.
|
||||
|
||||
|
||||
|
||||
mov dx,1f6h ;Drive and head port
|
||||
mov al,0a0h ;Drive 0, head 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f2h ;Sector count port
|
||||
mov al,1 ;Read one sector
|
||||
out dx,al
|
||||
|
||||
mov dx,1f3h ;Sector number port
|
||||
mov al,1 ;Read sector one
|
||||
out dx,al
|
||||
|
||||
mov dx,1f4h ;Cylinder low port
|
||||
mov al,0 ;Cylinder 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f5h ;Cylinder high port
|
||||
mov al,0 ;The rest of the cylinder 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f7h ;Command port
|
||||
mov al,20h ;Read with retry.
|
||||
out dx,al
|
||||
still_going:
|
||||
in al,dx
|
||||
test al,8 ;This means the sector buffer requires
|
||||
;servicing.
|
||||
jz still_going ;Don't continue until the sector buffer
|
||||
;is ready.
|
||||
|
||||
mov cx,512/2 ;One sector /2
|
||||
mov di,offset buffer
|
||||
mov dx,1f0h ;Data port - data comes in and out of here.
|
||||
rep insw
|
||||
|
||||
; ------
|
||||
|
||||
mov ax,201h ;Read using int13h then compare buffers.
|
||||
mov dx,80h
|
||||
mov cx,1
|
||||
mov bx,offset buffer2
|
||||
int 13h
|
||||
|
||||
mov cx,512
|
||||
mov si,offset buffer
|
||||
mov di,offset buffer2
|
||||
repe cmpsb
|
||||
jne failure
|
||||
mov ah,9
|
||||
mov dx,offset readmsg
|
||||
int 21h
|
||||
jmp good_exit
|
||||
failure:
|
||||
mov ah,9
|
||||
mov dx,offset failmsg
|
||||
int 21h
|
||||
good_exit:
|
||||
mov ax,4c00h ;Exit the program
|
||||
int 21h
|
||||
|
||||
readmsg db 'The buffers match. Hard disk read using ports.$'
|
||||
failmsg db 'The buffers do not match.$'
|
||||
|
||||
buffer db 512 dup ('V')
|
||||
buffer2 db 512 dup ('L')
|
||||
|
||||
|
||||
|
||||
|
||||
;
|
||||
; Writing to the hard disk using the ports! by qark
|
||||
; +---------------------------------------+
|
||||
;
|
||||
; The only differences between reading and writing using the ports is
|
||||
; that 30h is sent to the command register, and instead of INSW you
|
||||
; OUTSW.
|
||||
;
|
||||
; I chose to write to sector 2 because some idiot would trash their MBR
|
||||
; by running this.
|
||||
;
|
||||
|
||||
mov dx,1f6h ;Drive and head port
|
||||
mov al,0a0h ;Drive 0, head 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f2h ;Sector count port
|
||||
mov al,1 ;Write one sector
|
||||
out dx,al
|
||||
|
||||
mov dx,1f3h ;Sector number port
|
||||
mov al,2 ;Wrote to sector two
|
||||
out dx,al
|
||||
|
||||
mov dx,1f4h ;Cylinder low port
|
||||
mov al,0 ;Cylinder 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f5h ;Cylinder high port
|
||||
mov al,0 ;The rest of the cylinder 0
|
||||
out dx,al
|
||||
|
||||
mov dx,1f7h ;Command port
|
||||
mov al,30h ;Write with retry.
|
||||
out dx,al
|
||||
oogle:
|
||||
in al,dx
|
||||
test al,8 ;Wait for sector buffer ready.
|
||||
jz oogle
|
||||
|
||||
mov cx,512/2 ;One sector /2
|
||||
mov si,offset buffer
|
||||
mov dx,1f0h ;Data port - data comes in and out of here.
|
||||
rep outsw ;Send it.
|
||||
|
||||
; ------------
|
||||
|
||||
mov ax,201h ;We'll read in sector 2 using
|
||||
mov bx,offset buffer2 ;int13h and see if we are successful.
|
||||
mov cx,2
|
||||
mov dx,80h
|
||||
int 13h
|
||||
|
||||
mov cx,512
|
||||
mov si,offset buffer
|
||||
mov di,offset buffer2
|
||||
repe cmpsb ;Compare the buffers.
|
||||
jne failure
|
||||
|
||||
mov ah,9
|
||||
mov dx,offset write_msg
|
||||
int 21h
|
||||
jmp w_exit
|
||||
failure:
|
||||
mov ah,9
|
||||
mov dx,offset fail
|
||||
int 21h
|
||||
|
||||
w_exit:
|
||||
mov ax,4c00h ;Exit the program
|
||||
int 21h
|
||||
|
||||
write_msg db 'Sector two written to using the ports.$'
|
||||
fail db 'Writing using ports failed.$'
|
||||
|
||||
buffer db 512 dup ('A')
|
||||
buffer2 db 512 dup ('D')
|
||||
|
||||
|
||||
1111
study/sabre/os/files/Disk/IDE-tech.html
Normal file
378
study/sabre/os/files/Disk/IDEHDC.asm
Normal file
@@ -0,0 +1,378 @@
|
||||
; ========================================================================== ;
|
||||
; IDEHDC.asm ;
|
||||
; Direct disk I/O module for IDE disk controllers. ;
|
||||
; Written by Alan Martin. ;
|
||||
; Note - this code doesn't use interrupts! ;
|
||||
; ========================================================================== ;
|
||||
idehdc segment use16 'CODE' ; Direct disk I/O code segment.
|
||||
; Initialize segment.
|
||||
assume cs:idehdc ; Initial segment assumptions.
|
||||
.386 ; Assume 386+ code is valid.
|
||||
|
||||
; Stack addressing equates.
|
||||
_ax equ word ptr bp+001Ch ; Saved AX value.
|
||||
_al equ byte ptr bp+001Ch ; Saved AL value.
|
||||
_ah equ byte ptr bp+001Dh ; Saved AH value.
|
||||
_bx equ word ptr bp+0010h ; Saved BX value.
|
||||
_bl equ byte ptr bp+0010h ; Saved BL value.
|
||||
_bh equ byte ptr bp+0011h ; Saved BH value.
|
||||
_cx equ word ptr bp+0018h ; Saved CX value.
|
||||
_cl equ byte ptr bp+0018h ; Saved CL value.
|
||||
_ch equ byte ptr bp+0019h ; Saved CH value.
|
||||
_dx equ word ptr bp+0014h ; Saved DX value.
|
||||
_dl equ byte ptr bp+0014h ; Saved DL value.
|
||||
_dh equ byte ptr bp+0015h ; Saved DH value.
|
||||
|
||||
delay macro x ; Long delay (for 400ns transition).
|
||||
local @loop ; Local labels.
|
||||
push cx ; Save CX.
|
||||
mov cx,x ; Get repeat count.
|
||||
@loop: loop @loop ; Loop X times.
|
||||
pop cx ; Restore CX.
|
||||
endm ; End of DELAY macro.
|
||||
|
||||
hdcwait macro ; Wait for HDC to finish commands.
|
||||
local @loop,@ok,@err ; Local labels.
|
||||
push ax ecx dx ; Save registers.
|
||||
mov ecx,00040000h ; 1s delay on 486DX-50.
|
||||
mov dx,01F7h ; HDC status register.
|
||||
in al,dx ; Read status.
|
||||
test al,80h ; Is the HDC busy?
|
||||
jz @ok ; If not, end immediately.
|
||||
@loop: in al,dx ; Read status.
|
||||
delay 000Ah ; 50-100 clock delay.
|
||||
test al,80h ; Is the HDC busy?
|
||||
jz @ok ; If not, end loop.
|
||||
loopd @loop ; Otherwise, continue.
|
||||
pop dx ecx ax ; Restore registers.
|
||||
stc ; Set CF.
|
||||
jmp @err ; Exit with error.
|
||||
@ok: pop dx ecx ax ; Restore registers.
|
||||
clc ; Clear CF.
|
||||
@err:
|
||||
endm ; End of HDCWAIT macro.
|
||||
|
||||
; ------------------------------------------ ;
|
||||
; IOREAD - Read sectors through direct I/O. ;
|
||||
; Input.: AX=cylinder number ;
|
||||
; BH=head number; BL=sector number ;
|
||||
; CH=# of sectors; CL=drive (0 or 1) ;
|
||||
; DS:DX->buffer for sectors ;
|
||||
; Output: CF=0 (OK) or 1 (Error) ;
|
||||
; AL=error code or 0 if no error. ;
|
||||
; AH=device error code if applicable.;
|
||||
; Errors: AL=0 - No error. ;
|
||||
; 1 - Controller busy or absent. ;
|
||||
; 2 - Drive not ready. ;
|
||||
; 3 - Drive not ready for read. ;
|
||||
; 4 - Device error: ;
|
||||
; AH, bit 0: Address mark not found. ;
|
||||
; 1: Track 0 not found. ;
|
||||
; 2: Write fault. ;
|
||||
; 4: Sector not found. ;
|
||||
; 6: Error in data. ;
|
||||
; 7: Sector marked bad. ;
|
||||
; Note: There may be errors if a read is ;
|
||||
; across a cylinder (or sometimes even ;
|
||||
; a head) boundary. ;
|
||||
; ------------------------------------------ ;
|
||||
ioread proc far ; Read sectors through direct I/O.
|
||||
pushad ; Save all registers.
|
||||
mov bp,sp ; Address the stack.
|
||||
push ds es ; Save segments.
|
||||
in al,0A1h ; Get PIC 2 mask.
|
||||
push ax ; Save it.
|
||||
or al,40h ; Disable IRQ 14.
|
||||
out 0A1h,al ; Set PIC 2 mask.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc ir_ok0 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp ir_err ; ...done.
|
||||
ir_ok0:mov al,[_bh] ; Get head number.
|
||||
mov ah,[_cl] ; Get drive number.
|
||||
and ax,010Fh ; Mask out extra bits.
|
||||
shl ah,04h ; Adjust AH.
|
||||
or al,ah ; Combine data.
|
||||
or al,0A0h ; Set 512 bytes + ECC.
|
||||
mov dx,01F6h ; Write drive/head numbers...
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc ir_ok1 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp ir_err ; ...done.
|
||||
ir_ok1:mov ecx,000C0000h ; 3s delay.
|
||||
mov dx,01F7h ; HDC status register.
|
||||
ir_l1: in al,dx ; Read status.
|
||||
test al,40h ; Drive ready?
|
||||
jnz ir_ok2 ; Continue if so.
|
||||
loopd ir_l1 ; Loop for 3s.
|
||||
mov al,02h ; Error 2: Drive not ready...
|
||||
mov [_al],al ; .
|
||||
jmp ir_err ; ...done.
|
||||
ir_ok2:test al,10h ; Drive ready for read?
|
||||
jnz ir_ok3 ; Continue if so.
|
||||
loopd ir_l1 ; Loop for 3s.
|
||||
mov al,03h ; Error 3: Cannot read data...
|
||||
mov [_al],al ; .
|
||||
jmp ir_err ; ...done.
|
||||
ir_ok3:mov al,10h ; Set to >8 heads...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
mov dx,01F2h ; Write read parameters...
|
||||
mov al,[_ch] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_bl] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_al] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_ah] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_bh] ; .
|
||||
mov ah,[_cl] ; .
|
||||
and ax,010Fh ; .
|
||||
shl ah,04h ; .
|
||||
or al,ah ; .
|
||||
or al,0A0h ; .
|
||||
out dx,al ; ...done.
|
||||
mov dx,01F1h ; Write Precompensation = 0...
|
||||
xor al,al ; .
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc ir_ok4 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp ir_err ; ...done.
|
||||
ir_ok4:xor cx,cx ; Get sector count...
|
||||
mov cl,[_ch] ; ...done.
|
||||
push ds ; Put DS in ES...
|
||||
pop es ; ...done.
|
||||
mov di,[_dx] ; Get offset.
|
||||
mov dx,01F7h ; Send read command...
|
||||
mov al,20h ; .
|
||||
out dx,al ; ...done.
|
||||
ir_l2: mov dx,01F7h ; Get status port.
|
||||
delay 000Ah ; Delay for >400ns.
|
||||
in al,dx ; Get status.
|
||||
test al,80h ; Busy?
|
||||
jnz ir_l2 ; Loop if so.
|
||||
test al,29h ; Loop if no change...
|
||||
jz ir_l2 ; ...done.
|
||||
test al,08h ; Ready for data?
|
||||
jnz ir_rda ; If so, read it.
|
||||
test al,21h ; Error in command?
|
||||
jnz ir_dev ; If so, return device error.
|
||||
jmp ir_l2 ; Continue loop.
|
||||
ir_rda:push cx ; Save CX.
|
||||
mov cx,0100h ; Repeat count.
|
||||
mov dx,01F0h ; 16-bit transfer port.
|
||||
rep insw ; Read data.
|
||||
pop cx ; Restore CX.
|
||||
loop ir_l2 ; Loop until done.
|
||||
mov al,12h ; Deactivate controller...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
mov al,00h ; No error - return 0...
|
||||
mov [_al],al ; ...done.
|
||||
pop ax ; Reset PIC 2 mask...
|
||||
out 0A1h,al ; ...done.
|
||||
clc ; No error: CF=0.
|
||||
pop es ds ; Restore segments.
|
||||
popad ; Restore all registers.
|
||||
ret ; Return (far).
|
||||
ir_dev:mov al,04h ; Error 4: Device fault...
|
||||
mov [_al],al ; ...done.
|
||||
mov dx,01F1h ; Get error code...
|
||||
in al,dx ; .
|
||||
mov [_ah],al ; ...done.
|
||||
mov dx,01F6h ; Recalibrate head...
|
||||
mov al,[_bh] ; .
|
||||
mov ah,[_cl] ; .
|
||||
and ax,010Fh ; .
|
||||
shl ah,04h ; .
|
||||
or al,ah ; .
|
||||
or al,0A0h ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,10h ; .
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
mov al,12h ; Deactivate controller...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
ir_err:pop ax ; Reset PIC 2 mask...
|
||||
out 0A1h,al ; ...done.
|
||||
stc ; Error: CF=1.
|
||||
pop es ds ; Restore segments.
|
||||
popad ; Restore all registers.
|
||||
ret ; Return (far).
|
||||
ioread endp ; End of IOREAD procedure.
|
||||
|
||||
; ------------------------------------------ ;
|
||||
; IOWRITE - Write sectors through direct I/O.;
|
||||
; Input.: AX=cylinder number ;
|
||||
; BH=head number; BL=sector number ;
|
||||
; CH=# of sectors; CL=drive (0 or 1) ;
|
||||
; DS:DX->buffer for sectors ;
|
||||
; Output: CF=0 (OK) or 1 (Error) ;
|
||||
; AL=error code or 0 if no error. ;
|
||||
; AH=device error code if applicable.;
|
||||
; Errors: AL=0 - No error. ;
|
||||
; 1 - Controller busy or absent. ;
|
||||
; 2 - Drive not ready. ;
|
||||
; 3 - Drive not ready for write. ;
|
||||
; 4 - Device error: ;
|
||||
; AH, bit 0: Address mark not found. ;
|
||||
; 1: Track 0 not found. ;
|
||||
; 2: Write fault. ;
|
||||
; 4: Sector not found. ;
|
||||
; 6: Error in data. ;
|
||||
; 7: Sector marked bad. ;
|
||||
; Note: There may be errors if a write is ;
|
||||
; across a cylinder (or sometimes even ;
|
||||
; a head) boundary. ;
|
||||
; ------------------------------------------ ;
|
||||
iowrite proc far ; Write sectors through direct I/O.
|
||||
pushad ; Save all registers.
|
||||
mov bp,sp ; Address the stack.
|
||||
push ds es ; Save segments.
|
||||
in al,0A1h ; Get PIC 2 mask.
|
||||
push ax ; Save it.
|
||||
or al,40h ; Disable IRQ 14.
|
||||
out 0A1h,al ; Set PIC 2 mask.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc iw_ok0 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp iw_err ; ...done.
|
||||
iw_ok0:mov al,[_bh] ; Get head number.
|
||||
mov ah,[_cl] ; Get drive number.
|
||||
and ax,010Fh ; Mask out extra bits.
|
||||
shl ah,04h ; Adjust AH.
|
||||
or al,ah ; Combine data.
|
||||
or al,0A0h ; Set 512 bytes + ECC.
|
||||
mov dx,01F6h ; Write drive/head numbers...
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc iw_ok1 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp iw_err ; ...done.
|
||||
iw_ok1:mov ecx,000C0000h ; 3s delay.
|
||||
mov dx,01F7h ; HDC status register.
|
||||
iw_l1: in al,dx ; Read status.
|
||||
test al,40h ; Drive ready?
|
||||
jnz iw_ok2 ; Continue if so.
|
||||
loopd iw_l1 ; Loop for 3s.
|
||||
mov al,02h ; Error 2: Drive not ready...
|
||||
mov [_al],al ; .
|
||||
jmp iw_err ; ...done.
|
||||
iw_ok2:test al,10h ; Drive ready for write?
|
||||
jnz iw_ok3 ; Continue if so.
|
||||
loopd iw_l1 ; Loop for 3s.
|
||||
mov al,03h ; Error 3: Cannot write...
|
||||
mov [_al],al ; .
|
||||
jmp iw_err ; ...done.
|
||||
iw_ok3:mov al,10h ; Set to >8 heads...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
mov dx,01F2h ; Write write parameters...
|
||||
mov al,[_ch] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_bl] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_al] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_ah] ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,[_bh] ; .
|
||||
mov ah,[_cl] ; .
|
||||
and ax,010Fh ; .
|
||||
shl ah,04h ; .
|
||||
or al,ah ; .
|
||||
or al,0A0h ; .
|
||||
out dx,al ; ...done.
|
||||
mov dx,01F1h ; Write Precompensation = 0...
|
||||
xor al,al ; .
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
jnc iw_ok4 ; Continue if not busy.
|
||||
mov al,01h ; Error 1: Controller busy...
|
||||
mov [_al],al ; .
|
||||
jmp iw_err ; ...done.
|
||||
iw_ok4:xor cx,cx ; Get sector count...
|
||||
mov cl,[_ch] ; ...done.
|
||||
mov si,[_dx] ; Get offset.
|
||||
mov dx,01F7h ; Send write command...
|
||||
mov al,30h ; .
|
||||
out dx,al ; ...done.
|
||||
iw_l2: mov dx,01F7h ; Get status port.
|
||||
delay 000Ah ; Delay for >400ns.
|
||||
in al,dx ; Get status.
|
||||
test al,80h ; Busy?
|
||||
jnz iw_l2 ; Loop if so.
|
||||
test al,29h ; Loop if no change...
|
||||
jz iw_l2 ; ...done.
|
||||
test al,08h ; Ready for data?
|
||||
jnz iw_wda ; If so, write it.
|
||||
test al,21h ; Error in command?
|
||||
jnz iw_dev ; If so, return device error.
|
||||
jmp iw_l2 ; Continue loop.
|
||||
iw_wda:push cx ; Save CX.
|
||||
mov cx,0100h ; Repeat count.
|
||||
mov dx,01F0h ; 16-bit transfer port.
|
||||
rep outsw ; Write data.
|
||||
pop cx ; Restore CX.
|
||||
loop iw_l2 ; Loop until done.
|
||||
mov al,12h ; Deactivate controller...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
mov al,00h ; No error - return 0...
|
||||
mov [_al],al ; ...done.
|
||||
pop ax ; Reset PIC 2 mask...
|
||||
out 0A1h,al ; ...done.
|
||||
clc ; No error: CF=0.
|
||||
pop es ds ; Restore segments.
|
||||
popad ; Restore all registers.
|
||||
ret ; Return (far).
|
||||
iw_dev:mov al,04h ; Error 4: Device fault...
|
||||
mov [_al],al ; ...done.
|
||||
mov dx,01F1h ; Get error code...
|
||||
in al,dx ; .
|
||||
mov [_ah],al ; ...done.
|
||||
mov dx,01F6h ; Recalibrate head...
|
||||
mov al,[_bh] ; .
|
||||
mov ah,[_cl] ; .
|
||||
and ax,010Fh ; .
|
||||
shl ah,04h ; .
|
||||
or al,ah ; .
|
||||
or al,0A0h ; .
|
||||
out dx,al ; .
|
||||
inc dx ; .
|
||||
mov al,10h ; .
|
||||
out dx,al ; ...done.
|
||||
hdcwait ; Wait for HDC not busy.
|
||||
mov al,12h ; Deactivate controller...
|
||||
mov dx,03F6h ; .
|
||||
out dx,ax ; ...done.
|
||||
iw_err:pop ax ; Reset PIC 2 mask...
|
||||
out 0A1h,al ; ...done.
|
||||
stc ; Error: CF=1.
|
||||
pop es ds ; Restore segments.
|
||||
popad ; Restore all registers.
|
||||
ret ; Return (far).
|
||||
iowrite endp ; End of IOWRITE procedure.
|
||||
|
||||
; Clean up segment.
|
||||
assume nothing ; Remove segment assumptions.
|
||||
idehdc ends ; End of direct I/O segment.
|
||||
; ========================================================================== ;
|
||||
BIN
study/sabre/os/files/Disk/IDEInterrogate.zip
Normal file
2767
study/sabre/os/files/Disk/MSCDEX21.txt
Normal file
@@ -0,0 +1,112 @@
|
||||
<STYLE MEDIA="screen">
|
||||
#bodytext { font-family: Verdana, Arial, Helvetica;font-size: 9pt; line-height: 125%;}
|
||||
</STYLE>
|
||||
<STYLE MEDIA="print">
|
||||
#bodytext {display: all; margin-left: 90px; margin-right: 20px; font-family: Times; font-size: 11pt; line-height: 112%;}
|
||||
</STYLE>
|
||||
|
||||
<FONT FACE="Verdana, Arial, Helvetica" SIZE=1><blockquote><div id="bodytext">
|
||||
<!-- XXXXXXXXXXXXXXXXX PAGE TITLE: XXXXXXXXXXXXXXXXXXXXX -->
|
||||
<h3 class=main>Media Status Notification Support Specification for SCSI and ATAPI Devices, Version 0.1</h3>
|
||||
<!-- XXXXXXXXXXXXXXXXX START TOC: XXXXXXXXXXXXXXXXXXXXXX -->
|
||||
<DL class=contents>
|
||||
<DT class=contents><B>Contents:</B></DT>
|
||||
<DD class=contents><a class=contents href="#Introduction">Introduction</a></DD>
|
||||
<DD class=contents><a class=contents href="#Enabling">Enabling and Disabling Media Status Notification Support</a></DD>
|
||||
<DD class=contents><a class=contents href="#Returning">Returning Media Status</a></DD>
|
||||
<DD class=contents><a class=contents href="#Reporting">Reporting Media Status Changes</a></DD>
|
||||
<DD class=contents><a class=contents href="#SCSI">SCSI Compatibility Considerations</a></DD>
|
||||
</DL>
|
||||
<!-- XXXXXXXXXXXXXXX START CONTENT: XXXXXXXXXXXXXXXXXXXX -->
|
||||
<h3><A NAME="Introduction"></A>Introduction</h3>
|
||||
|
||||
<P>A major shortcoming of removable media devices on PC platforms is their inability to report to the host when the user attempts to eject the medium. Currently most removable media devices just eject the medium when the user presses the Eject button, and potentially any data the operating system has not saved to the device is lost. Various volume tracking and locking schemes reduce this risk, but do not eliminate it. Ideally, devices will have a means of communicating to the host that the user wants to eject the medium or has inserted a new medium.</P>
|
||||
|
||||
<P>This specification defines a protocol for providing this function for SCSI ATA and ATAPI devices. The support is enabled using a new SCSI command, ENABLE MEDIA STATUS, and the media status is retrieved using a new SCSI ATA command, GET MEDIA STATUS. </P>
|
||||
|
||||
<P>Because it is difficult for a SCSI target to asynchronously interrupt the host due to lack of industry support for Asynchronous Event Notification, the GET MEDIA STATUS command is not completed by the target until a media status change occurs. If tagged command queuing is not supported by the target and/or the host, a means of polling the target for status changes is also specified.
|
||||
Note that in some controllers the unused words in the ID Drive data are returned as 0FFFFh. Thus it may be better if the Status Notification support was returned as a 2 bit field, where 00b, 11b are both defined as drive not supporting Status notification.</P>
|
||||
|
||||
<h3><A NAME="Enabling"></A>Enabling and Disabling Media Status Notification Support</h3>
|
||||
|
||||
<P>To maintain compatibility with existing BIOS implementations and operating systems, the target must assume that the host does shall not enableimplement Media Status Notification support until the ENABLE MEDIA STATUS command is issued by the host, as described in this section.</P>
|
||||
|
||||
<P>When the host enables the support using the ENABLE MEDIA STATUS command, the target shallmust respond as described in this specification. When the host disables this featuresupport, the target must default to normal operating modes. A SCSI bus reset, bus device reset or power on condition must also cause the target to return to normal operating modes.</P>
|
||||
|
||||
<P><b>ENABLE MEDIA STATUS Command</b></P>
|
||||
|
||||
<P>The ENABLE MEDIA STATUS command requests that the SCSI Target enable or disable Media Status Notification. If Media Status Notification is not supported, the target shall return CHECK CONDITION (Sense Key 05 ILLEGAL REQUEST, Sense Code 24 INVALID FIELD IN COMMAND PACKET).
|
||||
</P>
|
||||
<P>
|
||||
<img src="scsienbl.gif" width=573 height=260 border=0></P>
|
||||
|
||||
<P>An Enable bit of one indicates that the target shall enable Media Status Notification. If the target currently has Media Status Notification enabled, the target shall return CHECK CONDITION (Sense Key 05 ILLEGAL REQUEST, Sense Code 4E OVERLAPPED COMMANDS ATTEMPTED).</P>
|
||||
|
||||
<P>An Enable bit of zero indicates that the target shall disable Media Status Notification.</P>
|
||||
|
||||
<h3><A NAME="Returning"></A>Returning Media Status</h3>
|
||||
|
||||
<P>The media status information is returned when the host issues the GET MEDIA STATUS command described below.</P>
|
||||
|
||||
<P><b>GET MEDIA STATUS Command</b></P>
|
||||
|
||||
<P>The ENABLE MEDIA STATUS command requests that the SCSI Target report media status changes. If Media Status Notification is not supported or not enabled, the target shall return CHECK CONDITION (Sense Key 05 ILLEGAL REQUEST, Sense Code 24 INVALID FILED IN COMMAND PACKET).</P>
|
||||
|
||||
<P>
|
||||
<img src="scsigetm.gif" width=572 height=260 border=0></P>
|
||||
|
||||
<P>This command has two modes of operation. If the Immed bit is set to one, and if the state of the target is normal (that is, medium not inserted, Eject button not pushed), the GET MEDIA STATUS command shall return good status. If the state of the target has changed, a CHECK CONDITION command shall be returned, and the subsequent REQUEST SENSE command shall return the appropriate keys as defined in the Reporting Media Status Changes section below.</P>
|
||||
|
||||
<P>If the Immed bit is set to zero (and the target supports tagged command queuing) and if the state of the target is normal (that is, medium in the target, medium not changed, Eject button not pushed), the GET MEDIA STATUS command shall be queued by the target until the status of the medium changes, or some error condition occurs. If the state of the target has changed, a CHECK CONDITION command shall be returned, and the subsequent REQUEST SENSE command shall return the appropriate keys as defined in the Reporting Media Status Changes section below.</P>
|
||||
|
||||
<P>If the Immed bit is set to zero and the target DOES NOT support tagged command queuing, the target shall return CHECK CONDITION (Sense Key 05 ILLEGAL REQUEST, Sense Code 24 INVALID FIELD IN COMMAND PACKET).</P>
|
||||
|
||||
<h3><A NAME="Reporting"></A>Reporting Media Status Changes</h3>
|
||||
|
||||
<P>When a media status change has been detected, the GET MEDIA STATUS command shall return CHECK CONDITION. The target shall return the following sense data:</P>
|
||||
|
||||
<P>Sense Key 06 (UNIT ATTENTION)</P>
|
||||
|
||||
<P>Sense Code E0 (MEDIA STATUS CHANGE)</P>
|
||||
|
||||
<P>Additional Sense Code Qualifier:</P>
|
||||
|
||||
<P><b>00 - EJREQ </b></P>
|
||||
|
||||
<P>This Qualifier indicates that the user has attempted to eject the medium. Usually this Qualifier will be set when the user presses the Eject button on the target. If theThe target is capable of preventing removal of the media, the target shallmust not allow the medium to be ejected until an EJECT command is received from the host. This Qualifier shallmust not be set again in response to the GET MEDIA STATUS command until the user subsequently releases the button and presses it again.</P>
|
||||
<P><b>01 - NEWMED</b></P>
|
||||
<P>This Qualifier indicates that a medium has been newly inserted in the target. The Qualifier must not be set for more than one invocation of the GET MEDIA STATUS command, until the user removes or reinserts the medium. In other words, when the user inserts a new medium in the target, and a GET MEDIA STATUS command is issued, the target will set this Qualifier. The next GET MEDIA STATUS command must not result in this Qualifier being set again unless the medium has been removed and reinserted.</P>
|
||||
<P>All other Qualifiers are reserved.</P>
|
||||
|
||||
<h3><A NAME="SCSI"></A>SCSI Compatibility Considerations</h3>
|
||||
|
||||
<P>SCSI commands must be processed exactly the same as they would be if Media Status Notification was not enabled. When the GET MEDIA STATUS command is received by the SCSI target, the status changed error codes must be reported as described in "Returning Media Status" earlier in this specification. However, the state of the bits must not be cleared by any other SCSI command. The insertion of a new medium must be reported independently with both the GET MEDIA STATUS and other SCSI commands. For example, if the user inserts a new medium and the target is accessed with an SCSI command, the CHECK CONDITION with UNIT ATTENTION must be reported, but the target must also report the NEMED error when it receives the next GET MEDIA STATUS command. The behavior must be the same if, after the medium is inserted, the GET MEDIA STATUS command is received before the next SCSI command.</P>
|
||||
<P>When the user presses the Eject button on the target, the SCSI commands must not be affected, but the EJREQ status must be reported when the first GET MEDIA STATUS command is received after the button is pressed, (it is reported only once after each button press). The SCSI target must continue to operate as normal. If the host determines that it is safe to eject the medium, an SCSI EJECT command shall be issued to the target by the host, at which time the target shall eject the medium.</P>
|
||||
|
||||
<P><TABLE WIDTH=78% BORDER=1 CELLPADDING=5 CELLSPACING=0>
|
||||
<TR VALIGN=TOP BGCOLOR="#80AADD">
|
||||
<TD colspan=3><FONT FACE="Arial" SIZE=2><B>Revision Record</B></FONT></TD></TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD><FONT FACE="Arial" SIZE=2><b>Edition</b></FONT></TD>
|
||||
<TD><FONT FACE="Arial" SIZE=2>Date Published</FONT></TD>
|
||||
<TD><FONT FACE="Arial" SIZE=2>Revised Comments</FONT></TD></TR>
|
||||
<TR VALIGN=TOP>
|
||||
<TD><FONT FACE="Arial" SIZE=2>0.1</FONT></TD>
|
||||
<TD><FONT FACE="Arial" SIZE=2>March 1996</FONT></TD>
|
||||
<TD><FONT FACE="Arial" SIZE=2>First Draft Version</FONT></TD></TR>
|
||||
</TABLE></P>
|
||||
<P>Send comments to <A HREF="mailto:billpa@microsoft.com">billpa@microsoft.com</A>.</P>
|
||||
|
||||
|
||||
<!-- XXXXXXXXXXXXXXXX END CONTENT XXXXXXXXXXXXXXXXXXXXXX -->
|
||||
</div></blockquote></font>
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH=92% BORDER=0>
|
||||
<TR><TD WIDTH=60></TD><TD></TD></TR><TR><TD></TD><TD valign=top>
|
||||
<hr size="1" color="#441100" noshade WIDTH="100%">
|
||||
<FONT FACE="Verdana, Arial, Helvetica" SIZE=1><p>
|
||||
<!-- ENTER CHANGE OF DATE -->
|
||||
<q class=date>File Date: July 7, 1998<br>
|
||||
<!--COPYRIGHT STATEMENT--><A STYLE="color:#001144" STYLE="text-decoration:underline;" HREF="/misc/cpyright.htm">© 1999 Microsoft Corporation. All rights reserved. Terms of Use.</A></q><BR></FONT>
|
||||
<!--COPYRIGHT STATEMENT END--></TD></TR></table>
|
||||
</BODY>
|
||||
</HTML>
|
||||
1028
study/sabre/os/files/Disk/SecureDeletion.html
Normal file
712
study/sabre/os/files/Disk/cdromfaq.txt
Normal file
@@ -0,0 +1,712 @@
|
||||
From marcj@nando.net Wed Mar 1 17:51:03 1995
|
||||
From: marcj@nando.net (MarcJ)
|
||||
Newsgroups: comp.os.msdos.programmer
|
||||
Subject: CD-ROM FAQ
|
||||
Date: 19 Feb 1995 23:18:50 -0500
|
||||
Organization: NandO -- The News & Observer online service
|
||||
NNTP-Posting-Host: parsifal.nando.net
|
||||
|
||||
In recognition of a number of questions I've seen recently asking
|
||||
questions on programming CD-ROMs...
|
||||
|
||||
CD-ROM programming FAQ Version 1.00
|
||||
|
||||
Copyright (C) 1995 by Marcus W. Johnson. All rights reserved. This
|
||||
article is not in the public domain, but it may be redistributed so
|
||||
long as this notice, the acknowledgments, and the information on
|
||||
obtaining the latest copy of this list are retained and no fee is
|
||||
charged. The code fragments may be used freely; credit would be
|
||||
polite.
|
||||
|
||||
------- Table of Contents --------------------------------------------
|
||||
|
||||
Section 0 - Availability
|
||||
0.01. How can I get the latest copy of this FAQ?
|
||||
Section 1 - MSCDEX Status
|
||||
1.01. How do I know if MSCDEX is installed?
|
||||
1.02. How do I determine the MSCDEX version?
|
||||
Section 2 - CD-ROM Existence
|
||||
2.01. How many CD-ROMs are present?
|
||||
2.02. Which drives are CD-ROMs?
|
||||
2.03. How do I get the name of the CD-ROM device driver?
|
||||
Section 3 - Drive Interface
|
||||
3.01. How do I open the door?
|
||||
3.02. How do I close the door?
|
||||
3.03. How do I unlock the door?
|
||||
3.04. How do I lock the door?
|
||||
3.05. How do I reset the drive?
|
||||
3.06. How do I get drive status?
|
||||
Section 4 - Drive Capacity
|
||||
4.01. What sector size is supported?
|
||||
4.02. How many sectors are on the disk?
|
||||
4.03. How much data is on the disk?
|
||||
Section 5 - Volume Table of Contents
|
||||
5.01. How do I get the abstract file name?
|
||||
5.02. How do I get the bibliography file name?
|
||||
5.03. How do I get the copyright file name?
|
||||
5.04. How do I read the Volume Table of Contents (VTOC)?
|
||||
Section 6 - Audio
|
||||
6.01. How do I find out how many tracks are on a CD?
|
||||
6.02. What are Red Book and HSG formats?
|
||||
6.03. How can I determine where a particular track starts?
|
||||
6.04. How do I play audio?
|
||||
6.05. How do I pause audio playback?
|
||||
6.06. How do I resume audio playback?
|
||||
|
||||
======================================================================
|
||||
Section 0 - Administration
|
||||
----------------------------------------------------------------------
|
||||
0.01. How can I get the latest copy of this FAQ?
|
||||
|
||||
The FAQ is published monthly in comp.os.msdos.programming and
|
||||
alt.msdos.programmer.
|
||||
----------------------------------------------------------------------
|
||||
0.02. Where did this information come from?
|
||||
|
||||
Ralf Brown's interrupt list
|
||||
"MS-DOS Extensions", by Ray Duncan, Microsoft Press
|
||||
My personal research for "PC-Programmer's Guide to Low-Level
|
||||
Functions and Interrupts", Sams
|
||||
The mention of particular books or programs must not be construed
|
||||
to reflect unfavorably on any that are not mentioned.
|
||||
----------------------------------------------------------------------
|
||||
0.03. How accurate is this information?
|
||||
|
||||
I have personally tested the code fragments in this FAQ, and
|
||||
they appear to work as advertised, but there is no warranty on
|
||||
the code or on the techniques described in this article.
|
||||
As testing may not have been perfect, and machines and
|
||||
configurations vary, it is possible that the fragments will not
|
||||
work for you.
|
||||
Please send corrections to marcj@nando.net.
|
||||
======================================================================
|
||||
Section 1 - MSCDEX Status
|
||||
======================================================================
|
||||
1.01. How do I know if MSCDEX is installed?
|
||||
|
||||
Call the MSCDEX installation check function. Here's code that
|
||||
performs the check:
|
||||
|
||||
mov AX,0DADAH
|
||||
push AX
|
||||
mov AX,01100H
|
||||
int 2FH
|
||||
pop BX
|
||||
cmp BX,0ADADH
|
||||
jne not_installed
|
||||
cmp AL,0FFH
|
||||
jne not_installed
|
||||
;
|
||||
; MSCDEX is installed
|
||||
;
|
||||
----------------------------------------------------------------------
|
||||
1.02. How do I determine the MSCDEX version?
|
||||
|
||||
Call the MSCDEX version check function. Here's code that gets
|
||||
the version:
|
||||
|
||||
mov AX,150CH
|
||||
int 2FH
|
||||
;
|
||||
; BH holds the major version
|
||||
; BL holds the minor version
|
||||
; Prior to MSCDEX version 2.0, the version returned is 0.0 (BX =
|
||||
; 0)
|
||||
;
|
||||
======================================================================
|
||||
Section 2 - CD-ROM Existence
|
||||
======================================================================
|
||||
2.01. How many CD-ROMs are present?
|
||||
|
||||
Ask MSCDEX. Here's code that gives the count of CD-ROMs
|
||||
installed and the drive letter of the first one:
|
||||
|
||||
mov AX,1500H
|
||||
xor BX,BX
|
||||
int 2FH
|
||||
;
|
||||
; BX will hold the number of CD-ROMs
|
||||
; CL will hold the first CD-ROM's drive; 0 = A:, 1 = B:, and so
|
||||
; on
|
||||
;
|
||||
|
||||
A problem with this method, BTW, is that it conflicts with DOS
|
||||
4.0's GRAPHICS.COM.
|
||||
----------------------------------------------------------------------
|
||||
2.02. Which drives are CD-ROMs?
|
||||
|
||||
There are two ways to find out. Both ways require MSCDEX version
|
||||
2 (see question 1.02, How do I determine the MSCDEX version?).
|
||||
The first way gives a list of all CD-ROM drives; the second
|
||||
verifies whether a specific drive is a CD-ROM.
|
||||
|
||||
Method 1: (get list of CD-ROMs)
|
||||
This method requires a block of memory; the size, in bytes, must
|
||||
be at least the number of drives returned by function 1500H (see
|
||||
question 2.01, How many CD-ROMs are present?).
|
||||
|
||||
mov AX,150DH
|
||||
les BX,LetterArray
|
||||
int 2FH
|
||||
;
|
||||
; each byte in LetterArray will contain a drive value (0 = A:, 1
|
||||
; = B:, etc.)
|
||||
;
|
||||
|
||||
Method 2: (is a specified drive a CD-ROM?)
|
||||
|
||||
mov AX,150BH
|
||||
mov CX,Drive ; 0 = A:, 1 = B:, and so on
|
||||
int 2FH
|
||||
or AX,AX
|
||||
jz not_cd_rom
|
||||
cmp BX,0ADADH
|
||||
jne not_cd_rom
|
||||
;
|
||||
; the drive is a CD-ROM
|
||||
;
|
||||
----------------------------------------------------------------------
|
||||
2.03. How do I get the name of the CD-ROM device driver?
|
||||
|
||||
First, you need to know how many CD-ROMs you have (see question
|
||||
2.01, How many CD-ROMs are present?). You need a block of memory
|
||||
whose size, in bytes, is 5 times the number of CD-ROMs present.
|
||||
This code will fill that array:
|
||||
|
||||
mov AX,1501H
|
||||
les BX,DriverArray
|
||||
int 2FH
|
||||
|
||||
Each 5-byte element in the array consists of the drive's subunit
|
||||
number (a CD-ROM device driver may support several drives as
|
||||
subunits), followed by the address of the drive's device driver.
|
||||
The filename is 10 bytes into the device driver. The filename is
|
||||
at most 8 bytes long, and if less than 8 bytes, is terminated by
|
||||
a space (20H).
|
||||
======================================================================
|
||||
Section 3 - Drive Interface
|
||||
======================================================================
|
||||
3.01. How do I open the door?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a one byte block of
|
||||
memory. Call DOS IOCTL function 4403H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,0
|
||||
lds DX,Command
|
||||
mov CX,1
|
||||
mov AX,4403H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,1
|
||||
jne write_error
|
||||
;
|
||||
; door should be open
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
----------------------------------------------------------------------
|
||||
3.02. How do I close the door?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a one byte block of
|
||||
memory. Call DOS IOCTL function 4403H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,5
|
||||
lds DX,Command
|
||||
mov CX,1
|
||||
mov AX,4403H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,1
|
||||
jne write_error
|
||||
;
|
||||
; door should be closed
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after closing the door before
|
||||
accessing the drive (see question 3.05, How do I reset the
|
||||
drive?).
|
||||
----------------------------------------------------------------------
|
||||
3.03. How do I unlock the door?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a two-byte block of
|
||||
memory. Call DOS IOCTL function 4403H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,1
|
||||
mov Command+1,0
|
||||
lds DX,Command
|
||||
mov CX,2
|
||||
mov AX,4403H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,2
|
||||
jne write_error
|
||||
;
|
||||
; door should be unlocked
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after unlocking the door before
|
||||
accessing the drive (see question 3.05, How do I reset the
|
||||
drive?).
|
||||
----------------------------------------------------------------------
|
||||
3.04. How do I lock the door?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a two-byte block of
|
||||
memory. Call DOS IOCTL function 4403H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,1
|
||||
mov Command+1,1
|
||||
lds DX,Command
|
||||
mov CX,2
|
||||
mov AX,4403H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,2
|
||||
jne write_error
|
||||
;
|
||||
; door should be locked
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after locking the door before
|
||||
accessing the drive (see question 3.05, How do I reset the
|
||||
drive?).
|
||||
----------------------------------------------------------------------
|
||||
3.05. How do I reset the drive?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a one-byte block of
|
||||
memory. Call DOS IOCTL function 4403H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,2
|
||||
lds DX,Command
|
||||
mov CX,1
|
||||
mov AX,4403H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,1
|
||||
jne write_error
|
||||
;
|
||||
; drive should be reset
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
----------------------------------------------------------------------
|
||||
3.06. How do I get drive status?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a five-byte block of
|
||||
memory. Call DOS IOCTL function 4402H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,6
|
||||
lds DX,Command
|
||||
mov CX,5
|
||||
mov AX,4402H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,5
|
||||
jne read_error
|
||||
;
|
||||
; The word at offset 1 of the five-byte block of memory contains
|
||||
; status
|
||||
; bit 10 is set if audio is playing
|
||||
; bit 9 is set if Red Book and HSG addressing are both
|
||||
; supported
|
||||
; bit 8 is set if audio channel control is supported
|
||||
; bit 7 is set if prefetch requests are supported
|
||||
; bit 5 is set if interleaving is supported
|
||||
; bit 4 is set if audio/video track playback is supported
|
||||
; bit 3 is set if the CD-ROM is writable
|
||||
; bit 2 is set if raw and cooked read is supported
|
||||
; bit 1 is set if the door is unlocked
|
||||
; bit 0 is set if the door is open
|
||||
;
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after checking drive status before
|
||||
accessing the drive (see question 3.05, How do I reset the
|
||||
drive?).
|
||||
======================================================================
|
||||
Section 4 - Drive Capacity
|
||||
======================================================================
|
||||
4.01. What sector size is supported?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a four-byte block of
|
||||
memory. Call DOS IOCTL function 4402H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,7
|
||||
lds DX,Command
|
||||
mov CX,4
|
||||
mov AX,4402H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,4
|
||||
jne read_error
|
||||
;
|
||||
; The byte at offset 1 of the four-byte block of memory contains
|
||||
; raw/cooked status (0 = cooked, 1 = raw)
|
||||
; The word at offset 2 of the four-byte block of memory contains
|
||||
; the sector size
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after getting the sector size before
|
||||
accessing the drive (see question 3.05, How do I reset the
|
||||
drive?).
|
||||
----------------------------------------------------------------------
|
||||
4.02. How many sectors are on the disk?
|
||||
|
||||
First, you need the name of the device driver (see question 2.03,
|
||||
How do I get the name of the CD-ROM device driver?). Open the
|
||||
file for read/write and obtain the file handle (DOS function 3DH
|
||||
will suffice).
|
||||
|
||||
Once you have the file handle, you need a five-byte block of
|
||||
memory. Call DOS IOCTL function 4402H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,8
|
||||
lds DX,Command
|
||||
mov CX,5
|
||||
mov AX,4402H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,5
|
||||
jne read_error
|
||||
;
|
||||
; The dword at offset 1 of the five-byte block of memory
|
||||
; contains the number of sectors
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
|
||||
The drive should be reset after getting the number of sectors
|
||||
before accessing the drive (see question 3.05, How do I reset
|
||||
the drive?).
|
||||
----------------------------------------------------------------------
|
||||
4.03. How much data is on the disk?
|
||||
|
||||
See question 4.01, What sector size is supported?, and question
|
||||
4.02, How many sectors are on the disk?. Take the product of the
|
||||
two values returned. The conventional DOS functions don't work
|
||||
reliably.
|
||||
======================================================================
|
||||
Section 5 - Volume Table of Contents
|
||||
======================================================================
|
||||
5.01. How do I get the abstract file name?
|
||||
|
||||
You need a 38-byte block of memory to hold the abstract file
|
||||
name. This code will fill that block:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1503H
|
||||
int 2FH
|
||||
jc error
|
||||
;
|
||||
; buffer is filled with the abstract file name.
|
||||
;
|
||||
|
||||
The file name is nul-terminated.
|
||||
|
||||
The drive should be reset after getting the abstract file name
|
||||
before accessing the drive (see question 3.05, How do I reset
|
||||
the drive?).
|
||||
----------------------------------------------------------------------
|
||||
5.02. How do I get the bibliography file name?
|
||||
|
||||
You need a 38-byte block of memory to hold the bibliography file
|
||||
name. This code will fill that block:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1504H
|
||||
int 2FH
|
||||
jc error
|
||||
;
|
||||
; buffer is filled with the bibliography file name.
|
||||
;
|
||||
|
||||
The file name is nul-terminated.
|
||||
|
||||
The drive should be reset after getting the bibliography file
|
||||
name before accessing the drive (see question 3.05, How do I
|
||||
reset the drive?).
|
||||
----------------------------------------------------------------------
|
||||
5.03. How do I get the copyright file name?
|
||||
|
||||
You need a 38-byte block of memory to hold the copyright file
|
||||
name. This code will fill that block:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1502H
|
||||
int 2FH
|
||||
jc error
|
||||
;
|
||||
; buffer is filled with the copyright file name.
|
||||
;
|
||||
|
||||
The file name is nul-terminated.
|
||||
|
||||
The drive should be reset after getting the copyright file name
|
||||
before accessing the drive (see question 3.05, How do I reset
|
||||
the drive?).
|
||||
----------------------------------------------------------------------
|
||||
5.04. How do I read the Volume Table of Contents (VTOC)?
|
||||
|
||||
The VTOC is read in 2048-byte blocks. This code fills a VTOC
|
||||
block:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov DX,BlockNumber ; 0 for the first block
|
||||
mov AX,1505H
|
||||
int 2FH
|
||||
jc error
|
||||
;
|
||||
; block is filled
|
||||
;
|
||||
; AX contains the descriptor type for this block:
|
||||
; 0001H = standard volume descriptor
|
||||
; 00FFH = volume descriptor terminator
|
||||
;
|
||||
|
||||
On error, AX will hold an error value: 000FH (invalid drive) or
|
||||
0015H (drive not ready).
|
||||
======================================================================
|
||||
Section 6 - Audio
|
||||
======================================================================
|
||||
6.01. How do I find out how many tracks are on a CD?
|
||||
|
||||
First, you need the name of the device driver (see question
|
||||
2.03, How do I get the name of the CD-ROM device driver?). Open
|
||||
the file for read/write and obtain the file handle (DOS function
|
||||
3DH will suffice).
|
||||
|
||||
Once you have the file handle, you need a seven-byte block of
|
||||
memory. Call DOS IOCTL function 4402H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,0AH
|
||||
lds DX,Command
|
||||
mov CX,7
|
||||
mov AX,4402H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,7
|
||||
jne read_error
|
||||
;
|
||||
; The byte at offset 1 of the seven-byte block of memory is the
|
||||
; number of the first track
|
||||
; The byte at offset 2 of the seven-byte block of memory is the
|
||||
; number of the last track
|
||||
; The dword at offset 4 of the seven-byte block of memory is the
|
||||
; start address of the first track in Red Book format
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
----------------------------------------------------------------------
|
||||
6.02. What are Red Book and HSG formats?
|
||||
|
||||
Both are ways of encoding frame information. An audio frame is
|
||||
1/75 second of audio. HSG encodes frame information into a
|
||||
double word: minute multiplied by 4500, plus second multiplied
|
||||
by 75, plus frame, minus 150. Red Book encodes frame information
|
||||
into a four-byte data structure:
|
||||
Byte 0: frame number
|
||||
Byte 1: second
|
||||
Byte 2: minute
|
||||
Byte 3: unused
|
||||
----------------------------------------------------------------------
|
||||
6.03. How can I determine where a particular track starts?
|
||||
|
||||
First, you need the name of the device driver (see question
|
||||
2.03, How do I get the name of the CD-ROM device driver?). Open
|
||||
the file for read/write and obtain the file handle (DOS function
|
||||
3DH will suffice).
|
||||
|
||||
Once you have the file handle, you need an eight-byte block of
|
||||
memory. Call DOS IOCTL function 4402H, as shown here:
|
||||
|
||||
mov BX,FileHandle
|
||||
mov Command,0BH
|
||||
mov Command+1,TrackNumber
|
||||
lds DX,Command
|
||||
mov CX,8
|
||||
mov AX,4402H
|
||||
int 21H
|
||||
jc error
|
||||
cmp AX,8
|
||||
jne read_error
|
||||
;
|
||||
; The dword at offset 2 of the eight-byte block of memory is the
|
||||
; start address of the specified track in Red Book format
|
||||
; The word at offset 6 of the eight-byte block of memory is the
|
||||
; track control information. Bits 15-12 are used:
|
||||
; 0xxx: Two audio channels, no pre-emphasis, digital copy not
|
||||
; permitted
|
||||
; 1xxx: Two audio channels, with pre-emphasis, digital copy not
|
||||
; permitted
|
||||
; 2xxx: Two audio channels, no pre-emphasis, digital copy
|
||||
; permitted
|
||||
; 3xxx: Two audio channels, with pre-emphasis, digital copy
|
||||
; permitted
|
||||
; 4xxx: Data track, digital copy not permitted
|
||||
; 6xxx: Data track, digital copy permitted
|
||||
; 8xxx: Four audio channels, no pre-emphasis, digital copy not
|
||||
; permitted
|
||||
; 9xxx: Four audio channels, with pre-emphasis, digital copy not
|
||||
; permitted
|
||||
; Axxx: Four audio channels, no pre-emphasis, digital copy
|
||||
; permitted
|
||||
; Bxxx: Four audio channels, with pre-emphasis, digital copy
|
||||
; permitted
|
||||
|
||||
On error (carry set), AX will hold an error code: 0001H (invalid
|
||||
function), 0005H (access denied), 0006H (invalid handle), or
|
||||
000DH (invalid data).
|
||||
----------------------------------------------------------------------
|
||||
6.04. How do I play audio?
|
||||
|
||||
For starters, you need MSCDEX Version 2.1 or greater (see
|
||||
question 1.02, How do I determine the MSCDEX version?).
|
||||
|
||||
You also need the subunit number for the drive containing the
|
||||
audio CD (see question 2.03, How do I get the name of the CD-ROM
|
||||
device driver?)
|
||||
|
||||
You also need to know what frame you want to start with (see
|
||||
question 6.03, How can I determine where a particular track
|
||||
starts?), and how many frames you want to play.
|
||||
|
||||
Now, you need a 22-byte block of memory. Write 22 (16H) to the
|
||||
first byte. Write the subunit number to the second byte. Write
|
||||
84H to the third byte. Write 0 to the byte at offset 0DH (this
|
||||
sets up HSG addressing). Convert the starting frame number to
|
||||
HSG format and write the 4-byte result to the dword at offset
|
||||
0EH. Finally, write the frame count to the dword at offset 12H.
|
||||
|
||||
To play the CD as instructed, execute this code:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1510H
|
||||
int 2FH
|
||||
;
|
||||
; status is in the word at offset 3 of the buffer. Look for bit
|
||||
; 8 set (done), and watch out for bit 15 set (error).
|
||||
;
|
||||
----------------------------------------------------------------------
|
||||
6.05. How do I pause audio playback?
|
||||
|
||||
For starters, you need MSCDEX Version 2.1 or greater (see
|
||||
question 1.02, How do I determine the MSCDEX version?).
|
||||
|
||||
You also need the subunit number for the drive containing the
|
||||
audio CD (see question 2.03, How do I get the name of the CD-ROM
|
||||
device driver?)
|
||||
|
||||
Now, you need a 13-byte block of memory. Write 13 (0DH) to the
|
||||
first byte. Write the subunit number to the second byte. Write
|
||||
85H to the third byte.
|
||||
|
||||
To pause the CD, execute this code:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1510H
|
||||
int 2FH
|
||||
;
|
||||
; status is in the word at offset 3 of the buffer. Look for bit
|
||||
; 8 set (done), and watch out for bit 15 set (error).
|
||||
;
|
||||
----------------------------------------------------------------------
|
||||
6.06. How do I resume audio playback?
|
||||
|
||||
For starters, you need MSCDEX Version 2.1 or greater (see
|
||||
question 1.02, How do I determine the MSCDEX version?).
|
||||
|
||||
You also need the subunit number for the drive containing the
|
||||
audio CD (see question 2.03, How do I get the name of the CD-ROM
|
||||
device driver?)
|
||||
|
||||
Now, you need a 13-byte block of memory. Write 13 (0DH) to the
|
||||
first byte. Write the subunit number to the second byte. Write
|
||||
88H to the third byte.
|
||||
|
||||
To resume, execute this code:
|
||||
|
||||
les BX,Buffer
|
||||
mov CX,Drive ; must be in format 0 = A:, 1 = B:, etc.
|
||||
mov AX,1510H
|
||||
int 2FH
|
||||
;
|
||||
; status is in the word at offset 3 of the buffer. Look for bit
|
||||
; 8 set (done), and watch out for bit 15 set (error).
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
7
study/sabre/os/files/Disk/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
BIN
study/sabre/os/files/Disk/scsienbl.gif
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
study/sabre/os/files/Disk/scsigetm.gif
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
7
study/sabre/os/files/Drivers/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
BIN
study/sabre/os/files/Drivers/stand-device.pdf
Normal file
128
study/sabre/os/files/Executables/AppendingFilesToEXEs.txt
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
Appending Files to EXEs.
|
||||
|
||||
After seeing several questions on appending files to EXEs, I decided to
|
||||
write this text. I did NOT originate this idea. While this text describes
|
||||
"a" way of implementing the technique it may not be the best way for your
|
||||
needs. I have simply attempted to supply you with a basic understanding of
|
||||
the process.
|
||||
|
||||
|
||||
WHY?
|
||||
|
||||
A couple years ago, I purchased a copy of Ultima 7. After installing it
|
||||
I looked at the directory. There were a lot of files and moving any one of
|
||||
them out of the directory crashed the program. When I got Unreal by Future
|
||||
Crew all of my preconceived ideas went out the window.
|
||||
|
||||
1. You can't run a 2meg EXE, can you?!
|
||||
2. Where are the music and graphic files?!
|
||||
3. How'd they do that? (This includes the effects :)
|
||||
|
||||
The answer to #1 : "It runs; therefore, you must be able to do it. Idiot!"
|
||||
The answer to #2 : "All the music and graphic files are contained IN the EXE."
|
||||
Question #3 is a little harder to explain, I still don't know exactly what FC
|
||||
did, but the technique I discuss in this file gives you similar results.
|
||||
|
||||
|
||||
|
||||
Appending a file
|
||||
|
||||
Before you append a file to the end of your EXE, ask yourself how do
|
||||
access it. If your adding 10 files how do you know where they are? This is
|
||||
actually really simple once you think it through. Create a directory
|
||||
structure of your own and make it the very last file you append! Use your own
|
||||
structure if you want but feel free to use mine.
|
||||
|
||||
Directory structure:
|
||||
|
||||
repeat
|
||||
name - string
|
||||
filepos - long int, pointer to the first byte of the file
|
||||
filesize - long int
|
||||
for each file being attach
|
||||
|
||||
long int - number of entries
|
||||
|
||||
|
||||
|
||||
Since this is similar to a WAD file, we'll call is a KAD file.
|
||||
KAD = Kodiak Wad file, get it a KAD file.
|
||||
Okay, so it wasn't that good, lets move on.
|
||||
|
||||
To build the KAD file all you have to do is tack one file after another INTO
|
||||
a single file and add the directory to the end of it.
|
||||
|
||||
|
||||
see packer.c
|
||||
|
||||
Open output file
|
||||
repeat
|
||||
save the output's file position in directory structure
|
||||
save the input's file name, ignoring path, in directory structure
|
||||
save the input's file size in directory structure
|
||||
open input file
|
||||
copy input file to output file
|
||||
close input file
|
||||
until all files are appended
|
||||
save directory info
|
||||
close file
|
||||
|
||||
Simple, ehh?
|
||||
|
||||
Now that you have the KAD file what do you do with it?
|
||||
|
||||
To access the KAD your code should read the directory into a memory array.
|
||||
Just read the last dword of the KAD multiply by 8 (2 dwords) add 4, and seek
|
||||
from the end of the file back that many bytes and fill your directory array
|
||||
from there.
|
||||
|
||||
Now if you want to load the first file from the KAD, get the file offset from
|
||||
your directory array, seek to the file position and load. What could be
|
||||
simpler? How about using a pre-written function GETFILE. :)
|
||||
|
||||
While you are developing your program use the KAD file. Once your code is
|
||||
done your ready for the final step. Instead of reading from the KAD file,
|
||||
change the input name your program is looking for, to itself. Then repack the
|
||||
files to the end of your EXE.
|
||||
|
||||
see packer.c
|
||||
|
||||
Open EXE file
|
||||
seek the end of the EXE file
|
||||
repeat
|
||||
save the output's file position in directory structure
|
||||
save the input's file type in directory structure
|
||||
save the input's file size in directory structure
|
||||
open input file
|
||||
copy input file to output file
|
||||
close input file
|
||||
until all files are appended
|
||||
save directory info
|
||||
close file
|
||||
|
||||
That's it! YOUR DONE!
|
||||
|
||||
|
||||
Keep in mind that this is NOT the only way to accomplish this. I have
|
||||
included a fully functional KAD system implemented for Watcom C. It includes
|
||||
LZARI decompression routine. If this file has helped you, let me know. Feel
|
||||
free to use the code included, but if you do greet me. A postcard would be
|
||||
nice too. :)
|
||||
|
||||
|
||||
NOTE: I have heard it said "you can't do this when using an EXE compression
|
||||
loader like Pklite." I have one thing to say......BULL! The trick is to
|
||||
compress your EXE prior to appending the KAD to it.
|
||||
|
||||
|
||||
|
||||
Coded by Kodiak of The Apollo Project
|
||||
AKA Charles Jones
|
||||
1122 s 32nd St #2
|
||||
Omaha, NE 68105
|
||||
(402)-346-8974
|
||||
|
||||
Email: CAD@UnOmaha.edu
|
||||
IRC : #Coders (lo *, Bri_acid: I still want to be on OPPER's list)
|
||||
|
||||
BIN
study/sabre/os/files/Executables/AppendingFilesToEXEs.zip
Normal file
58
study/sabre/os/files/Executables/COM.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
COM Format
|
||||
Intel byte order
|
||||
|
||||
Information from File Format List 2.0 by Max Maischein.
|
||||
|
||||
--------!-CONTACT_INFO----------------------
|
||||
If you notice any mistakes or omissions, please let me know! It is only
|
||||
with YOUR help that the list can continue to grow. Please send
|
||||
all changes to me rather than distributing a modified version of the list.
|
||||
|
||||
This file has been authored in the style of the INTERxxy.* file list
|
||||
by Ralf Brown, and uses almost the same format.
|
||||
|
||||
Please read the file FILEFMTS.1ST before asking me any questions. You may find
|
||||
that they have already been addressed.
|
||||
|
||||
Max Maischein
|
||||
|
||||
Max Maischein, 2:244/1106.17
|
||||
Max_Maischein@spam.fido.de
|
||||
corion@informatik.uni-frankfurt.de
|
||||
Corion on #coders@IRC
|
||||
--------!-DISCLAIMER------------------------
|
||||
DISCLAIMER: THIS MATERIAL IS PROVIDED "AS IS". I verify the information
|
||||
contained in this list to the best of my ability, but I cannot be held
|
||||
responsible for any problems caused by use or misuse of the information,
|
||||
especially for those file formats foreign to the PC, like AMIGA or SUN file
|
||||
formats. If an information it is marked "guesswork" or undocumented, you
|
||||
should check it carefully to make sure your program will not break with
|
||||
an unexpected value (and please let me know whether or not it works
|
||||
the same way).
|
||||
|
||||
Information marked with "???" is known to be incomplete or guesswork.
|
||||
|
||||
Some file formats were not released by their creators, others are regarded
|
||||
as proprietary, which means that if your programs deal with them, you might
|
||||
be looking for trouble. I don't care about this.
|
||||
--------------------------------------------
|
||||
|
||||
The COM files are raw binary executables and are a leftover from the old CP/M
|
||||
machines with 64K RAM. A COM program can only have a size of less than one
|
||||
segment (64K), including code and static data since no fixups for segment
|
||||
relocation or anything else is included. One method to check for a COM file is
|
||||
to check if the first byte in the file could be a valid jump or call opcode, but
|
||||
this is a very weak test since a COM file is not required to start with a jump
|
||||
or a call. In principle, a COM file is just loaded at offset 100h in the segment
|
||||
and then executed.
|
||||
|
||||
OFFSET Count TYPE Description
|
||||
0000h 1 byte ID=0E9h
|
||||
ID=0EBh
|
||||
Those are not safe ways to determine wether a
|
||||
file is a COM file or not, but most COM files
|
||||
start with a jump.
|
||||
Further information not available.
|
||||
EXTENSION:COM
|
||||
OCCURENCES:PC
|
||||
SEE ALSO:EXE,MZ EXE,NE EXE
|
||||
BIN
study/sabre/os/files/Executables/Dwarf.pdf
Normal file
BIN
study/sabre/os/files/Executables/ELF.pdf
Normal file
445
study/sabre/os/files/Executables/EXE-3.1.txt
Normal file
@@ -0,0 +1,445 @@
|
||||
Executable-File Header Format (3.1)
|
||||
|
||||
An executable (.EXE) file for the Windows operating system contains a
|
||||
combination of code and data or a combination of code, data, and resources. The
|
||||
executable file also contains two headers: an MS-DOS header and a Windows
|
||||
header. The next two sections describe these headers; the third section
|
||||
describes the code and data contained in a Windows executable file.
|
||||
|
||||
MS-DOS Header
|
||||
|
||||
The MS-DOS (old-style) executable-file header contains four distinct parts: a
|
||||
collection of header information (such as the signature word, the file size,
|
||||
and so on), a reserved section, a pointer to a Windows header (if one exists),
|
||||
and a stub program. The following illustration shows the MS-DOS executable-file
|
||||
header: If the word value at offset 18h is 40h or greater, the word value at
|
||||
3Ch is typically an offset to a Windows header. Applications must verify this
|
||||
for each executable-file header being tested, because a few applications have a
|
||||
different header style. MS-DOS uses the stub program to display a message if
|
||||
Windows has not been loaded when the user attempts to run a program.
|
||||
|
||||
Windows Header
|
||||
|
||||
The Windows (new-style) executable-file header contains information that the
|
||||
loader requires for segmented executable files. This information includes the
|
||||
linker version number, data specified by the linker, data specified by the
|
||||
resource compiler, tables of segment data, tables of resource data, and so on.
|
||||
The following illustration shows the Windows executable-file header:
|
||||
|
||||
The following sections describe the entries in the Windows executable-file
|
||||
header.
|
||||
|
||||
Information Block
|
||||
|
||||
The information block in the Windows header contains the linker version number,
|
||||
the lengths of various tables that further describe the executable file, the
|
||||
offsets from the beginning of the header to the beginning of these tables, the
|
||||
heap and stack sizes, and so on. The following list summarizes the contents of
|
||||
the header information block (the locations are relative to the beginning of
|
||||
the block):
|
||||
|
||||
Loc Description
|
||||
|
||||
00h The signature word. The low byte contains "N" (4Eh) and the high byte
|
||||
contains "E" (45h).
|
||||
02h The linker version number.
|
||||
03h The linker revision number.
|
||||
04h The offset to the entry table (relative to the beginning of the
|
||||
header).
|
||||
06h The length of the entry table, in bytes.
|
||||
08h Reserved.
|
||||
0Ch Flags that describe the contents of the executable file. This value can
|
||||
be one or more of the following bits:
|
||||
|
||||
Bit Meaning
|
||||
|
||||
0 The linker sets this bit if the executable-file format is
|
||||
SINGLEDATA. An executable file with this format contains one
|
||||
data segment. This bit is set if the file is a dynamic-link
|
||||
library (DLL).
|
||||
1 The linker sets this bit if the executable-file format is
|
||||
MULTIPLEDATA. An executable file with this format contains
|
||||
multiple data segments. This bit is set if the file is a
|
||||
Windows application.
|
||||
If neither bit 0 nor bit 1 is set, the executable-file format
|
||||
is NOAUTODATA. An executable file with this format does not
|
||||
contain an automatic data segment.
|
||||
2 Reserved.
|
||||
3 Reserved.
|
||||
8 Reserved.
|
||||
9 Reserved.
|
||||
11 If this bit is set, the first segment in the executable file
|
||||
contains code that loads the application.
|
||||
13 If this bit is set, the linker detects errors at link time but
|
||||
still creates an executable file.
|
||||
14 Reserved.
|
||||
15 If this bit is set, the executable file is a library module.
|
||||
If bit 15 is set, the CS:IP registers point to an
|
||||
initialization procedure called with the value in the AX
|
||||
register equal to the module handle. The initialization
|
||||
procedure must execute a far return to the caller. If the
|
||||
procedure is successful, the value in AX is nonzero. Otherwise,
|
||||
the value in AX is zero. The value in the DS register is set to
|
||||
the library's data segment if SINGLEDATA is set. Otherwise, DS
|
||||
is set to the data segment of the application that loads the
|
||||
library.
|
||||
|
||||
0Eh The automatic data segment number. (0Eh is zero if the SINGLEDATA and
|
||||
MULTIPLEDATA bits are cleared.)
|
||||
10h The initial size, in bytes, of the local heap. This value is zero if
|
||||
there is no local allocation.
|
||||
12h The initial size, in bytes, of the stack. This value is zero if the SS
|
||||
register value does not equal the DS register value.
|
||||
14h The segment:offset value of CS:IP.
|
||||
18h The segment:offset value of SS:SP.
|
||||
The value specified in SS is an index to the module's segment table.
|
||||
The first entry in the segment table corresponds to segment number 1.
|
||||
If SS addresses the automatic data segment and SP is zero, SP is set to
|
||||
the address obtained by adding the size of the automatic data segment
|
||||
to the size of the stack.
|
||||
1Ch The number of entries in the segment table.
|
||||
1Eh The number of entries in the module-reference table.
|
||||
20h The number of bytes in the nonresident-name table.
|
||||
22h A relative offset from the beginning of the Windows header to the
|
||||
beginning of the segment table.
|
||||
24h A relative offset from the beginning of the Windows header to the
|
||||
beginning of the resource table.
|
||||
26h A relative offset from the beginning of the Windows header to the
|
||||
beginning of the resident-name table.
|
||||
28h A relative offset from the beginning of the Windows header to the
|
||||
beginning of the module-reference table.
|
||||
2Ah A relative offset from the beginning of the Windows header to the
|
||||
beginning of the imported-name table.
|
||||
2Ch A relative offset from the beginning of the file to the beginning of
|
||||
the nonresident-name table.
|
||||
30h The number of movable entry points.
|
||||
32h A shift count that is used to align the logical sector. This count is
|
||||
log2 of the segment sector size. It is typically 4, although the
|
||||
default count is 9. (This value corresponds to the /alignment [/a]
|
||||
linker switch. When the linker command line contains /a:16, the shift
|
||||
count is 4. When the linker command line contains /a:512, the shift
|
||||
count is 9.)
|
||||
34h The number of resource segments.
|
||||
36h The target operating system, depending on which bits are set:
|
||||
|
||||
Bit Meaning
|
||||
|
||||
0 Operating system format is unknown.
|
||||
1 Reserved.
|
||||
2 Operating system is Microsoft Windows.
|
||||
3 Reserved.
|
||||
4 Reserved.
|
||||
|
||||
37h Additional information about the executable file. It can be one or more
|
||||
of the following values:
|
||||
|
||||
Bit Meaning
|
||||
|
||||
1 If this bit is set, the executable file contains a Windows 2.x
|
||||
application that runs in version 3.x protected mode.
|
||||
2 If this bit is set, the executable file contains a Windows 2.x
|
||||
application that supports proportional fonts.
|
||||
3 If this bit is set, the executable file contains a fast-load
|
||||
area.
|
||||
|
||||
38h The offset, in sectors, to the beginning of the fast-load area. (Only
|
||||
Windows uses this value.)
|
||||
3Ah The length, in sectors, of the fast-load area. (Only Windows uses this
|
||||
value.)
|
||||
3Ch Reserved.
|
||||
3Eh The expected version number for Windows. (Only Windows uses this
|
||||
value.)
|
||||
|
||||
Segment Table
|
||||
|
||||
The segment table contains information that describes each segment in an
|
||||
executable file. This information includes the segment length, segment type,
|
||||
and segment-relocation data. The following list summarizes the values found in
|
||||
the segment table (the locations are relative to the beginning of each entry):
|
||||
|
||||
Loc Description
|
||||
|
||||
00h The offset, in sectors, to the segment data (relative to the beginning
|
||||
of the file). A value of zero means no data exists.
|
||||
02h The length, in bytes, of the segment, in the file. A value of zero
|
||||
indicates that the segment length is 64K, unless the selector offset is
|
||||
also zero.
|
||||
04h Flags that describe the contents of the executable file. This value can
|
||||
be one or more of the following:
|
||||
|
||||
Bit Meaning
|
||||
|
||||
0 If this bit is set, the segment is a data segment. Otherwise,
|
||||
the segment is a code segment.
|
||||
1 If this bit is set, the loader has allocated memory for the
|
||||
segment.
|
||||
2 If this bit is set, the segment is loaded.
|
||||
3 Reserved.
|
||||
4 If this bit is set, the segment type is MOVABLE. Otherwise, the
|
||||
segment type is FIXED.
|
||||
5 If this bit is set, the segment type is PURE or SHAREABLE.
|
||||
Otherwise, the segment type is IMPURE or NONSHAREABLE.
|
||||
6 If this bit is set, the segment type is PRELOAD. Otherwise, the
|
||||
segment type is LOADONCALL.
|
||||
7 If this bit is set and the segment is a code segment, the
|
||||
segment type is EXECUTEONLY. If this bit is set and the segment
|
||||
is a data segment, the segment type is READONLY.
|
||||
8 If this bit is set, the segment contains relocation data.
|
||||
9 Reserved.
|
||||
10 Reserved.
|
||||
11 Reserved.
|
||||
12 If this bit is set, the segment is discardable.
|
||||
13 Reserved.
|
||||
14 Reserved.
|
||||
15 Reserved.
|
||||
|
||||
06h The minimum allocation size of the segment, in bytes. A value of zero
|
||||
indicates that the minimum allocation size is 64K.
|
||||
|
||||
Resource Table
|
||||
|
||||
The resource table describes and identifies the location of each resource in
|
||||
the executable file.
|
||||
|
||||
Following are the members in the resource table:
|
||||
|
||||
rscAlignShift The alignment shift count for resource data. When the shift
|
||||
count is used as an exponent of 2, the resulting value
|
||||
specifies the factor, in bytes, for computing the location of a
|
||||
resource in the executable file.
|
||||
rscTypes An array of TTYPEINFO structures containing information about
|
||||
resource types. There must be one TTYPEINFO structure for each
|
||||
type of resource in the executable file.
|
||||
rscEndTypes The end of the resource type definitions. This member must be
|
||||
zero.
|
||||
rscResourceNames The names (if any) associated with the resources in this
|
||||
table. Each name is stored as consecutive bytes; the first
|
||||
byte specifies the number of characters in the name.
|
||||
rscEndNames The end of the resource names and the end of the resource
|
||||
table. This member must be zero.
|
||||
|
||||
Type Information
|
||||
|
||||
Following are the members in the TTYPEINFO structure:
|
||||
|
||||
rtTypeID The type identifier of the resource. This integer value is
|
||||
either a resource-type value or an offset to a resource-type
|
||||
name. If the high bit in this member is set (0x8000), the value
|
||||
is one of the following resource-type values:
|
||||
|
||||
Value Resource type
|
||||
|
||||
RT_ACCELERATOR Accelerator table
|
||||
RT_BITMAP Bitmap
|
||||
RT_CURSOR Cursor
|
||||
RT_DIALOG Dialog box
|
||||
RT_FONT Font component
|
||||
RT_FONTDIR Font directory
|
||||
RT_GROUP_CURSOR Cursor directory
|
||||
RT_GROUP_ICON Icon directory
|
||||
RT_ICON Icon
|
||||
RT_MENU Menu
|
||||
RT_RCDATA Resource data
|
||||
RT_STRING String table
|
||||
|
||||
If the high bit of the value in this member is not set, the value represents an
|
||||
offset, in bytes relative to the beginning of the resource table, to a name in
|
||||
the rscResourceNames member.
|
||||
|
||||
rtResourceCount The number of resources of this type in the executable file.
|
||||
rtReserved Reserved.
|
||||
rtNameInfo An array of TNAMEINFO structures containing information about
|
||||
individual resources. The rtResourceCount member specifies the
|
||||
number of structures in the array.
|
||||
|
||||
Name Information
|
||||
|
||||
Following are the members in the TNAMEINFO structure:
|
||||
|
||||
rnOffset An offset to the contents of the resource data (relative to the
|
||||
beginning of the file). The offset is in terms of alignment
|
||||
units specified by the rscAlignShift member at the beginning of
|
||||
the resource table.
|
||||
rnLength The resource length, in bytes.
|
||||
rnFlags Whether the resource is fixed, preloaded, or shareable. This
|
||||
member can be one or more of the following values:
|
||||
|
||||
Value Meaning
|
||||
|
||||
0x0010 Resource is movable (MOVEABLE). Otherwise, it is fixed.
|
||||
0x0020 Resource can be shared (PURE).
|
||||
0x0040 Resource is preloaded (PRELOAD). Otherwise, it is
|
||||
loaded on demand.
|
||||
|
||||
rnID Specifies or points to the resource identifier. If the
|
||||
identifier is an integer, the high bit is set (8000h).
|
||||
Otherwise, it is an offset to a resource string, relative to
|
||||
the beginning of the resource table.
|
||||
rnHandle Reserved.
|
||||
rnUsage Reserved.
|
||||
|
||||
Resident-Name Table
|
||||
|
||||
The resident-name table contains strings that identify exported functions in
|
||||
the executable file. As the name implies, these strings are resident in system
|
||||
memory and are never discarded. The resident-name strings are case-sensitive
|
||||
and are not null-terminated. The following list summarizes the values found in
|
||||
the resident-name table (the locations are relative to the beginning of each
|
||||
entry):
|
||||
|
||||
Location Description
|
||||
|
||||
00h The length of a string. If there are no more strings in the
|
||||
table, this value is zero.
|
||||
01h - xxh The resident-name text. This string is case-sensitive and is
|
||||
not null-terminated.
|
||||
xxh + 01h An ordinal number that identifies the string. This number is an
|
||||
index into the entry table.
|
||||
|
||||
The first string in the resident-name table is the module name.
|
||||
|
||||
Module-Reference Table
|
||||
|
||||
The module-reference table contains offsets for module names stored in the
|
||||
imported-name table. Each entry in this table is 2 bytes long.
|
||||
|
||||
Imported-Name Table
|
||||
|
||||
The imported-name table contains the names of modules that the executable file
|
||||
imports. Each entry contains two parts: a single byte that specifies the length
|
||||
of the string and the string itself. The strings in this table are not
|
||||
null-terminated.
|
||||
|
||||
Entry Table
|
||||
|
||||
The entry table contains bundles of entry points from the executable file (the
|
||||
linker generates each bundle). The numbering system for these ordinal values is
|
||||
1-based--that is, the ordinal value corresponding to the first entry point is
|
||||
1. The linker generates the densest possible bundles under the restriction that
|
||||
it cannot reorder the entry points. This restriction is necessary because other
|
||||
executable files may refer to entry points within a given bundle by their
|
||||
ordinal values. The entry-table data is organized by bundle, each of which
|
||||
begins with a 2-byte header. The first byte of the header specifies the number
|
||||
of entries in the bundle (a value of 00h designates the end of the table). The
|
||||
second byte specifies whether the corresponding segment is movable or fixed. If
|
||||
the value in this byte is 0FFh, the segment is movable. If the value in this
|
||||
byte is 0FEh, the entry does not refer to a segment but refers, instead, to a
|
||||
constant defined within the module. If the value in this byte is neither 0FFh
|
||||
nor 0FEh, it is a segment index.
|
||||
|
||||
For movable segments, each entry consists of 6 bytes and has the following
|
||||
form:
|
||||
|
||||
Loc Description
|
||||
|
||||
00h Specifies a byte value. This value can be a combination of the
|
||||
following bits:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
0 If this bit is set, the entry is exported.
|
||||
1 If this bit is set, the segment uses a global (shared) data
|
||||
segment.
|
||||
3-7 If the executable file contains code that performs ring
|
||||
transitions, these bits specify the number of words that
|
||||
compose the stack. At the time of the ring transition, these
|
||||
words must be copied from one ring to the other.
|
||||
|
||||
01h An int 3fh instruction.
|
||||
03h The segment number.
|
||||
04h The segment offset.
|
||||
|
||||
For fixed segments, each entry consists of 3 bytes and has the following form:
|
||||
|
||||
Loc Description
|
||||
|
||||
00h Specifies a byte value. This value can be a combination of the
|
||||
following bits:
|
||||
|
||||
Bit(s) Meaning
|
||||
|
||||
0 If this bit is set, the entry is exported.
|
||||
1 If this bit is set, the entry uses a global (shared) data
|
||||
segment. (This may be set only for SINGLEDATA library modules.)
|
||||
3-7 If the executable file contains code that performs ring
|
||||
transitions, these bits specify the number of words that
|
||||
compose the stack. At the time of the ring transition, these
|
||||
words must be copied from one ring to the other.
|
||||
|
||||
01h Specifies an offset.
|
||||
|
||||
Nonresident-Name Table
|
||||
|
||||
The nonresident-name table contains strings that identify exported functions in
|
||||
the executable file. As the name implies, these strings are not always resident
|
||||
in system memory and are discardable. The nonresident-name strings are
|
||||
case-sensitive; they are not null-terminated. The following list summarizes the
|
||||
values found in the nonresident-name table (the specified locations are
|
||||
relative to the beginning of each entry):
|
||||
|
||||
Location Description
|
||||
|
||||
00h The length, in bytes, of a string. If this byte is 00h, there
|
||||
are no more strings in the table.
|
||||
01h - xxh The nonresident-name text. This string is case-sensitive and is
|
||||
not null-terminated.
|
||||
xx + 01h An ordinal number that is an index to the entry table.
|
||||
|
||||
The first name that appears in the nonresident-name table is the module
|
||||
description string (which was specified in the module-definition file).
|
||||
|
||||
Code Segments and Relocation Data
|
||||
|
||||
Code and data segments follow the Windows header. Some of the code segments may
|
||||
contain calls to functions in other segments and may, therefore, require
|
||||
relocation data to resolve those references. This relocation data is stored in
|
||||
a relocation table that appears immediately after the code or data in the
|
||||
segment. The first 2 bytes in this table specify the number of relocation items
|
||||
the table contains. A relocation item is a collection of bytes specifying the
|
||||
following information:
|
||||
|
||||
- Address type (segment only, offset only, segment and offset)
|
||||
- Relocation type (internal reference, imported ordinal, imported name)
|
||||
- Segment number or ordinal identifier (for internal references)
|
||||
- Reference-table index or function ordinal number (for imported ordinals)
|
||||
- Reference-table index or name-table offset (for imported names)
|
||||
|
||||
Each relocation item contains 8 bytes of data, the first byte of which
|
||||
specifies one of the following relocation-address types:
|
||||
|
||||
Value Meaning
|
||||
|
||||
0 Low byte at the specified offset
|
||||
2 16-bit selector
|
||||
3 32-bit pointer
|
||||
5 16-bit offset
|
||||
11 48-bit pointer
|
||||
13 32-bit offset
|
||||
|
||||
The second byte specifies one of the following relocation types:
|
||||
|
||||
Value Meaning
|
||||
|
||||
0 Internal reference
|
||||
1 Imported ordinal
|
||||
2 Imported name
|
||||
3 OSFIXUP
|
||||
|
||||
The third and fourth bytes specify the offset of the relocation item within the
|
||||
segment.
|
||||
|
||||
If the relocation type is imported ordinal, the fifth and sixth bytes specify
|
||||
an index to a module's reference table and the seventh and eighth bytes specify
|
||||
a function ordinal value.
|
||||
|
||||
If the relocation type is imported name, the fifth and sixth bytes specify an
|
||||
index to a module's reference table and the seventh and eighth bytes specify an
|
||||
offset to an imported-name table.
|
||||
|
||||
If the relocation type is internal reference and the segment is fixed, the
|
||||
fifth byte specifies the segment number, the sixth byte is zero, and the
|
||||
seventh and eighth bytes specify an offset to the segment. If the relocation
|
||||
type is internal reference and the segment is movable, the fifth byte specifies
|
||||
0FFh, the sixth byte is zero; and the seventh and eighth bytes specify an
|
||||
ordinal value found in the segment's entry table.
|
||||
|
||||
527
study/sabre/os/files/Executables/EXE-LINK.txt
Normal file
@@ -0,0 +1,527 @@
|
||||
<20> Advanced Linking Techniques
|
||||
<20> Part 1
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
||||
How to put everything into <20>
|
||||
- ONE BIG EXE FILE -
|
||||
|
||||
In the good old days most of the programs had many files. That was a
|
||||
simple and convenient way for storing the necessary data. But the time quic-
|
||||
kly ran forth and a new tendency appeared: the single EXE method. This
|
||||
is more difficult to deal with (from the coders' point of view), but it's
|
||||
also more elegant. So this article discusses some system coding, which is
|
||||
important in a demo, but quite invisible.
|
||||
|
||||
I. Capabilities of EXE files
|
||||
II. Link data to the executable file
|
||||
III. Overlays
|
||||
IV. Link EXEs together (chaining)
|
||||
V. Virtual file systems
|
||||
|
||||
|
||||
I. Concerning EXE files
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
An EXE file consists of three parts: header, body and overlay. The header
|
||||
contains info about the body (the executable part). The rest of the file
|
||||
is the overlay: it can be any data copied to the end of the body. For
|
||||
example, the debug info. The body is 512-byte aligned in the file by
|
||||
default, but it may be put to 16-byte boundary to save some space. (Actually
|
||||
the loading of 512-aligned executable parts is faster in DOS.)
|
||||
|
||||
!USEFUL! For source-level debugging assemble with the /zi switch and
|
||||
link with /v. Then in Turbo Debugger select View/module and You're
|
||||
debugging in your source code. Also You may take a look at the end of the
|
||||
file - how the debug info looks like. (Extremely interesing ;-) Plus one
|
||||
thing: Pklite doesn't kill overlays - compressed files remain wonderfully
|
||||
debuggable!
|
||||
|
||||
Now I wouldn't like to discuss over the structure of the EXE header - its
|
||||
description may be found in many places (DosRef, IntrList, TechHelp) -
|
||||
just to point to some funny things.
|
||||
|
||||
|
||||
Some facts about the EXE header
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Signature: Can be either 'MZ' or 'ZM'. If a file to be executed starts with
|
||||
'MZ' or 'ZM', it will be treated as EXE file, otherwise .COM file. (The
|
||||
extension (EXE/COM) doesn't matter at all.)
|
||||
|
||||
Partial Page: Equals the length of the executable part + length of the
|
||||
header mod 512. (I'll refer to 'Length of the file without overlays' as 'EXE
|
||||
Length' in the followings, so this field is EXE Length mod 512.)
|
||||
|
||||
PageCounter : This is NOT EXE Length div 512 and also NOT EXE Length div
|
||||
512 +1 as some docs claims. It's exactly the upper whole part (UpRound) of
|
||||
EXE Length / 512. Practically, if PartialPage = 0, it's EXELength div
|
||||
512, else EXE Length div 512 + 1.
|
||||
|
||||
Checksum: Nobody cares it.
|
||||
Originally it's a pad word that the sum of the words in an EXE file would
|
||||
be 0. No info on what should happen if the file is odd-length... So this word
|
||||
can be anything.
|
||||
|
||||
Start of the relocation table : Tlink sets it to 3eh, but it can be placed
|
||||
elsewhere.
|
||||
|
||||
Overlay number : Another unused area. To save space, the relocation table
|
||||
can start here. According to some documentations this doesn't belong
|
||||
to the EXE header. So the shortest EXE file in the world is 26 bytes
|
||||
long, and consists of only a header. Its entry point is the 'int 20h' ins-
|
||||
truction in the PSP. Executable files under 26 byte are all .COM files even
|
||||
if they start with 'MZ'...
|
||||
And the shortest .COM file is a single 'retn' instruction ;-)
|
||||
|
||||
!TRICK! It's funny to add some text to the beginning to the EXE file with
|
||||
a message "Ripping is lame!" or something... Here's the technique:
|
||||
a postprocessor program places the relocation table elsewhere and copies
|
||||
a message after the header.
|
||||
|
||||
A freshly compiled EXE file looks like this:
|
||||
|
||||
"MZ" <- signature
|
||||
<header data>
|
||||
"<22>0jr" <- Tasm crap
|
||||
<relocation table (if any)>
|
||||
<Numerous pad bytes> <- Body is 512
|
||||
<Body> aligned
|
||||
|
||||
This can be modified/compressed into:
|
||||
|
||||
"MZ" <- Remains
|
||||
<header data> <- New reloc.
|
||||
table start!
|
||||
"Ripping is lame!" <- Message
|
||||
<relocation table>
|
||||
<Max. 12 pad bytes> <-Body will be
|
||||
<Body> paragraph aligned
|
||||
|
||||
So if an inquistive dude looks to the EXE file, he immediately confronts
|
||||
the message :-)
|
||||
|
||||
|
||||
Now some general things
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- You may copy any data to your EXE file, e.g.
|
||||
|
||||
'copy /b demoEXE+piccy.raw demo2EXE'
|
||||
|
||||
This won't affect the execution of the EXE file. It's Your problem how to
|
||||
access the data... see chapter 3.
|
||||
|
||||
- .COM to EXE conversion : All to be done is to insert a 32-byte header be-
|
||||
fore the .COM file. The only interesting thing is how to calculate the
|
||||
entry point. DOS loads the body to PSP+10h:0, and adds it to the Relative
|
||||
initial CS. This value will be the program's CS. The problem is that at
|
||||
.COM files the initial CS equals the PSP's segment... So the Rel. init. CS
|
||||
in this case must be fff0. It's added to PSP+10h will be exactly the PSP's
|
||||
segment ;-) Some programs don't recognize this technique (Like F-Prot and
|
||||
Hacker's View), but it works anyway. The appropriate header looks like this:
|
||||
|
||||
"MZ" <- Ususal sign
|
||||
PartPage = (COM's length+32) mod 512
|
||||
PageCnt = UpRound((COM's length+32) / 512)
|
||||
Checksum <- Anything
|
||||
Size of header=2 <- (2 paragraphs)
|
||||
Minimal Memory=(ffff - COM's length) / 16
|
||||
Maximal Memory=ffff
|
||||
Initial IP=100h <- .COM property
|
||||
Rel. init CS=fff0 <- It will overflow
|
||||
Initial SP=fffe <- .COM property
|
||||
Rel. init SS=fff0 <- Same as CS
|
||||
Number of relocations=0 <- No relos
|
||||
Start of relocation table <- Anything
|
||||
Overlay number <- Anything
|
||||
4 pad bytes <- Anything
|
||||
Now the most important topic comes in
|
||||
this article:
|
||||
|
||||
How to kick out Windows from a demo nicely and intelligently
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
The Windows EXE file format is a superset of the DOS EXE format. How
|
||||
Windows starts executing a program?
|
||||
|
||||
1. Checks the 1st word of the file. If it's not 'MZ' treates it as a DOS prg.
|
||||
2. if it's 'MZ', gets a word from the file at offset 003dh (let's call this
|
||||
word New EXE Header Offset (NEHO)), then checks the word at NEHO. If it's
|
||||
'NE', then it's a Windows EXE file, otherwise not.
|
||||
|
||||
Also every Windows EXE contains a little DOS EXE (called STUB) which
|
||||
will run when somebody tries to start the program from DOS. Usually it shows
|
||||
up a message like 'This program requires Microsoft Windows'. (Gosh! Some
|
||||
evil stubs start Windows if they find it :-( What is our goal? We want a
|
||||
program which runs perfectly in DOS, and under Windows shows up a message
|
||||
box: 'This program requires NO Microsoft Windows.', then kills Windoze,
|
||||
executes itself under DOS and restarts Windoze. The main idea is that we
|
||||
change the 'stub' program of a Windooz application.
|
||||
|
||||
Here's the C code of the Windows
|
||||
program:
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
int PASCAL WinMain(HWND hInstance,
|
||||
HWND hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow){
|
||||
char MyName[128];
|
||||
|
||||
MessageBox(0,"This program"
|
||||
"requires NO Microsoft Windows.",
|
||||
"Windooz suks", 0);
|
||||
|
||||
GetModuleFileName(hInstance, MyName,
|
||||
128);
|
||||
|
||||
ExitWindowsExec(MyName, lpCmdLine);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
In the module-definition (.DEF) file the 'STUB' entry must be changed from
|
||||
winstub.exe to demo.exe :-)
|
||||
|
||||
One thing must be maintaned : the relocation table of the 'stub' file
|
||||
must start AFTER 003dh. This is not a problem for freshly assembled or PKLI-
|
||||
TEd files.
|
||||
|
||||
Problem that the 'stub' proggy must be less than 64k. This is enough for pro-
|
||||
tecting intros - for big demos some postprocessing is required.
|
||||
|
||||
II. Link data to the executable file
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Here come few tips how to put data to the program at compile and link-
|
||||
time. I assume the using of full segment declarations, NOT the simpli-
|
||||
fied version like .model and .data.
|
||||
|
||||
|
||||
1. Include method
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Let's assume we want to insert a bunch of bytes to the program (a raw
|
||||
picture, for example, 'piccy.bin'). First convert it to ASCII form:
|
||||
|
||||
BIN2ASM piccy.bin piccy.inc
|
||||
|
||||
Piccy.inc will be approximately 3-4 times large than the binary file. Now
|
||||
insert the following lines to the source code (e.g. demo.asm):
|
||||
|
||||
piccy label byte
|
||||
include piccy.inc
|
||||
|
||||
Wow. We've done it. The data will get into the program at compile-time. This
|
||||
is the most simple and most slow way. Why to compile the whole data again
|
||||
when only the code changes? And why to store the huge include file on the
|
||||
expensive harddisk?
|
||||
|
||||
|
||||
2. Link method
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Now the data will get into the proggy at link-time. We'll use object (.obj)
|
||||
files. First we have to make the object files from binary files.
|
||||
There's a utility (binobj) but it's quite unusable (it doesn't handle seg-
|
||||
ment names). For a moment we'll have to use include files... Make piccy.inc
|
||||
from the binary file! Then create a source file named piccy.asm:
|
||||
|
||||
main segment use16
|
||||
|
||||
public piccy
|
||||
piccy label byte
|
||||
include piccy.inc
|
||||
|
||||
main ends
|
||||
end
|
||||
|
||||
and compile it. (The segment name should match one of the main source
|
||||
module's segment names.) Now let's have a look at the main module
|
||||
(demo.asm):
|
||||
|
||||
o equ offset
|
||||
main segment use16
|
||||
|
||||
extrn piccy:byte
|
||||
|
||||
;Here can be anything...
|
||||
;For example,
|
||||
mov si, o piccy
|
||||
xor di,di
|
||||
rep movsd
|
||||
|
||||
main ends
|
||||
|
||||
And finally put the things together:
|
||||
tasm demo /m9
|
||||
tasm piccy
|
||||
tlink demo piccy
|
||||
|
||||
Basically these are the steps of the object-level linking. Some extensions:
|
||||
|
||||
- When You want to link independent segments (such segments which don't
|
||||
occur in the main module), enough to use segment names only. This may
|
||||
be needed when big data arrays are in use, e.g. bitmaps, and it's
|
||||
unnecessary to fool with identifier names like 'piccy'. In this case You
|
||||
don't have to add the 'public' and 'extrn' directives, just declare the
|
||||
segment:
|
||||
|
||||
piccy.asm:
|
||||
picture segment use16
|
||||
include piccy.inc
|
||||
picture ends
|
||||
end
|
||||
|
||||
demo.asm:
|
||||
main segment
|
||||
|
||||
mov ax,picture
|
||||
mov ds,ax
|
||||
xor si,si
|
||||
xor di,di
|
||||
rep movsd
|
||||
|
||||
main ends
|
||||
|
||||
picture segment ;Just declare segment
|
||||
picture ends
|
||||
|
||||
- Link more than 64k arrays
|
||||
One way is to cut the data to 64k segments... but it's better to link
|
||||
it in one step. Simply change piccy.asm:
|
||||
|
||||
.386
|
||||
picture segment use32
|
||||
include piccy.inc
|
||||
picture ends
|
||||
end
|
||||
|
||||
and the 'picture' segment can be refered as a 'normal' segment in
|
||||
real mode too. In this case, link with the /3 switch.
|
||||
|
||||
- Never forget to delete the temporary include files. They're kinda long.
|
||||
|
||||
- Use makefiles instead of batch files. Makefiles handle time-depen-
|
||||
dencies, so only those parts will be compiled which were modified since
|
||||
the last compilation. (Working time can be heavily reduced) Imagine what
|
||||
would happen if at every compilation the include files were in use :-(
|
||||
If the makefile's name is 'makefile' then enough to type 'make' at the
|
||||
command prompt, else
|
||||
'make -fdemo.mak'. If the dates of the source files are not correct,
|
||||
use the 'touch' utility. It's useful when You want to compile something
|
||||
even if it wasn't changed.
|
||||
|
||||
3. Advantages and disadvantages
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
- When compressing the EXE file the linked data will be compressed too.
|
||||
- Doesn't require postprocessing.
|
||||
- Data is available when the program starts.
|
||||
|
||||
- The amount of linkable data is limited.
|
||||
- Structure of the source code is more complex.
|
||||
|
||||
|
||||
III. Overlays
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
The advantage of the previous method is that all data You've linked are
|
||||
available when the program starts - no need for additional reading from the
|
||||
disk. The disadvantage is that the amount of the linkable data is fairly
|
||||
limited because of the lovely real mode 640k barrier. Overlays allow
|
||||
unlimited quantity of aditional data. How overlay works? As I mentioned be-
|
||||
fore, we can copy anything after an EXE file, that won't be loaded to the
|
||||
memory. It's our problem how to reach that data. Let's make an overlaid EXE
|
||||
file:
|
||||
|
||||
'copy /b demo.exe+piccy.bin demo2.exe'
|
||||
|
||||
The method is very simple : the demo2EXE opens itself, seeks to the
|
||||
beginning of the overlay data, and reads it to the memory. This reqires
|
||||
some plus administration: we have to know the length of the overlay file(s)
|
||||
in advance. The demo.exe alone of course is unusable without the overlay
|
||||
data.
|
||||
|
||||
(Now let's assume we want to show a simple picture on the screen - 64000
|
||||
bytes)
|
||||
|
||||
Borland Pascal version:
|
||||
|
||||
Var F:File;
|
||||
|
||||
Assume (F, paramstr(0));
|
||||
Reset (F, 1);
|
||||
Seek (F, Filesize(F)-64000);
|
||||
BlockRead(F, Mem[$a000:0], 64000);
|
||||
|
||||
Assembly version (Provided that DS points to the PSP):
|
||||
|
||||
mov es,[2ch] ; Get env str
|
||||
xor di,di
|
||||
mov cx,0ffffh
|
||||
mov al,0
|
||||
|
||||
get_argv0:
|
||||
repne scasb
|
||||
scasb
|
||||
jne get_argv0
|
||||
|
||||
push es ; Open file
|
||||
pop ds
|
||||
mov dx,di
|
||||
mov ax,3d20h
|
||||
int 21h
|
||||
|
||||
xchg bx,ax ; Seek to ovr
|
||||
mov ax,4202h
|
||||
mov cx,0ffffh
|
||||
mov dx,-64000
|
||||
int 21h
|
||||
|
||||
push 0a000h ; Read picture
|
||||
pop ds
|
||||
mov ah,3fh
|
||||
mov cx,64000
|
||||
xor dx,dx
|
||||
int 21h
|
||||
|
||||
This is the 'backward' method:
|
||||
|
||||
We seek from the end of the file. It's good because we don't have to know the
|
||||
size of the main EXE file.
|
||||
|
||||
|
||||
IV. Chaining
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Perhaps this is the most interesting topic in this article... The base
|
||||
problem : we have a couple of EXE files (...a demo's parts...) and we
|
||||
want ONE NICE BIG EXE file. The most convenient way is renaming these files
|
||||
to *.DAT and writing a 'master' proggy which sequentially executes them. But
|
||||
then there are many files which isn't so elegant... The solution : an EXE
|
||||
loader must be written which stores the independent EXE files in itself
|
||||
(as overlays), and executes them. Unfortunately DOS doesn't have such a
|
||||
service :-(
|
||||
|
||||
1. Simple EXE loader
|
||||
|
||||
This works for non-overlayed EXE files only. The files to be executed must
|
||||
NOT open themselves for reading or writing.
|
||||
|
||||
Structure of this big EXE file:
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
<EFBFBD>Loader<EFBFBD> 1st EXE <20> 2nd EXE <20>...
|
||||
<EFBFBD> <20>(Overlay1)<29>(Overlay2)<29>
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
The loader's task to process each 'file':
|
||||
- Load the header to get info on the proggy
|
||||
- Load the body
|
||||
- Load relocation table and process it
|
||||
- Jump to the beginning of the program
|
||||
|
||||
The detailed process:
|
||||
- Reduce the loader's occupied memory to minimal
|
||||
- Open the loader file, seek to the start of the next program
|
||||
- Read the header (1ah bytes)
|
||||
- Create a PSP (there's a DOS function, but copying loader's PSP will do too)
|
||||
- Seek to the body's start
|
||||
- Read the body to the memory (Page Counter*512 bytes right after the
|
||||
newly created PSP - You can ignore the Partial Page field)
|
||||
- Seek to the relocation table's beginning
|
||||
- Load the relocation table and relocate the body (the table can be
|
||||
loaded in 4-byte steps to save space). One relocation item consists
|
||||
of two words: ReloSeg and ReloOffset. Process for one item:
|
||||
Add the body's segment address to ReloSeg (This will be a segment
|
||||
address, let's call it ReloSeg2), then add the body's segment to the
|
||||
word at ReloSeg2:ReloOffset.
|
||||
- Make the new PSP active
|
||||
- Redirect DOS exit function 4c that it could catch the terminating process
|
||||
- Set DS & ES to the new PSP, FS & GS to 0, SS to new PSP+Relative Initial
|
||||
SS, SP to Initial SP, other registers to 0
|
||||
- Jump to new PSP + Initial Relative CS:Initial IP
|
||||
|
||||
Of course these steps can be extended with safety and convenience services.
|
||||
For example, handling the TSR exit (27h) function. Let's say we have a
|
||||
resident modplayer, but normally it can't be killed from the memory...
|
||||
What should the loader do when a program wants to exit as TSR? It's
|
||||
enough to reserve the required memory for it, then create the next program's
|
||||
PSP after that. And when the loader exits, it should restore the whole
|
||||
interrupt table (which was saved in the beginning of the whole process ;-)
|
||||
|
||||
2. More complex EXE loader
|
||||
|
||||
This method allows self-overlaying files to run. The individual programs
|
||||
can read/write themselves without noticing that they're not alone on the
|
||||
disk but in the overlay area of a loader! Of course, it requires very
|
||||
much work... The file structure:
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
<EFBFBD>Loader<EFBFBD>EXE1<EFBFBD>EXE1's <20>EXE2<45>EXE2's <20>
|
||||
<EFBFBD> <20>body<64>overlay<61>body<64>overlay<61>...
|
||||
<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
<EFBFBD> <20> Overlay I <20> Overlay II <20>...
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
The 'soul' of this kind of loader is the redirected set of DOS functions.
|
||||
Among others, the 'File open' function (3dh) must be revised. If a running
|
||||
program wants to open itself, an appropriate file handle must be given
|
||||
back (... which should be a real, valid file handle; it initially points
|
||||
in the loader's overlay area to the beginning of the current process' EXE
|
||||
header...) Other functions to take over:
|
||||
seek (42h), close (3e), read (3f),
|
||||
write (40h), TSR exit (27h),
|
||||
normal exit (4c), and the exec.
|
||||
Most of these must check whether the call refers to the EXE itself or an
|
||||
external file. How to notice that a program wants to open itself? At least
|
||||
two ways must be maintained:
|
||||
|
||||
1. Check by the original filename
|
||||
2. Check by the enironment string
|
||||
|
||||
Actually I developed this system for putting HUGE demo parts together, not
|
||||
simple routines...
|
||||
|
||||
My chainer program is able to handle self-overlaying files. It can put into
|
||||
one file, for example, the followings: Verses, Hell, Timeless, No!, Epsilon,
|
||||
Doom, Face, and Scream Tracker. Also it was able to make a single EXE from
|
||||
the Project Angel unlinked version's EXE files. (Well, with a minor modifi-
|
||||
cation - right, Walken? :-) The reasons that I didn't include it to
|
||||
Imphobia:
|
||||
a) the source is too ugly at the moment and partially uncommented,
|
||||
b) the exapmle program for Imphobia (in my opinion) should be a nice demo
|
||||
effect, or at least something visible, not some creepy system code. If You
|
||||
want it, mail me, I will send it with the source.
|
||||
|
||||
V. Virtual file systems
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
What to do when a lot of data files are in use? Imagine a 'master' program
|
||||
which copies these into one file, then hooks DOS services (open, read, etc.)
|
||||
that other programs believe they use the original files - actually they
|
||||
will use this big file! It's very familiar with the complicated version
|
||||
of the EXE loader. Let's have a look at the problems of this method (these
|
||||
apply for the 2nd type EXE loader too):
|
||||
- Every file handle must be administrated by the 'kernel'.
|
||||
- The same file can be opened more than once.
|
||||
- It should be impossible to read when the 'virtual file handle' reached
|
||||
the end of the appropriate 'virtual file', although the big file is
|
||||
longer...
|
||||
|
||||
|
||||
Compressed virtual file systems
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
It looks like a simplified version of Stacker. (You know, modrn diskk comprs
|
||||
soin sftwarez ar nearli foOlproOf...) The 'master' program compresses the
|
||||
necessary data files and when the demo wants to open one, uncompresses it to
|
||||
the memory, and until the 'file' is opened, keeps it uncompressed. If the
|
||||
demo reads the file, the kernel simply copies the required amount of data.
|
||||
This system is not useful for handling big files because its memory require-
|
||||
ment.
|
||||
|
||||
Ervin/Abaddon
|
||||
|
||||
|
||||
52
study/sabre/os/files/Executables/EXE.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
offset length description comments
|
||||
----------------------------------------------------------------------
|
||||
0 word exe file signature usually 4d5a
|
||||
2 word length of last used sector in file modulo 512
|
||||
4 word size of file, incl. header in 512-pages
|
||||
6 word number of relocation table items
|
||||
8 word size of header in 16-byte paragraphs
|
||||
a word min. paragraphs needed above program in 16-byte paragraphs
|
||||
c word max. paragraphs needen above program in 16-byte paragraphs
|
||||
e word displacement of stack segment in module rel. to start of prog.
|
||||
10 word contents of SP reg. at entry
|
||||
12 word checksum 2's complement
|
||||
14 word contents of IP reg. at entry
|
||||
16 word displacement of code module rel. to start of prog.
|
||||
18 word offset to first relocation item in file rel. to start of prog.
|
||||
1a word overlay number 0 for resident prog.
|
||||
1c varies variable RESERVED place
|
||||
varies varies relocation table
|
||||
varies varies variable RESERVED place
|
||||
varies varies program and data space
|
||||
varies varies stack segment
|
||||
|
||||
The relocation table is a set of far pointers (eg: 1234:5678h) and it appears
|
||||
you just add the relocation factor to the value at that address. The relocation
|
||||
factor is the start segment of where the program is loaded.
|
||||
|
||||
Example:
|
||||
------------------------------------------------
|
||||
code segment
|
||||
start:
|
||||
mov ax,seg _myseg
|
||||
code ends
|
||||
|
||||
_myseg segment
|
||||
_myseg ends
|
||||
end start
|
||||
-------------------------------------------------
|
||||
|
||||
Start Stop Length Name Class
|
||||
|
||||
00000H 00002H 00003H CODE
|
||||
00010H 00010H 00000H _MYSEG
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
Note that _MYSEG is exactly one segment above CODE.
|
||||
|
||||
Generated output is B8 01 00; which is "mov ax,0001"
|
||||
|
||||
The fixup table for this file has a single entry, 0000:0001. Thus if the start
|
||||
of the program begins at segment 3562 then the "mov ax,0001" gets converted to
|
||||
"mov ax,3563".
|
||||
97
study/sabre/os/files/Executables/LIB.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
Document ID: Q79259
|
||||
|
||||
Product: Microsoft BASIC Compiler
|
||||
Title: Microsoft Library (.LIB) Format, Created by LIB.EXE
|
||||
|
||||
Updated: 27-DEC-1991
|
||||
Operating System Versions: 6.00 6.00B 7.00 7.10
|
||||
Operating Systems: MS-DOS
|
||||
|
||||
Summary:
|
||||
|
||||
This article describes the components of the Microsoft Library Format
|
||||
(for .LIB files created by the LIB.EXE Library Manager). The Microsoft
|
||||
Library Format is consistent between compatible Microsoft languages.
|
||||
While future library utilities will remain backward- compatible with
|
||||
the older library formats, the actual library format itself is subject
|
||||
to change. This information is taken from Chapter 5 of the "Microsoft
|
||||
C Developer's Toolkit Reference," which contains more in-depth
|
||||
information on the Microsoft Library Format.
|
||||
|
||||
This information applies to Microsoft QuickBasic versions 4.0, 4.0b,
|
||||
and 4.5 for MS-DOS, to Microsoft Basic Compiler versions 6.0 and 6.0b
|
||||
for MS-DOS, and to Microsoft Basic Professional Development System
|
||||
(PDS) versions 7.0 and 7.1 for MS-DOS.
|
||||
|
||||
More Information:
|
||||
|
||||
Library Header Record
|
||||
---------------------
|
||||
|
||||
Object code library .LIB files under MS-DOS always contain blocks of
|
||||
data in multiples of 512 bytes. The first record in the library is a
|
||||
library header. This record is structured the same as a Microsoft
|
||||
object-module-format (MS OMF) record. That is, the first byte of the
|
||||
record identifies the record's type, and the next two bytes specify
|
||||
the number of bytes remaining in the record. Note that the length
|
||||
field is byte-swapped (in other words, the low-order byte precedes the
|
||||
high-order byte). The record type for this library header is F0 hex
|
||||
(240 decimal).
|
||||
|
||||
Modules in a library always start at the beginning of a page. Page
|
||||
size is determined by adding three (one for the record type byte and
|
||||
two for the record length field itself) to the value in the record
|
||||
length field; thus the library header record always occupies exactly
|
||||
one page. Legal values for page size are given by the range of 2
|
||||
through the n, where n is a value from 4 through 15.
|
||||
|
||||
The four bytes immediately following the length field are a byte-
|
||||
swapped long integer specifying the byte offset within the library of
|
||||
the first block of the dictionary. The next two bytes are a byte-
|
||||
swapped word field that specifies the number of blocks in the
|
||||
dictionary. (Note: The Library Manager, LIB.EXE for MS-DOS, cannot
|
||||
create a library whose dictionary requires more than 251 512-byte
|
||||
pages.)
|
||||
|
||||
The next byte contains flags describing the library. One current flag
|
||||
definition is "0x01 = case sensitive". This applies to both regular
|
||||
and extended dictionaries. All other values are reserved for future
|
||||
use and should be 0. The remaining bytes in the library header record
|
||||
are not significant. This record deviates from the typical Microsoft
|
||||
OMF record in that the last byte is not used as a checksum on the rest
|
||||
of the record.
|
||||
|
||||
Object Modules
|
||||
--------------
|
||||
|
||||
The first object module in the library immediately follows the header.
|
||||
The first object module is followed in turn by all other object
|
||||
modules in the library. Each module is in Microsoft OMF. Individual
|
||||
modules are aligned so that they start at the beginning of a new page.
|
||||
If, as is commonly the case, a module does not occupy a number of
|
||||
bytes that is exactly a multiple of the page size, then its last block
|
||||
is padded with as many null bytes as are required to fill it. This
|
||||
special format is covered in detail in the "C Developer's Toolkit
|
||||
Reference."
|
||||
|
||||
Dictionary Blocks
|
||||
-----------------
|
||||
|
||||
The remaining blocks in the library compose the dictionary. The number
|
||||
of blocks in the dictionary is given in the library header. Dictionary
|
||||
length is in 512-byte blocks. Detailed information on the exact
|
||||
content and format of the dictionary are contained in the "C
|
||||
Developer's Toolkit Reference."
|
||||
|
||||
Extended Dictionary
|
||||
-------------------
|
||||
|
||||
The extended dictionary is optional and indicates dependencies between
|
||||
modules in the library. Versions of LIB.EXE earlier than version 3.09
|
||||
do not create an extended dictionary. The extended dictionary is
|
||||
placed at the end of the library. Again, see the "C Developer's
|
||||
Toolkit Reference" for details on the structure of the Extended
|
||||
Dictionary.
|
||||
|
||||
Additional reference words: 6.00 6.00b 7.00 7.10 4.00 4.00b 4.50
|
||||
129
study/sabre/os/files/Executables/LIBDICT.TXT
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
Document ID: Q71891
|
||||
|
||||
Product: Microsoft EXEMOD, EXEPACK, or LIB Utility
|
||||
Title: Dictionary Hashing Algorithm Used by the LIB Utility
|
||||
|
||||
Updated: 16-MAY-1991
|
||||
Operating System Versions: 3.0X 3.10 3.11 3.14 3.15 3.17 3.18 | 3.1
|
||||
Operating Systems: MS-DOS | OS/2
|
||||
|
||||
Summary:
|
||||
|
||||
The last part of each library produced by the Microsoft Library
|
||||
Manager (LIB) contains a dictionary that holds all the public symbols
|
||||
in the library. The hashing algorithm mentioned on page 63 of the
|
||||
"Microsoft C Developer's Toolkit Reference" is used to place data in
|
||||
the dictionary. The code required to implement the hashing algorithm
|
||||
is shown at the end of this article.
|
||||
|
||||
More Information:
|
||||
|
||||
The library dictionary is divided into pages that are 512 bytes long.
|
||||
Each page starts with a 37-byte bucket table, which contains 37
|
||||
separate offsets to the symbols in the rest of the page. The values in
|
||||
the buckets are multiplied by 2 to get the actual offset (since 1 byte
|
||||
can contain only 256 different values).
|
||||
|
||||
The hashing algorithm analyzes a symbol's name and produces two
|
||||
indexes (page index and bucket index) and two deltas (page index delta
|
||||
and bucket index delta). Using the offset contained in the bucket at
|
||||
bucket index in the page at page index, you must compare the symbol at
|
||||
that location with the one you are looking for.
|
||||
|
||||
If (due to symbol collision) you have not found the correct symbol,
|
||||
add the bucket index delta to the current bucket index, modulo 37, and
|
||||
try again. Continue until all the buckets in the current page are
|
||||
tried. Then, add the page index delta to the current page, modulo by
|
||||
the page count, and try all the buckets in that page starting at
|
||||
bucket index. Continue this process until all of the possible page and
|
||||
offset combinations have been tried.
|
||||
|
||||
For more information on the actual format of the symbols in the
|
||||
dictionary, and information on the format for the rest of the library,
|
||||
see the "Microsoft C Developer's Toolkit Reference."
|
||||
|
||||
Sample Code
|
||||
-----------
|
||||
|
||||
/* This code illustrates the hashing algorithm used by LIB */
|
||||
|
||||
/* Compile options needed: none
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define XOR ^
|
||||
#define MODULO %
|
||||
|
||||
char *symbol; /* Symbol to find (or to place) */
|
||||
int dictlength; /* Dictionary length in pages */
|
||||
int buckets; /* Number of buckets on one page */
|
||||
|
||||
char *pb; /* A pointer to the beginning of the symbol */
|
||||
char *pe; /* A pointer to the end of the symbol */
|
||||
int slength; /* Length of the symbol's name */
|
||||
|
||||
int page_index; /* Page Index */
|
||||
int page_index_delta; /* Page Index Delta */
|
||||
int bucket_index; /* Bucket Index */
|
||||
int bucket_index_delta; /* Bucket Index Delta */
|
||||
|
||||
unsigned c;
|
||||
|
||||
void hash(void)
|
||||
{
|
||||
page_index = 0;
|
||||
page_index_delta = 0;
|
||||
bucket_index = 0;
|
||||
bucket_index_delta = 0;
|
||||
|
||||
while( slength--)
|
||||
{
|
||||
c = *(pb++) | 32; /* Convert character to lower case */
|
||||
page_index = (page_index<<2) XOR c; /* Hash */
|
||||
bucket_index_delta = (bucket_index_delta>>2) XOR c; /* Hash */
|
||||
c = *(pe--) | 32;
|
||||
bucket_index = (bucket_index>>2) XOR c; /* Hash */
|
||||
page_index_delta = (page_index_delta<<2) XOR c; /* Hash */
|
||||
}
|
||||
/* Calculate page index */
|
||||
page_index = page_index MODULO dictlength;
|
||||
|
||||
/* Calculate page index delta */
|
||||
if( (page_index_delta = page_index_delta MODULO dictlength) == 0)
|
||||
page_index_delta = 1;
|
||||
|
||||
/* Calculate bucket offset */
|
||||
bucket_index = bucket_index MODULO buckets;
|
||||
|
||||
/* Calculate bucket offset delta */
|
||||
if( (bucket_index_delta = bucket_index_delta MODULO buckets) == 0)
|
||||
bucket_index_delta = 1;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int i;
|
||||
dictlength = 3;
|
||||
buckets = 37;
|
||||
|
||||
if ( (symbol = (char *) malloc( sizeof(char) * 4 )) == NULL )
|
||||
exit(1);
|
||||
|
||||
strcpy( symbol, "one");
|
||||
|
||||
for( i = 0; i < 2; i++ ) {
|
||||
slength = strlen(symbol);
|
||||
pb = symbol;
|
||||
pe = symbol + slength ;
|
||||
hash();
|
||||
printf("\npage_index: %2d page_index_delta: %d",
|
||||
page_index, page_index_delta);
|
||||
printf("\nbucket_index: %2d bucket_index_delta: %d",
|
||||
bucket_index, bucket_index_delta);
|
||||
strcpy( symbol, "two");
|
||||
}
|
||||
1894
study/sabre/os/files/Executables/LX.txt
Normal file
BIN
study/sabre/os/files/Executables/MicrosoftSymbolAndTypeInfo.pdf
Normal file
BIN
study/sabre/os/files/Executables/OBJ_FORM.ZIP
Normal file
BIN
study/sabre/os/files/Executables/OMF1.1.pdf
Normal file
320
study/sabre/os/files/Executables/OpenBSD-a.out.txt
Normal file
@@ -0,0 +1,320 @@
|
||||
A.OUT(5) OpenBSD Programmer's Manual A.OUT(5)
|
||||
|
||||
NAME
|
||||
a.out - format of executable binary files
|
||||
|
||||
SYNOPSIS
|
||||
#include <a.out.h>
|
||||
|
||||
DESCRIPTION
|
||||
The include file <a.out.h> declares three structures and several macros.
|
||||
The structures describe the format of executable machine code files
|
||||
(``binaries'') on the system.
|
||||
|
||||
A binary file consists of up to 7 sections. In order, these sections
|
||||
are:
|
||||
|
||||
exec header Contains parameters used by the kernel to load a binary
|
||||
file into memory and execute it, and by the link editor
|
||||
ld(1) to combine a binary file with other binary files.
|
||||
This section is the only mandatory one.
|
||||
|
||||
text segment Contains machine code and related data that are loaded
|
||||
into memory when a program executes. May be loaded
|
||||
read-only.
|
||||
|
||||
data segment Contains initialized data; always loaded into writable
|
||||
memory.
|
||||
|
||||
text relocations Contains records used by the link editor to update
|
||||
pointers in the text segment when combining binary
|
||||
files.
|
||||
|
||||
data relocations Like the text relocation section, but for data segment
|
||||
pointers.
|
||||
|
||||
symbol table Contains records used by the link editor to cross ref-
|
||||
erence the addresses of named variables and functions
|
||||
(``symbols'') between binary files.
|
||||
|
||||
string table Contains the character strings corresponding to the
|
||||
symbol names.
|
||||
|
||||
Every binary file begins with an exec structure:
|
||||
|
||||
struct exec {
|
||||
u_int32_t a_midmag;
|
||||
u_int32_t a_text;
|
||||
u_int32_t a_data;
|
||||
u_int32_t a_bss;
|
||||
u_int32_t a_syms;
|
||||
u_int32_t a_entry;
|
||||
u_int32_t a_trsize;
|
||||
u_int32_t a_drsize;
|
||||
};
|
||||
|
||||
The fields have the following functions:
|
||||
|
||||
a_midmag This field is stored in network byte-order so that binaries for
|
||||
machines with alternate byte orders can be distinguished. It
|
||||
has a number of sub-components accessed by the macros
|
||||
N_GETFLAG(), N_GETMID(),and N_GETMAGIC(), and set by the macro
|
||||
N_SETMAGIC().
|
||||
|
||||
|
||||
|
||||
The macro N_GETFLAG()() returns a few flags:
|
||||
|
||||
EX_DYNAMIC Indicates that the executable requires the services
|
||||
of the run-time link editor.
|
||||
|
||||
EX_PIC Indicates that the object contains position inde-
|
||||
pendent code. This flag is set by as(1) when given
|
||||
the -k flag and is preserved by ld(1) if necessary.
|
||||
|
||||
If both EX_DYNAMIC and EX_PIC are set, the object file is a po-
|
||||
sition independent executable image (e.g., a shared library),
|
||||
which is to be loaded into the process address space by the
|
||||
run-time link editor.
|
||||
|
||||
The macro N_GETMID() returns the machine-id. This indicates
|
||||
which machine(s) the binary is intended to run on.
|
||||
|
||||
N_GETMAGIC() specifies the magic number, which uniquely identi-
|
||||
fies binary files and distinguishes different loading conven-
|
||||
tions. The field must contain one of the following values:
|
||||
|
||||
OMAGIC The text and data segments immediately follow the head-
|
||||
er and are contiguous. The kernel loads both text and
|
||||
data segments into writable memory.
|
||||
|
||||
NMAGIC As with OMAGIC, text and data segments immediately fol-
|
||||
low the header and are contiguous. However, the kernel
|
||||
loads the text into read-only memory and loads the data
|
||||
into writable memory at the next page boundary after
|
||||
the text.
|
||||
|
||||
ZMAGIC The kernel loads individual pages on demand from the
|
||||
binary. The header, text segment and data segment are
|
||||
all padded by the link editor to a multiple of the page
|
||||
size. Pages that the kernel loads from the text seg-
|
||||
ment are read-only, while pages from the data segment
|
||||
are writable.
|
||||
|
||||
a_text Contains the size of the text segment in bytes.
|
||||
|
||||
a_data Contains the size of the data segment in bytes.
|
||||
|
||||
a_bss Contains the number of bytes in the ``bss segment'' and is used
|
||||
by the kernel to set the initial break (brk(2)) after the data
|
||||
segment. The kernel loads the program so that this amount of
|
||||
writable memory appears to follow the data segment and initial-
|
||||
ly reads as zeroes.
|
||||
|
||||
a_syms Contains the size in bytes of the symbol table section.
|
||||
|
||||
a_entry Contains the address in memory of the entry point of the pro-
|
||||
gram after the kernel has loaded it; the kernel starts the exe-
|
||||
cution of the program from the machine instruction at this ad-
|
||||
dress.
|
||||
|
||||
a_trsize Contains the size in bytes of the text relocation table.
|
||||
|
||||
a_drsize Contains the size in bytes of the data relocation table.
|
||||
|
||||
The a.out.h include file defines several macros which use an exec struc-
|
||||
ture to test consistency or to locate section offsets in the binary file.
|
||||
|
||||
N_BADMAG(exec) Non-zero if the a_magic field does not contain a recog-
|
||||
nized value.
|
||||
|
||||
N_TXTOFF(exec) The byte offset in the binary file of the beginning of
|
||||
|
||||
the text segment.
|
||||
|
||||
N_SYMOFF(exec) The byte offset of the beginning of the symbol table.
|
||||
|
||||
N_STROFF(exec) The byte offset of the beginning of the string table.
|
||||
|
||||
Relocation records have a standard format which is described by the
|
||||
relocation_info structure:
|
||||
|
||||
struct relocation_info {
|
||||
int r_address;
|
||||
unsigned int r_symbolnum : 24,
|
||||
r_pcrel : 1,
|
||||
r_length : 2,
|
||||
r_extern : 1,
|
||||
r_baserel : 1,
|
||||
r_jmptable : 1,
|
||||
r_relative : 1,
|
||||
r_copy : 1;
|
||||
};
|
||||
|
||||
The relocation_info fields are used as follows:
|
||||
|
||||
r_address Contains the byte offset of a pointer that needs to be link-
|
||||
edited. Text relocation offsets are reckoned from the start
|
||||
of the text segment, and data relocation offsets from the
|
||||
start of the data segment. The link editor adds the value
|
||||
that is already stored at this offset into the new value
|
||||
that it computes using this relocation record.
|
||||
|
||||
r_symbolnum Contains the ordinal number of a symbol structure in the
|
||||
symbol table (it is not a byte offset). After the link edi-
|
||||
tor resolves the absolute address for this symbol, it adds
|
||||
that address to the pointer that is undergoing relocation.
|
||||
(If the r_extern bit is clear, the situation is different;
|
||||
see below.)
|
||||
|
||||
r_pcrel If this is set, the link editor assumes that it is updating
|
||||
a pointer that is part of a machine code instruction using
|
||||
pc-relative addressing. The address of the relocated point-
|
||||
er is implicitly added to its value when the running program
|
||||
uses it.
|
||||
|
||||
r_length Contains the log base 2 of the length of the pointer in
|
||||
bytes; 0 for 1-byte displacements, 1 for 2-byte displace-
|
||||
ments, 2 for 4-byte displacements.
|
||||
|
||||
r_extern Set if this relocation requires an external reference; the
|
||||
link editor must use a symbol address to update the pointer.
|
||||
When the r_extern bit is clear, the relocation is ``local'';
|
||||
the link editor updates the pointer to reflect changes in
|
||||
the load addresses of the various segments, rather than
|
||||
changes in the value of a symbol (except when r_baserel is
|
||||
also set, see below). In this case, the content of the
|
||||
r_symbolnum field is an n_type value (see below); this type
|
||||
field tells the link editor what segment the relocated
|
||||
pointer points into.
|
||||
|
||||
r_baserel If set, the symbol, as identified by the r_symbolnum field,
|
||||
is to be relocated to an offset into the Global Offset
|
||||
Table. At run-time, the entry in the Global Offset Table at
|
||||
this offset is set to be the address of the symbol.
|
||||
|
||||
r_jmptable If set, the symbol, as identified by the r_symbolnum field,
|
||||
is to be relocated to an offset into the Procedure Linkage
|
||||
|
||||
Table.
|
||||
|
||||
r_relative If set, this relocation is relative to the (run-time) load
|
||||
address of the image this object file is going to be a part
|
||||
of. This type of relocation only occurs in shared objects.
|
||||
|
||||
r_copy If set, this relocation record identifies a symbol whose
|
||||
contents should be copied to the location given in
|
||||
r_address. The copying is done by the run-time link editor
|
||||
from a suitable data item in a shared object.
|
||||
|
||||
Symbols map names to addresses (or more generally, strings to values).
|
||||
Since the link editor adjusts addresses, a symbol's name must be used to
|
||||
stand for its address until an absolute value has been assigned. Symbols
|
||||
consist of a fixed-length record in the symbol table and a variable-
|
||||
length name in the string table. The symbol table is an array of nlist
|
||||
structures:
|
||||
|
||||
struct nlist {
|
||||
union {
|
||||
char *n_name;
|
||||
long n_strx;
|
||||
} n_un;
|
||||
unsigned char n_type;
|
||||
char n_other;
|
||||
short n_desc;
|
||||
unsigned long n_value;
|
||||
};
|
||||
|
||||
The fields are used as follows:
|
||||
|
||||
n_un.n_strx Contains a byte offset into the string table for the name of
|
||||
this symbol. When a program accesses a symbol table with
|
||||
the nlist(3) function, this field is replaced with the
|
||||
n_un.n_name field, which is a pointer to the string in memo-
|
||||
ry.
|
||||
|
||||
n_type Used by the link editor to determine how to update the sym-
|
||||
bol's value. The n_type field is broken down into three
|
||||
sub-fields using bitmasks. The link editor treats symbols
|
||||
with the N_EXT type bit set as ``external'' symbols and per-
|
||||
mits references to them from other binary files. The N_TYPE
|
||||
mask selects bits of interest to the link editor:
|
||||
|
||||
N_UNDF An undefined symbol. The link editor must locate an
|
||||
external symbol with the same name in another binary
|
||||
file to determine the absolute value of this symbol.
|
||||
As a special case, if the n_value field is non-zero
|
||||
and no binary file in the link-edit defines this
|
||||
symbol, the link editor will resolve this symbol to
|
||||
an address in the bss segment, reserving an amount
|
||||
of bytes equal to n_value. If this symbol is unde-
|
||||
fined in more than one binary file and the binary
|
||||
files do not agree on the size, the link editor
|
||||
chooses the greatest size found across all binaries.
|
||||
|
||||
N_ABS An absolute symbol. The link editor does not update
|
||||
an absolute symbol.
|
||||
|
||||
N_TEXT A text symbol. This symbol's value is a text ad-
|
||||
dress and the link editor will update it when it
|
||||
merges binary files.
|
||||
|
||||
N_DATA A data symbol; similar to N_TEXT but for data ad-
|
||||
dresses. The values for text and data symbols are
|
||||
not file offsets but addresses; to recover the file
|
||||
offsets, it is necessary to identify the loaded ad-
|
||||
dress of the beginning of the corresponding section
|
||||
and subtract it, then add the offset of the section.
|
||||
|
||||
N_BSS A bss symbol; like text or data symbols but has no
|
||||
corresponding offset in the binary file.
|
||||
|
||||
N_FN A filename symbol. The link editor inserts this
|
||||
symbol before the other symbols from a binary file
|
||||
when merging binary files. The name of the symbol
|
||||
is the filename given to the link editor, and its
|
||||
value is the first text address from that binary
|
||||
file. Filename symbols are not needed for link
|
||||
editing or loading, but are useful for debuggers.
|
||||
|
||||
The N_STAB mask selects bits of interest to symbolic debug-
|
||||
gers such as gdb(1); the values are described in stab(5).
|
||||
|
||||
n_other This field provides information on the nature of the symbol
|
||||
independent of the symbol's location in terms of segments as
|
||||
determined by the n_type field. Currently, the lower 4 bits
|
||||
of the n_other field hold one of two values: AUX_FUNC and
|
||||
AUX_OBJECT (see <link.h> for their definitions). AUX_FUNC
|
||||
associates the symbol with a callable function, while
|
||||
AUX_OBJECT associates the symbol with data, irrespective of
|
||||
their locations in either the text or the data segment.
|
||||
This field is intended to be used by ld(1) for the construc-
|
||||
tion of dynamic executables.
|
||||
|
||||
n_desc Reserved for use by debuggers; passed untouched by the link
|
||||
editor. Different debuggers use this field for different
|
||||
purposes.
|
||||
|
||||
n_value Contains the value of the symbol. For text, data and bss
|
||||
symbols, this is an address; for other symbols (such as de-
|
||||
bugger symbols), the value may be arbitrary.
|
||||
|
||||
The string table consists of an u_int32_t length followed by null-termi-
|
||||
nated symbol strings. The length represents the size of the entire table
|
||||
in bytes, so its minimum value (or the offset of the first string) is al-
|
||||
ways 4 on 32-bit machines.
|
||||
|
||||
SEE ALSO
|
||||
as(1), gdb(1), ld(1), brk(2), execve(2), nlist(3), core(5),
|
||||
link(5), stab(5)
|
||||
|
||||
HISTORY
|
||||
The a.out.h include file appeared in Version 7 AT&T UNIX.
|
||||
|
||||
BUGS
|
||||
Nobody seems to agree on what bss stands for.
|
||||
|
||||
New binary file formats may be supported in the future, and they probably
|
||||
will not be compatible at any level with this ancient format.
|
||||
|
||||
OpenBSD 2.6 June 5, 1993 5
|
||||
BIN
study/sabre/os/files/Executables/PE.pdf
Normal file
86
study/sabre/os/files/Executables/SYS.txt
Normal file
@@ -0,0 +1,86 @@
|
||||
===========================================================================
|
||||
From: BRIAN FRASER Refer#: NONE
|
||||
To: MATHIEU BOUCHARD Recvd: NO
|
||||
Subj: .SYS format. Conf: (99) 80xxxProgr
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Main Header:
|
||||
|
||||
00h word - Link to next driver, offset
|
||||
02h word - Link to next driver, segment
|
||||
04h word - Device Attribute
|
||||
06h word - Strategy entry point, offset
|
||||
0ah word - interrupt entry point, offset
|
||||
-- Character device --
|
||||
0ch 8 bytes - Logical Name
|
||||
-- Block device --
|
||||
0ch byte - Number of units
|
||||
|
||||
|
||||
Header Attribute word:
|
||||
bit 15 - 1= Character device; 0= Block device
|
||||
bit 14 - 1= IOCTL read and write supported
|
||||
-- Character device --
|
||||
bit 13 - 1= Output until busy supported
|
||||
-- Block device --
|
||||
bit 13 - 1= Check BIOS to determine media characteristics; 0= Media ID
|
||||
should be used instead
|
||||
bit 12 - should be 0
|
||||
bit 11 - 1= if open/close/removable media supported
|
||||
bit 7-10 - 0
|
||||
bit 6 - 1= if generic IOCTL and get/set logical drive supported
|
||||
bit 5 - 0
|
||||
bit 4 - 1= if CON driver and int 29h fast-output supported
|
||||
bit 3 - 1= if current CLOCK$ device
|
||||
bit 2 - 1= if current NULL device
|
||||
-- Character device --
|
||||
bit 1 - 1= if standard output device (stdout)
|
||||
-- Block device --
|
||||
bit 1 - 1= if 32bit sector addressing supported
|
||||
bit 0 - 1= if current standard input device (stdin)
|
||||
|
||||
|
||||
Strategy Request Header:
|
||||
00h byte - length of request header
|
||||
01h byte - unit number for this request
|
||||
02h byte - request headers command code
|
||||
03h word - drivers return status
|
||||
05h 8 bytes - ? (reserved)
|
||||
|
||||
The rest of the header varies depending on what function is being called.
|
||||
|
||||
I would think it's best to find a book, as I don't really want to type out all
|
||||
the different headers for each function. :)
|
||||
|
||||
This book I am using is Advanced MS-DOS, Second Ed. Provided, it's a little out
|
||||
of date, but alot of the information is still the same. Plus, I got it for 8
|
||||
bucks.. Can't complain for that price! :) Check out the book list.
|
||||
|
||||
|
||||
Heres just a little info on what the above headers are for...
|
||||
|
||||
There are two different kinds of device drivers. Character, and Block.
|
||||
Character devices handle 1 character at a time, while Block devices deal with
|
||||
Blocks of data. Character devices can have a logical name like "MYSYS", which
|
||||
can be used like "CON" or "PRN" etc.. Block devices use units (drives), which
|
||||
are assigned upon install.
|
||||
|
||||
The Main Header is the first few bytes of the SYS file, The link to next driver
|
||||
is to be -1:-1 (or FFFF:FFFF) unless there is more then one driver in this SYS
|
||||
file, then you set this to the next driver in the chain. BUT, the last driver
|
||||
must have FFFF:FFFF as the next driver, or you have big problems! :)
|
||||
|
||||
The Device attribute is fairly strate forward.
|
||||
|
||||
The strategy routine is a routine that is called my DOS with the address of the
|
||||
Request Header. All this routine has to do is save the address in a local
|
||||
memory location.
|
||||
|
||||
The interrupt routine is then called after the strategy routine. The interrupt
|
||||
routine process the request header, and performs the requested function, and
|
||||
returns.
|
||||
|
||||
If you can't find a book.. Maybe I'll type out the return attributes, and the
|
||||
info for each function.
|
||||
|
||||
Brian
|
||||
1584
study/sabre/os/files/Executables/a.out.txt
Normal file
BIN
study/sabre/os/files/Executables/dwarf-v1.1.0.pdf
Normal file
7
study/sabre/os/files/Executables/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
274
study/sabre/os/files/Executables/omf.script
Normal file
@@ -0,0 +1,274 @@
|
||||
:gdoc sec='Copyright IBM Corp. 1991'.
|
||||
:prolog.
|
||||
:docprof
|
||||
ldrdots='yes'
|
||||
duplex='no'.
|
||||
:title.
|
||||
:tline.IBM OS/2 32 bit Object Module Format (OMF)
|
||||
:tline.and Linear eXecutable Module Format (LX)
|
||||
:tline.&rbl.
|
||||
:tline.Draft 5
|
||||
:etitle.
|
||||
.*
|
||||
:date.
|
||||
.*
|
||||
.*
|
||||
:address.
|
||||
:aline.Boca Programming Center
|
||||
:aline.Boca Raton, Florida
|
||||
:eaddress
|
||||
:date.
|
||||
:eprolog.
|
||||
:frontm.
|
||||
:tipage.
|
||||
:lblbox.Purpose of this document
|
||||
:p.
|
||||
THIS DOCUMENT PROVIDED BY IBM SHALL BE PROVIDED ON AN "AS IS" BASIS
|
||||
WITHOUT ANY WARRANTY OF ANY KIND EITHER EXPRESS OR IMPLIED.
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE EXPRESSLY DISCLAIMED.
|
||||
:p.
|
||||
FURTHERMORE, THIS DOCUMENTATION IS IN A PRELIMINARY FORM; IS NOT
|
||||
COMPLETE; HAS NOT YET BEEN TESTED, VALIDATED OR REVIEWED; MAY CONTAIN
|
||||
ERRORS, OMISSIONS, INACCURACIES OR THE LIKE; AND IS SUBJECT TO BEING
|
||||
CHANGED, REVISED OR SUPERSEDED IN WHOLE OR IN PART BY IBM.
|
||||
IBM DOES NOT ASSUME ANY RESPONSIBILITY TO NOTIFY ANY PARTIES, COMPANIES,
|
||||
USERS, AND OR OTHERS OF DEFECTS, DEFICIENCIES, CHANGES, ERRORS OR OTHER
|
||||
FAILINGS OR SHORTCOMING OF THE DOCUMENTATION.
|
||||
:p.
|
||||
RECIPIENT'S USE OF THIS DOCUMENT IS LIMITED TO RECIPIENT'S PERSONAL USE
|
||||
FOR THE SOLE PURPOSE OF CREATING TOOLS FOR THE OS/2:fnref refid=ibm.
|
||||
OPERATING SYSTEM.
|
||||
:elblbox
|
||||
:fn id=ibm.
|
||||
OS/2 is a Registered Trademark of International Business Machines Corp.
|
||||
:efn.
|
||||
:toc.
|
||||
:figlist.
|
||||
:revision id=r1 char='|' run=yes
|
||||
:revision id=r2 char='X' run=yes
|
||||
:revision id=r3 char='B' run=yes
|
||||
:revision id=r4 char='D' run=yes
|
||||
.* :rev refid=r1.
|
||||
.* :p.This line is marked for revision.
|
||||
.* :erev refid=r1.
|
||||
:body.
|
||||
:lblbox.Major changes to this document
|
||||
:ul
|
||||
:rev refid=r1.
|
||||
:li.Draft 1 = Combined information from several documents into one.
|
||||
:li.Draft 2 = Added Comments from Lexington and Toronto.
|
||||
:li.Draft 3 = Added the Linear Executable format (LX).
|
||||
:eul
|
||||
:elblbox
|
||||
:erev refid=r1.
|
||||
:h1.Introduction
|
||||
:p.This document is intended to describe the interface that is
|
||||
used by language translators and generators as their intermediate
|
||||
:rev refid=r1.
|
||||
output to the linker for the 32-bit OS/2 operating system.
|
||||
:erev refid=r1.
|
||||
The linker will generate the executable module that is used by
|
||||
the loader to invoke the .EXE and .DLL programs at execution time.
|
||||
:h1.THE 32-BIT OBJECT MODULE FORMAT
|
||||
:fig place=inline.
|
||||
:cgraphic.
|
||||
Record Format:
|
||||
|
||||
All object records conform to the following format:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1 byte 2 byte
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---
|
||||
<20>Record <20> Record <20>
|
||||
<20>Type <20> Length <20>
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---
|
||||
|
||||
<------ record length in bytes -------->
|
||||
|
||||
<variable length> 1 byte
|
||||
--<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
||||
<20> Record <20>Chk Sum<75>
|
||||
<20> Contents <20>or 0 <20>
|
||||
--<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
:ecgraphic
|
||||
:figcap.Standard object module record format
|
||||
:figdesc.
|
||||
:p.The Record type field is a 1-byte field containing the
|
||||
hexadecimal number that identifies the type of object record.
|
||||
The format is determined by the least significant bit of the
|
||||
RecTyp field.
|
||||
Note that this does not govern Use32/Use16
|
||||
segment attributes; it simply specifies the size of certain numeric
|
||||
fields within the record.
|
||||
An odd RecTyp indicates that 32-bit
|
||||
values are present; the fields affected are described with each
|
||||
record.
|
||||
:p.
|
||||
:rev refid=r1.
|
||||
An entire record occupies RecLength + 3 bytes.
|
||||
:erev refid=r1.
|
||||
The record length does not include the count for the record type and
|
||||
record length fields.
|
||||
Unless otherwise noted within the record definition, the record length
|
||||
should not exceed 1024 bytes.
|
||||
:p.
|
||||
The byte sum over the entire record, ignoring overflow, is zero.
|
||||
:p.
|
||||
The record contents are determined by the record type.
|
||||
:efig.
|
||||
:h2.Frequent Object Record Subfields
|
||||
:p.
|
||||
Certain subfields appear frequently; the format of such fields is
|
||||
described next.
|
||||
:p.
|
||||
:h3.Names
|
||||
:p.Name strings are encoded as an 8-bit unsigned count followed by a
|
||||
string of &odq.count&cdq. characters. The character set is usually
|
||||
some ASCII subset. A null name is specified by a single byte
|
||||
of 0 (indicating a string of length zero).
|
||||
:p.
|
||||
:h3.Indexed References
|
||||
:p.Certain items are ordered by occurrence, and referenced by index
|
||||
(starting index is 1). Index fields can contain 0, indicating
|
||||
not-present, or values from 1 through 7FFF. The index is encoded
|
||||
as 1 or 2 bytes and a 16-bit value is obtained as follows&colon.
|
||||
.fo off
|
||||
.in +10
|
||||
|
||||
if (first_byte & 0x80)
|
||||
index_word = (first_byte & 7F) * 0x100 + second_byte;
|
||||
else
|
||||
index_word = first_byte
|
||||
.in -10
|
||||
.fo on
|
||||
:p.
|
||||
:h4.Type indices
|
||||
:p.
|
||||
The type index is treated as an index field when a record is parsed
|
||||
(occupies one or two bytes, occurs in PUBDEF, COMDEF,
|
||||
EXTDEF records).
|
||||
They are encoded as described under indexed references.
|
||||
:p.
|
||||
NOTE&colon. At present, no type checking is done by the linker.
|
||||
If any link-time semantics are defined, that information will
|
||||
be recorded somewhere within this document.
|
||||
:p.
|
||||
:h4.Ordered Collections
|
||||
:p.
|
||||
Certain records and record groups are ordered; the ordering is
|
||||
obtained from the order of the record types within the file together
|
||||
with the ordering of repeated fields within these records.
|
||||
Such ordered collections are referenced by index, counting from 1
|
||||
(index 0 indicates unknown or decline-to-state).
|
||||
:p.The ordered collections are&colon.
|
||||
:ul.
|
||||
:li.NAMES: ordered by LNAMES record and names within each.
|
||||
Referenced as a Name Index.
|
||||
:li.LOGICAL SEGMENTS: ordered by SEGDEF records in file.
|
||||
Referenced as a Segment Index.
|
||||
:li.GROUPS: ordered by GRPDEF of records in file.
|
||||
Referenced as a Group Index.
|
||||
:rev refid=r1.
|
||||
:li.External symbols: ordered by EXTDEF and COMDEF
|
||||
:erev refid=r1.
|
||||
records and symbols within each.
|
||||
Referenced as an External Index (in FIXUPs).
|
||||
:eul.
|
||||
:p.
|
||||
:h3.Numeric 2 and 4 byte fields
|
||||
:p.Words and double words (16 and 32 bit quantities) are stored
|
||||
in Intel byte order (lowest address is least significant).
|
||||
:p.Certain records, notably SEGDEF, PUBDEF, LINNUM, LEDATA,
|
||||
LIDATA, FIXUPP and MODEND, contain size, offset, and
|
||||
displacement values which may be 32 bit quantities for Use32 segments.
|
||||
The encoding is as follows.
|
||||
:ul.
|
||||
:li.When the least significant bit of the record type byte is
|
||||
set (ie record type is an odd number), the numeric fields are 4 bytes.
|
||||
:li.When the least significant bit of the record type byte is
|
||||
clear, the fields occupy 2 bytes (16 bit Object Module Format).
|
||||
The values are zero-extended when applied to Use32 segments.
|
||||
:eul.
|
||||
:p.See the description of SEGDEF records for an explanation of
|
||||
Use16/Use32 segments.
|
||||
.***************
|
||||
:h2.Order of records
|
||||
:p.
|
||||
The record order is chosen so that bind/link passes through an object
|
||||
module are minimized. This differs from the previous
|
||||
less specific ordering in that all symbolic information (in particular,
|
||||
all export and public symbols) must occur at the start of the object
|
||||
module.
|
||||
This order is recommended but not mandatory.
|
||||
.cp 1i
|
||||
:ol.
|
||||
:lp.:hp1.Identifier record(s)&colon.:ehp1.
|
||||
:li.:hp2.Must be the first record.:ehp2.
|
||||
:rev refid=r1.
|
||||
:li.THEADR
|
||||
:erev refid=r1.
|
||||
.sk
|
||||
:lp.:hp1.Records processed by Link Pass one&colon.:ehp1.
|
||||
:li.:hp2.May occur in any order but must precede the Link pass separator
|
||||
if it is present.:ehp2.
|
||||
:li.COMENT identifying object format and extensions
|
||||
:li.COMENT any, other than link pass separator comment.
|
||||
:li.LNAMES providing ordered name list
|
||||
:li.SEGDEF providing ordered list of program segments
|
||||
:li.GRPDEF providing ordered list of logical segments
|
||||
:li.PUBDEF locating and naming public symbols
|
||||
:li.COMDEF and EXTDEF records.
|
||||
:ul.
|
||||
:li.This group of records is indexed together, so External Index fields
|
||||
in FIXUPP records may refer to any of the record types listed.
|
||||
:eul.
|
||||
.sk
|
||||
:lp.:hp1.Link pass separator (optional)&colon.:ehp1.
|
||||
:li.COMENT class A2 indicating that pass 1 of the linker is complete.
|
||||
When this record is encountered, LINK immediately starts Pass 2; no
|
||||
records after this comment are read in Pass 1.
|
||||
All the above listed records must come before this comment record.
|
||||
:p.For greater linking speed, all LIDATA, LEDATA, FIXUPP and
|
||||
LINNUM records should come after the A2 comment record, but this is
|
||||
not required.
|
||||
In LINK, Pass 2 begins again at the start of the object module, so
|
||||
LIDATA records, etc., are processed in Pass 2 no matter where they
|
||||
are placed in the object module.
|
||||
.sk
|
||||
:lp.:hp1.Records ignored by link pass one and processed by link pass
|
||||
two&colon.:ehp1.
|
||||
:li.LIDATA, LEDATA or COMDAT records followed by applicable FIXUPP records.
|
||||
:li.FIXUPPs containing THREADs only.
|
||||
:li.LINNUM providing line number to program code
|
||||
or data association.
|
||||
.br
|
||||
:lp.:hp1.Terminator:ehp1.
|
||||
:li.MODEND indicating end of module with optional start address.
|
||||
:eol.
|
||||
.********************
|
||||
.** embedded record types in type sequence
|
||||
.im theadr
|
||||
.im coment
|
||||
.im modend
|
||||
.im extdef
|
||||
.im pubdef
|
||||
.im linnum
|
||||
.im lnames
|
||||
.im segdef
|
||||
.im grpdef
|
||||
.im fixupp
|
||||
.im ledata
|
||||
.im lidata
|
||||
.im comdef
|
||||
.im comdat
|
||||
.im exe1
|
||||
.im exe2
|
||||
.im exe3
|
||||
.pa
|
||||
.pa
|
||||
:egdoc.
|
||||
|
||||
1133
study/sabre/os/files/FileSystems/AFS_info.txt
Normal file
BIN
study/sabre/os/files/FileSystems/Bill_Earl_LSMWS.pdf
Normal file
BIN
study/sabre/os/files/FileSystems/ClassHierarchy.pdf
Normal file
@@ -0,0 +1,73 @@
|
||||
<html><head>
|
||||
<title>HPFS: Application Programs and the HPFS</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>Application Programs and the HPFS</h1>
|
||||
</center>
|
||||
|
||||
Each of the OS/2 releases thus far have carried with them a major
|
||||
discontinuity for application programmers who teamed their trade in the
|
||||
MS-DOS environment. In OS/2 1.0, such programmers were faced for the first
|
||||
time with virtual memory, multitasking, inter-process communications, and
|
||||
the protected mode restrictions on addressing and direct control of the
|
||||
hardware and were challenged to master powerful new concepts such as
|
||||
threading and dynamic linking. In OS/2 Version 1.1, the stakes were raised
|
||||
even fufiher. Programmers were offered a powerful hardware-independent
|
||||
graphical user interface but had to restructure their applications
|
||||
drastically for an event-driven environment based on objects and message
|
||||
passing. In OS/2 Version 1.2, it is time for many of the file- oriented
|
||||
programming habits and assumptions carried forward from the MS-DOS
|
||||
environment to fall by the wayside. An application that wishes to take
|
||||
full advantage of the HPFS must allow for long, free-form, mixed-case
|
||||
filenames and paths with few restrictions on punctuation and must be
|
||||
sensitive to the presence of EAs and ACLs.
|
||||
<p>
|
||||
After all, if EAs are to be of any use, it won't suffice for applications
|
||||
to update a file by renaming the old file and creating a new one without
|
||||
also copying the EAs. But the necessary changes for OS/2 Version 1.2 are
|
||||
not tricky to make. A new API function, DosCopy, helps applications create
|
||||
backups--it essentially duplicates an existing file together with its EAs.
|
||||
EAs can also be manipulated explicitly with DosQFileInfo DosSetFileInfo
|
||||
DosQPathlnfo and DosSetPathInfo. A program should call DosQSysInfo at run
|
||||
time to find the maximum possible path length for the system and ensure
|
||||
that all buffers used by DosChDir DosQCurDir and related functions are
|
||||
sufficiently large. Similarly the buffers used by DosOpen DosMove
|
||||
DosGetModName, DosFindFirst D DosFindNext and like functions must allow for
|
||||
longer filenames. Any logic that folds cases in filenames or tests for the
|
||||
occurrence of only one dot delimiter in a filename must be rethought or
|
||||
eliminated. The other changes in the API will not affect the average
|
||||
application. The functions DosQFileInfo DosFindFirst and DosFindNext now
|
||||
retain all three sets of times and dates (created last accessed last
|
||||
motified) for a file on an HPFS volume but few programs are concerned with
|
||||
time and date stamps anyway. DosQFslnfo is used to obtain volume labels or
|
||||
disk characteristics just as before and the use of DosSetFsInfo for volume
|
||||
labels is unchanged. There are a few totally new API functions such as
|
||||
DosFsCtl (analogous to DosDevlOCtl but used for communication between an
|
||||
application and an FSD) DosFsAttach (a sort of explicit mount call) and
|
||||
DosQFsAttach (determines which FSD owns a volume) these are intended mainly
|
||||
for use by disk utility program. In order to prevent old OS/2 applications
|
||||
and MS-DOS applications running in the DOS box from inadvertently damaging
|
||||
HPFS files a new flag bit has been defined in the EXE file header that
|
||||
indicates whether an application is HPFS-aware. If this bit is not set the
|
||||
application will only be able to search for open or create files on HPFS
|
||||
volumes that are compatible with the FAT' file system's 8.3 naming conventions.
|
||||
lf the bit is set OS/2 allows access to all files on an HPFS volume because
|
||||
it assumes that the program knows how to handle long free-form filenames and
|
||||
will take the responsibility of conserving a file's EAs and ACLs.
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
< <a href="faultol.html">[Fault Tolerance]</a> |
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="sum.html">[Summary]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
43
study/sabre/os/files/FileSystems/DesignGoalsHPFS/design.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<html><head>
|
||||
<title>HPFS: Design</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>
|
||||
Design Goals and Implementation of the<br>
|
||||
New High Performance File System
|
||||
</h1>
|
||||
</center>
|
||||
|
||||
The High Performance File System (hereafter HPFS), which is making its first
|
||||
appearance in the OS/2 operating system Version 1.2, had its genesis in the
|
||||
network division of Microsoft and was designed by Gordon Letwin, the chief
|
||||
architect of the OS/2 operating system. The HPFS has been designed to meet
|
||||
the demands of increasingly powerful PC's, fixed disks, and networks for many
|
||||
years to come and to serve as a suitable platform for object-oriented languages,
|
||||
applications, and user interfaces.
|
||||
The HPFS is a complex topic because it incorporates three distinct yet
|
||||
interrelated file system issues. First, the HPFS is a way of organizing data
|
||||
on a random access block storage device. Second, it is a software module that
|
||||
translates file-oriented requests from an application program into more
|
||||
primitive requests that a device driver can understand, using a variety of
|
||||
creative techniques to maximize performance. Third, the HPFS is a practical
|
||||
illustration of an important new OS/2 feature known as Installable File Systems.
|
||||
This article introduces the three aspects of the HPFS. But first, it puts the
|
||||
HPFS in perspective by reviewing some of the problems that led to the system's
|
||||
existence.
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="fat.html">[FAT File System]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
91
study/sabre/os/files/FileSystems/DesignGoalsHPFS/dirs.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<html><head>
|
||||
<title>HPFS: Directories</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>Directories</h1>
|
||||
</center>
|
||||
|
||||
Directories like files are anchored on Fnodes. A pointer to the Fnode for
|
||||
the root directory is found in the Super Block The Anodes for directories
|
||||
other than the root are reached through subdirectory entries in their parent
|
||||
directories. Directories can grow to any size and are built up from 2Kb
|
||||
directory blocks, which are allocated as four consecutive sectors on the disk.
|
||||
The file system attempts to allocate directory blocks in the directory band,
|
||||
which is located at or near the seek center of the disk. Once the directory
|
||||
band is full, the directory blocks are allocated wherever space is available.
|
||||
Each 2Kb directory block contains from one to many directory entries.
|
||||
A directory entry contains several fields, including time and date stamps,
|
||||
an Fnode pointer, a usage count for use by disk maintenance programs, the
|
||||
length of the file or directory name, the name itself, and a B-Tree pointer.
|
||||
Each entry begins with a word that contains the length of the entry. This
|
||||
provides for a variable amount of flex space at the end of each entry, which
|
||||
can be used by special versions of the file system and allows the directory
|
||||
block to be traversed very quickly (<a href="#fig5.html">Figure 5</a>).
|
||||
The number of entries in a directory block varies with the length of names.
|
||||
If the average filename length is 13 characters, an average directory block
|
||||
will hold about 40 entries.
|
||||
<p>
|
||||
|
||||
The entries in a directory block are sorted by the binary lexical order of
|
||||
their name fields (this happens to put them in alphabetical order for the US.
|
||||
alphabet). The last entry in a directory block is a dummy record that marks
|
||||
the end of the block. When a directory gets too large to be stored in one
|
||||
block, it increases in size by the addition of 2Kb blocks that are organized
|
||||
as a B-Tree (see B-T tees and B+ Trees ). When searching for a specific name,
|
||||
the file system traverses a directory block until it either finds a match or
|
||||
finds a name that is lexically greater than the target. In the latter case,
|
||||
the file system extracts the Tree pointer from the entry. If there is no
|
||||
pointer, the search failed otherwise the file system follows the pointer to
|
||||
the next directory block in the tree and continues the search. A little
|
||||
back-of-the-envelope arithmetic yields some impressive statistics. Assuming
|
||||
40 entries per block, a two-level tree of directory blocks can hold 1640
|
||||
directory entries and a three-level tree can hold an astonishing 65,640 entries.
|
||||
In other words, a particular file can be found (or shown not to exist) in a
|
||||
typical directory of 65,640 files with a maximum of three disk hits--the
|
||||
actual number of disk accesses depending on cache contents and the location
|
||||
of the file's name in the directory blockB-Tree.That's quite a contrast to
|
||||
the FAT file system, where in the worst case more than 4000 sectors would
|
||||
have to be read to establish that a filewas or was not present in a directory
|
||||
containing the same number of files. The B-Tree directory structure has
|
||||
interesting implications beyond its effect on open and find operations.
|
||||
A file creation, renaming, or deletion may result in a cascade of complex
|
||||
operations, as directory blocks are added or freed or names are moved from
|
||||
one block to the other to keep the tree balanced. In fact, a rename
|
||||
operation could theoretically fail for lack of disk space even though the
|
||||
file itself is not growing. In order to avoid this sort of disaster, the
|
||||
HPFS maintains a small pool of free blocks that can be drawn from in a
|
||||
directory emergency; a pointer to this pool of free blocks is stored in the
|
||||
Spare Block.
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig5.gif" name="fig5">
|
||||
<img src="fig5.gif" alt="[Fig. 5]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 5</b>:
|
||||
Here directories are anchored on an Fnode and are built up from 2Kb directory
|
||||
blocks. The number of entries in a directory block varies because the length
|
||||
of the entries depends on the filename. When a directory requires more than
|
||||
one block the blocks are organized as a B-Tree. This allows a filename to be
|
||||
located very quickly with a small number of disk accesses even when the
|
||||
directory grows very large.
|
||||
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
< <a href="fnodes.html">[Files and Fnodes]</a> |
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="ea.html">[Extended Attributes]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
65
study/sabre/os/files/FileSystems/DesignGoalsHPFS/ea.html
Normal file
@@ -0,0 +1,65 @@
|
||||
<html><head>
|
||||
<title>HPFS: Extended Attributes</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>Extended Attributes</h1>
|
||||
</center>
|
||||
|
||||
File attributes are information about a file that is maintained by the
|
||||
operating system outside the file's overt storage area. The FAT file
|
||||
system supports only a few simple attributes (read only, system, hidden,
|
||||
and archive) that are actually stored as bit flags in the file's directory
|
||||
entry these attributes are inspected or modified by special function calls
|
||||
and are not accessible through the normal file open, read, and write calls.
|
||||
The HPF'S supports the same attributes as the FAT file system for historical
|
||||
reasons, but it also supports a new form of file- associated, highly
|
||||
generalized information called Extended Attributes (EAs). Each EA is
|
||||
conceptually similar to an environment variable, taking the form
|
||||
(name=value) except that the value portion can be either a null- tenninated
|
||||
(ASCIIZ) string or binary data. In OS/2 1.2, each file or direc-tory can
|
||||
have a maximum of 64Kb of EAs attached to it. This limit may be lifted in
|
||||
a later release of OS/2. The storage method for EAs can vary. If the EAs
|
||||
associated with a given file or directory are small enough, they will be
|
||||
stored right in the Fnode. If the total size of the EAs is too large, they
|
||||
are stored outside the Fnode in sector runs, and a B+ Tree of allocation
|
||||
sectors can be created to describe the runs. If a single EA gets too large,
|
||||
it can be pushed outside the Fnode into a B+ Tree of its own.
|
||||
<p>
|
||||
The kernel API functions DosQFileInfo and DosSetFileInfo have been expanded
|
||||
with new information levels that allow application programs to manipulate
|
||||
extended attributes for files. The new functions DosQPathInfo and
|
||||
DosSetPathInfo are used to read or write the EAs associated with arbitrary
|
||||
path names. An application program can either ask for the value of a
|
||||
specific EA (supplying a name to be matched) or can obtain all of the EAs
|
||||
for the file or directory at once. Although application programs can begin
|
||||
to take advantage of EAs as soon as the HPFS is released, support for EAs
|
||||
is an essential component in Microsoft's long-range plans for object-oriented
|
||||
file systems. Information of almost any type can be stored in EAs, ranging
|
||||
from the name of the application that owns the file to names of dependent
|
||||
files to icons to executable code. As the HPFS evolves, its facilities for
|
||||
manipulating EAs are likely to become much more sophisticated. It's easy to
|
||||
imagine, for example, that in future versions the API might be extended with
|
||||
EA functions that are analogous to DosFindFirst and DosFindNext and EA data
|
||||
might get organized into B-Trees. I should note here that in addition to EAs,
|
||||
the LAN Manager version of HPFS will support another class of fil-associated
|
||||
information called Access Control Lists (ACLs). ACLs have the same general
|
||||
appearance as EAs and are manipulated in a similar manner, but they are used
|
||||
to store access rights, passwords, and other information of interest in a
|
||||
networking multi user environment.
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
< <a href="dirs.html">[Directories]</a> |
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="ifs.html">[Installable File Systems]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
94
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fat.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<html><head>
|
||||
<title>HPFS: FAT File System</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>FAT File System</h1>
|
||||
</center>
|
||||
|
||||
The so-called FAT file system ,which is the file system used in all versions of the
|
||||
MS-DOS operating system to date and in the first two releases of OS/2' (Versions 1.0
|
||||
and 1.1), has a dual heritage in Microsoft's earliest programming language products
|
||||
and the Digital Research CP/M operating system--software originally written for
|
||||
8080-based and Z-80-based microcomputers. It inherited characteristics from both
|
||||
ancestors that have progressively turned into handicaps in this new era of
|
||||
multitasking, protected mode, virtual memory, and huge fixed disks.
|
||||
<p>
|
||||
|
||||
The FAT file system revolves around the File Allocation Table for which it is
|
||||
named. Each logical volume has its own FAT, which serves two important functions:
|
||||
it contains the allocation information for each file on the volume in the fonn
|
||||
of linked lists of allocation units (clusters, which are power-of-2 multiples
|
||||
of sectors) and it indicates which allocation units are free for assignment to
|
||||
a file that is being created or extended.
|
||||
<p>
|
||||
|
||||
The FAT was invented by Bill Gates and Marc McDonald in 1977 as
|
||||
a method of managing disk space in the NCR version of standalone Microsoft's Disk
|
||||
BASIC. Tim Paterson, at that time an employee of Seattle Computer Products (SCP), was
|
||||
introduced to the FAT concept when his company shared a booth with Microsoft at the
|
||||
National Computer Conference in 1979. Paterson subsequently incorporated FATs into
|
||||
the file system of 86-DOS, an operating system for SCP s S-100 bus 8086 CPU boards.
|
||||
86-DOS was eventually purchased by Micro-soft and became the starting point for
|
||||
MS-DOS Version 1.0, which was released for the original lBM PC in August 1981.
|
||||
<p>
|
||||
When the FAT was conceived, it was an excellent solution to disk management,
|
||||
mainly because the floppy disks on which it was used were rarely larger than
|
||||
1 Mb.
|
||||
On such disks, the FAT was small enough to be held in memory at all times,
|
||||
allowing very fast random access to any part of any file. This proved far
|
||||
superior to the CP/M method of tracking disk space, in which the information
|
||||
about the sectors assigned to a file might be spread across many directory
|
||||
entries, which were in turn scattered randomly throughout the disk directory.
|
||||
When applied to fixed disks, however, the FAT began to look more like a bug
|
||||
than a feature. it became too large to be held entirely resident and had to
|
||||
be paged into memory in pieces: this paging resulted in many superfluous disk
|
||||
head movements as a program was reading through a file and degraded system
|
||||
throughput. in addition, because the information about free disk space was
|
||||
dispersed across many sectors of FAT, it was impractical to allocate file
|
||||
space contiguously, and file fragmentation became another obstacle to good
|
||||
performance. Moreover, the use of relatively large clusters on fixed disks
|
||||
resulted in a lot of dead space, since an average of one- half cluster was
|
||||
wasted for each file. (Some network servers use clusters as large as 64Kb.)
|
||||
<p>
|
||||
|
||||
The FAT file system 's restrictions on naming files and directories are
|
||||
inherited from CP/M. When Paterson was writing 86-DOS one of his primary
|
||||
objectives was to make programs easy to port from CP/M to his new operating
|
||||
system. He therefore adopted CP/M's limits on filenames and extensions so the
|
||||
critical fields of 86-DOS File Control Blocks (FCBs) would look almost exactly
|
||||
like those of CP/M. The sizes of the FCB filename and extension fields were
|
||||
also propagated into the structure of disk directory entries. In due time 86-DOS
|
||||
became MS- DOS and application programs for MS-DOS proliferated beyond anyone's
|
||||
wildest dreams. Since most of the early programs depended on the structure of
|
||||
FCBs the 8.3 format for filenames became irrevocably locked into the system.
|
||||
<p>
|
||||
|
||||
During the last couple of years Microsoft and IBM have made valiant attempts
|
||||
to prolong the useful life of the FAT file system by lifting the restrictions
|
||||
on volume sizes improving allocation strategies caching path names and moving
|
||||
tables and buffers into expanded memory. But these can only be regarded as
|
||||
temporizing measures because the fundamental data structures used by the FAT
|
||||
file system are simply not well suited to large random access devices.
|
||||
The HPFS solves the FAT file system problems mentioned here and many others
|
||||
but it is not derived in any way from the FAT file system. The architect of
|
||||
the HPFS started with a clean sheet of paper and designed a file system that
|
||||
can take full advantage of a multitasking environment and that will be able to
|
||||
cope with any sort of disk device likely to arrive on microcomputers during
|
||||
the next decade.
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
< <a href="design.html">[HPFS Design]</a> |
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="hpfs_vol.html">[HPFS Volumes]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
@@ -0,0 +1,84 @@
|
||||
<html><head>
|
||||
<title>HPFS: Fault Tolerance</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>Fault Tolerance</h1>
|
||||
</center>
|
||||
|
||||
The HPFS's extensive use of lazy writes makes it imperative for the HPFS to
|
||||
be able to recover gracefully from write errors under any but the most dire
|
||||
circumstances. After all, by the time a write is known to have failed, the
|
||||
application has long since gone on its way under the illusion that it has
|
||||
safely shipped the data into disk storage. The errors may be detected by the
|
||||
hardware (such as a "sector not found" error returned by the disk adapter),
|
||||
or they may be detected by the disk driver in spite of the hardware during a
|
||||
read-after-write verification of the data. The primary mechanism for handling
|
||||
write errors is called a hot fix. When an error is detected, the file system
|
||||
takes a free block out of a reserved hot fix pool, writes the data to that
|
||||
block, and updates the hot fix map. (The hot fix map is simply a series of
|
||||
pairs of double words, with each pair containing the number of a bad sector
|
||||
associated with the number of its hot fix replacement. A pointer to the hot
|
||||
fix map is maintained in the Spare Block.) A copy of the hot fix map is then
|
||||
written to disk, and a warning message is displayed to let the user know that
|
||||
all is not well with the disk device.
|
||||
<p>
|
||||
|
||||
Each time the file system requests a sector read or write from the disk
|
||||
driver, it scans the hot fix map and replaces any bad sector members with the
|
||||
corresponding good sector holding the actual data. This look aside translation
|
||||
of sector numbers is not as expensive as it sounds, since the hot fix list
|
||||
need only be scanned when a sector is physically read or written, not each
|
||||
time it is accessed in the cache. One of CHKDSK's duties is to empty the hot
|
||||
fix map. For each replacement block on the hot fix map, it allocates a new
|
||||
sector that is in a favorable location for the file that owns the data, moves
|
||||
the data from the hot fix block to tile newly allocated sector, and updates
|
||||
the file's allocation information which may involve rebalancing allocation
|
||||
trees and other elaborate operations). It then adds the bad sector to the bad
|
||||
block list, releases the replacement sector back to the hot fix pool, deletes
|
||||
the hot fix entry from the hot fix map, and writes the updated hot fix map to
|
||||
disk. of course, write errors that can be detected and fixed on the fly are
|
||||
not the only calamity that can befall a file system. The HPFS designers also
|
||||
had to consider the inevitable damage to be wreaked by power failures, program
|
||||
crashes, malicious viruses and Trojan horses, and those users who turn off
|
||||
the machine without selecting Shut-down in the Presentation Manager Shell.
|
||||
(Shutdown notifies the file system to flush the disk cache, update directories,
|
||||
and do whatever else is necessary to bring the disk to a consistent state.)
|
||||
<p>
|
||||
|
||||
The HPFS defends itself against the user who is too abrupt with the Big Red
|
||||
Switch by maintaining a Dirty FS flag in the Spare Block of each HPFS volume.
|
||||
The flag is only cleared when all files on the volume have been closed and
|
||||
all dirty buffers in the cache have been written out or, in the case of the
|
||||
boot volume since OS2.INI and the swap file are never closed), when Shutdown
|
||||
has been selected and has completed its work. During the OS/2 boot sequence,
|
||||
the file system inspects the Dirty FS flag on each HPFS volume and, if the
|
||||
flag is set, will not allow further access to that volume until CHKDSK has
|
||||
been run. If the Dirty FS flag is set on the boot volume, the system will
|
||||
refuse to boot the user must boot OS/2 in maintenance mode from a diskette
|
||||
and run CHKDSK to check and possibly repair the boot volume. In the event
|
||||
of a truly major catastrophe, such as loss of the Super Block or the root
|
||||
directory, the HPFS is designed to give data recovery the best possible
|
||||
chance of success. Every type of crucial file objects including Fnodes,
|
||||
allocation sectors, and directory blocks is doubly linked to both its parent
|
||||
and its children and contains a unique 32-bit signature. Fnodes also contain
|
||||
the initial pofiion of the name of their file or directory. Consequently,
|
||||
CHKDSK can rebuild an entire volume by methodically scanning the disk for
|
||||
Fnodes, allocation sectors, and directory blocks, using them to reconstruct
|
||||
the files and directories and finally regenerating the freespace bitmaps.
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
< <a href="perform.html">[Performance Issues]</a> |
|
||||
<a href="hpfs.html">[HPFS Home]</a> |
|
||||
<a href="app_hpfs.html">[Application Programs and the HPFS]</a> >
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig1.gif
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig2.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig3.gif
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig4.gif
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig5.gif
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/fig6.gif
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/figa.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/figb.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
study/sabre/os/files/FileSystems/DesignGoalsHPFS/figc.gif
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
156
study/sabre/os/files/FileSystems/DesignGoalsHPFS/figs.html
Normal file
@@ -0,0 +1,156 @@
|
||||
<html><head>
|
||||
<title>HPFS: Illustrations</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<h1>HPFS: Illustrations</h1>
|
||||
</center>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig1.gif" name="fig1">
|
||||
<img src="fig1.gif" alt="[Fig. 1]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 1</b>:
|
||||
This figure shows the overall structure of an HPFS volume. The most important
|
||||
fixed objects in such a volume are the Bootblock the Super Block, and the
|
||||
Spare Block. The remainder of the volume is divided into 8Mb bands. There is
|
||||
a freespace bitmap for each band and the bitmaps are located between alternate
|
||||
bands consequently, the maximum contiguous space which can be allocated to a
|
||||
file is 16Mb.
|
||||
<li><a href="hpfs_vol.html">HPFS Volume Structure</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig2.gif" name="fig2">
|
||||
<img src="fig2.gif" alt="[Fig. 2]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 2</b>:
|
||||
This figure shows the overall structure of an Fnode. The Fnode is the
|
||||
fundamental object in an HPFS volume and is the first sector allocated to a
|
||||
file or directory. it contains control and access history information used
|
||||
by the file system, cached EAs and ACLs or pointers to same, a truncated
|
||||
copy of the file or directory name (to aid disk repair programs, and an
|
||||
allocation structure which defines the size and location of the file's storage.
|
||||
<li><a href="fnodes.html">Files and FNodes</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig3.gif" name="fig3">
|
||||
<img src="fig3.gif" alt="[Fig. 3]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 3</b>:
|
||||
The simplest form of tracking for the sectors owned by a file is shown. The
|
||||
Fnode s allocation structure points directly to as many as eight sector runs.
|
||||
Each run pointer consists of a pair of 32-bit doublewords: a starting sector
|
||||
number and a length !n sectors.
|
||||
<li><a href="fnodes.html">Files and FNodes</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig4.gif" name="fig4">
|
||||
<img src="fig4.gif" alt="[Fig. 4]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 4</b>:
|
||||
This figure demonstrates the technique used to track the sectors owned by a
|
||||
file with 9-480 sector runs. The allocation structure in the Fnode holds the
|
||||
roots for a B+ Tree of allocation sectors. Each allocation sector can describe
|
||||
as many as 40 sector runs. lf the file requires more than 480 sector runs,
|
||||
additional intermediate levels are added to the B+ Tree, which increases the
|
||||
number of possible sector runs by a factor of sixty for each new !evel.
|
||||
<li><a href="fnodes.html">Files and FNodes</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig5.gif" name="fig5">
|
||||
<img src="fig5.gif" alt="[Fig. 5]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 5</b>:
|
||||
Here directories are anchored on an Fnode and are built up from 2Kb directory
|
||||
blocks. The number of entries in a directory block varies because the length
|
||||
of the entries depends on the filename. When a directory requires more than
|
||||
one block the blocks are organized as a B-Tree. This allows a filename to be
|
||||
located very quickly with a small number of disk accesses even when the
|
||||
directory grows very large.
|
||||
<li><a href="dirs.html">Directories</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="fig6.gif" name="fig6">
|
||||
<img src="fig6.gif" alt="[Fig. 6]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE 6</b>:
|
||||
A simplified sketch of the relationship between an application program, the
|
||||
OS/2 kernel, an installable file system, a disk drlver, and the physical disk
|
||||
device. The applicatIon issues logical file requests to the OS/2 kernel by
|
||||
calling the entry points for DosOpen, DosRead, DosWrlte, DosChgFilePtr, and
|
||||
so on. The kernel passes these requests to the appropriate installable file
|
||||
system for the volume holding the file. The installable file system translates
|
||||
the logical file requests into requests for reads or writes of logical sectors
|
||||
and calls a kernel File System Helper (FsHlp) to pass these requests to the
|
||||
appropriate disk drlver. The disk driver transforms the logical sector
|
||||
requests into requests for specific physical units, cylinders heads, and
|
||||
sectors, and issues commands to the disk adapter to transfer data between the
|
||||
disk and memory.
|
||||
<li><a href="ifs.html">Installable File Systems</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="figa.gif" name="figa">
|
||||
<img src="figa.gif" alt="[Fig. A]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE A</b>:
|
||||
To find a piece of data, the binary tree is traversed from the root until
|
||||
the data is found or an empty subtree is encountered.
|
||||
<li><a href="sum.html">Summary</a>
|
||||
<p>
|
||||
|
||||
|
||||
<center>
|
||||
<a href="figb.gif" name="figb">
|
||||
<img src="figb.gif" alt="[Fig. B]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE B</b>:
|
||||
In a balanced B-Tree, data is stored in nodes, more than one data item can
|
||||
be stored in a node, and all branches of the tree are the same length.
|
||||
<li><a href="sum.html">Summary</a>
|
||||
<p>
|
||||
|
||||
<center>
|
||||
<a href="figc.gif" name="figc">
|
||||
<img src="figc.gif" alt="[Fig. C]" border=0></a>
|
||||
</center>
|
||||
<p>
|
||||
<b>FIGURE C</b>:
|
||||
A B+ Tree has internal nodes that point to other nodes and external nodes
|
||||
that contain actual data.
|
||||
<li><a href="sum.html">Summary</a>
|
||||
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
|
||||
<a href="hpfs.html">[HPFS Home]</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=-1>
|
||||
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
|
||||
</font>
|
||||
|
||||
</body></html>
|
||||