add directory study

This commit is contained in:
gohigh
2024-02-19 00:25:23 -05:00
parent b1306b38b1
commit f3774e2f8c
4001 changed files with 2285787 additions and 0 deletions

Binary file not shown.

View 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

View 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 &copy; 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>

Binary file not shown.

View 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.

View 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 &lt;linux/config.h&gt;
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 &gt;= 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 &lt;- 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 &copy; 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>

View 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 &copy; 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>

View 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>

Binary file not shown.

Binary file not shown.

View 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

View 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

View 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>

View 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 //
//===============//=======================//

View 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.

View 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.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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>

View 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

File diff suppressed because it is too large Load Diff

View 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.

File diff suppressed because it is too large Load Diff

View 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
--

Binary file not shown.

View 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

View 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

View 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

View 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.
========================================================================

View 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.
========================================================================

View 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')

File diff suppressed because it is too large Load Diff

View 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.
; ========================================================================== ;

Binary file not shown.

File diff suppressed because it is too large Load Diff

View 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">&copy; 1999 Microsoft Corporation. All rights reserved. Terms of Use.</A></q><BR></FONT>
<!--COPYRIGHT STATEMENT END--></TD></TR></table>
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View 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).
;

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View 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>

Binary file not shown.

View 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)

View 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

Binary file not shown.

Binary file not shown.

View 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.

View 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

View 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".

View 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

View 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");
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View 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

Binary file not shown.

View 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

File diff suppressed because it is too large Load Diff

Binary file not shown.

View 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>

View 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.


File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View 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>
&lt; <a href="faultol.html">[Fault Tolerance]</a> |
<a href="hpfs.html">[HPFS Home]</a> |
<a href="sum.html">[Summary]</a> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

View 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> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

View 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>
&lt; <a href="fnodes.html">[Files and Fnodes]</a> |
<a href="hpfs.html">[HPFS Home]</a> |
<a href="ea.html">[Extended Attributes]</a> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

View 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>
&lt; <a href="dirs.html">[Directories]</a> |
<a href="hpfs.html">[HPFS Home]</a> |
<a href="ifs.html">[Installable File Systems]</a> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

View 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>
&lt; <a href="design.html">[HPFS Design]</a> |
<a href="hpfs.html">[HPFS Home]</a> |
<a href="hpfs_vol.html">[HPFS Volumes]</a> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

View File

@@ -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>
&lt; <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> &gt;
<hr>
<font size=-1>
Html'ed by <a href="http://www.seds.org/~spider/">Hartmut Frommert</a>
</font>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View 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>

Some files were not shown because too many files have changed in this diff Show More