add directory study
This commit is contained in:
BIN
study/sabre/os/files/Booting/BIOSBootSpecsV1.01.pdf
Normal file
BIN
study/sabre/os/files/Booting/BIOSBootSpecsV1.01.pdf
Normal file
Binary file not shown.
486
study/sabre/os/files/Booting/BIOS_SEG.txt
Normal file
486
study/sabre/os/files/Booting/BIOS_SEG.txt
Normal file
@@ -0,0 +1,486 @@
|
||||
Format of BIOS Data Segment at segment 40h:
|
||||
{items in curly braces not documented by IBM}
|
||||
Offset Size Description
|
||||
00h WORD Base I/O address of 1st serial I/O port, zero if none
|
||||
02h WORD Base I/O address of 2nd serial I/O port, zero if none
|
||||
04h WORD Base I/O address of 3rd serial I/O port, zero if none
|
||||
06h WORD Base I/O address of 4th serial I/O port, zero if none
|
||||
Note: Above fields filled in turn by POST as it finds serial
|
||||
ports. POST never leaves gaps. DOS and BIOS serial device
|
||||
numbers may be redefined by re-assigning these fields.
|
||||
08h WORD Base I/O address of 1st parallel I/O port, zero if none
|
||||
0Ah WORD Base I/O address of 2nd parallel I/O port, zero if none
|
||||
0Ch WORD Base I/O address of 3rd parallel I/O port, zero if none
|
||||
0Eh WORD [non-PS] Base I/O address of 4th parallel I/O port, zero if none
|
||||
[PS] Segment of Extended BIOS Data Segment
|
||||
Note: Above fields filled in turn by POST as it finds
|
||||
parallel ports. POST never leaves gaps. DOS and BIOS
|
||||
parallel device numbers may de redefined by re-assigning
|
||||
these fields.
|
||||
10h WORD Installed hardware:
|
||||
bits 15-14: number of parallel devices
|
||||
bit 13: [Conv] Internal modem
|
||||
bit 12: reserved
|
||||
bits 11- 9: number of serial devices
|
||||
bit 8: reserved
|
||||
bits 7- 6: number of diskette drives minus one
|
||||
bits 5- 4: Initial video mode:
|
||||
00b = EGA,VGA,PGA
|
||||
01b = 40 x 25 color
|
||||
10b = 80 x 25 color
|
||||
11b = 80 x 25 mono
|
||||
bit 3: reserved
|
||||
bit 2: [PS] =1 if pointing device
|
||||
[non-PS] reserved
|
||||
bit 1: =1 if math co-processor
|
||||
bit 0: =1 if diskette available for boot
|
||||
12h BYTE [Conv] POST status
|
||||
[AT] {Manufacturing test initialisation flags}
|
||||
13h WORD Base memory size in kbytes (0-640)
|
||||
15h BYTE [AT] {Manufacturing test scratch pad}
|
||||
16h BYTE [AT] {Manufacturing test scratch pad}
|
||||
[PS/2 Mod 30] BIOS control flags
|
||||
17h BYTE Keyboard status flags 1:
|
||||
bit 7 =1 INSert active
|
||||
bit 6 =1 Caps Lock active
|
||||
bit 5 =1 Num Lock active
|
||||
bit 4 =1 Scroll Lock active
|
||||
bit 3 =1 either Alt pressed
|
||||
bit 2 =1 either Ctrl pressed
|
||||
bit 1 =1 Left Shift pressed
|
||||
bit 0 =1 Right Shift pressed
|
||||
18h BYTE Keyboard status flags 2:
|
||||
bit 7 =1 INSert pressed
|
||||
bit 6 =1 Caps Lock pressed
|
||||
bit 5 =1 Num Lock pressed
|
||||
bit 4 =1 Scroll Lock pressed
|
||||
bit 3 =1 Pause state active
|
||||
bit 2 =1 Sys Req pressed
|
||||
bit 1 =1 Left Alt pressed
|
||||
bit 0 =1 Left Ctrl pressed
|
||||
19h BYTE Keyboard: Alt-nnn keypad workspace
|
||||
1Ah WORD Keyboard: ptr to next character in keyboard buffer
|
||||
1Ch WORD Keyboard: ptr to first free slot in keyboard buffer
|
||||
1Eh 16 WORDs Keyboard circular buffer (but see 80h, 82h for override)
|
||||
3Eh BYTE Diskette recalibrate status:
|
||||
bit 7 =1 Diskette hardware interrupt occurred
|
||||
bits 6-4 reserved
|
||||
bit 3 =1 Recalibrate diskette 3
|
||||
bit 2 =1 Recalibrate diskette 2
|
||||
bit 1 =1 Recalibrate diskette 1
|
||||
bit 0 =1 Recalibrate diskette 0
|
||||
3Fh BYTE Diskette motor status:
|
||||
bit 7 =1 current operation is write or format
|
||||
=0 current operation is read or verify
|
||||
bit 6 reserved
|
||||
bits 5-4 diskette drive number selected (0-3)
|
||||
bit 3 =1 diskette 3 motor on
|
||||
bit 2 =1 diskette 2 motor on
|
||||
bit 1 =1 diskette 1 motor on
|
||||
bit 0 =1 diskette 0 motor on
|
||||
40h BYTE Diskette motor turn-off time-out count
|
||||
41h BYTE Diskette last operation status (0 = OK)
|
||||
bit 7 =1 drive not ready
|
||||
bit 6 =1 seek error
|
||||
bit 5 =1 general controller failure
|
||||
bits 4-0:
|
||||
00h no error
|
||||
01h invalid request
|
||||
02h address mark not found
|
||||
03h write-protect error
|
||||
04h sector not found
|
||||
06h diskette change line active
|
||||
08h DMA overrun
|
||||
09h DMA across 64k boundary
|
||||
0Ch media type unknown
|
||||
10h CRC error on read
|
||||
42h 7 BYTEs Diskette/Fixed disk status/command bytes
|
||||
49h BYTE Video current mode
|
||||
4Ah WORD Video columns on screen
|
||||
4Ch WORD Video page (regen buffer) size in bytes
|
||||
4Eh WORD Video current page start address in regen buffer
|
||||
50h 16 BYTEs Video cursor position (col, row) for eight pages, 0 based
|
||||
60h WORD Video cursor type, 6845 compatible, hi=startline, lo=endline
|
||||
62h BYTE Video current page number
|
||||
63h WORD Video CRT controller base address: color=03D4h, mono=03B4h
|
||||
65h BYTE Video current setting of mode select register 03D8h/03B8h
|
||||
66h BYTE Video current setting of CGA palette register 03D9h
|
||||
67h DWORD POST real mode re-entry point after certain resets
|
||||
6Bh BYTE POST last unexpected interrupt
|
||||
6Ch DWORD Timer ticks since midnight
|
||||
70h BYTE Timer overflow, non-zero if has counted past midnight
|
||||
71h BYTE Ctrl-Break flag: bit 7=1
|
||||
72h WORD POST reset flag:
|
||||
= 1234h if to bypass memory test (warm boot)
|
||||
= 4321h [PS/2 MCA only] if to preserve memory
|
||||
= 5678h [Conv] system suspended
|
||||
= 9ABCh [Conv] manufacturing test mode
|
||||
= ABCDh [Conv] POST loop mode
|
||||
= 64h Burn-in mode
|
||||
74h BYTE Fixed disk last operation status: {except ESDI drives}
|
||||
00h no error
|
||||
01h invalid function request
|
||||
02h address mark not found
|
||||
03h write protect error
|
||||
04h sector not found
|
||||
05h reset failed
|
||||
07h drive parameter activity failed
|
||||
08h DMA overrun
|
||||
09h DMA data boundary error
|
||||
0Ah bad sector flag detected
|
||||
0Bh bad track detected
|
||||
0Dh invalid number of sectors for Format
|
||||
0Eh control data address mark detected
|
||||
0Fh DMA arbitration level out of range
|
||||
10h uncorrectable ECC or CRC error
|
||||
11h ECC corrected data error
|
||||
20h general controller failed
|
||||
40h seek failed
|
||||
80h time out
|
||||
AAh drive not ready
|
||||
BBh undefined error
|
||||
CCh write fault on selected drive
|
||||
E0h status error/error register is zero
|
||||
FFh sense failed
|
||||
75h BYTE Fixed disk: number of fixed disk drives
|
||||
76h BYTE Fixed disk: control byte {IBM document only for XT}
|
||||
77h BYTE Fixed disk: I/O port offset {IBM document only for XT}
|
||||
78h 3 BYTEs Parallel devices 1-3 time-out counters
|
||||
7Bh BYTE parallel device 4 time-out counter [non-PS]
|
||||
bit 5 set if Virtual DMA Spec supported [PS] (see INT 4B)
|
||||
7Ch 4 BYTEs Serial devices 1-4 time-out counters
|
||||
80h WORD Keyboard buffer start as offset from segment 40h (normally 1Eh)
|
||||
82h WORD Keyboard buffer end+1 as offset from segment 40h (normally 3Eh)
|
||||
[XT BIOS dated 11/08/82 ends here]
|
||||
84h BYTE Video EGA/MCGA/VGA rows on screen minus one
|
||||
85h WORD Video EGA/MCGA/VGA character height in scan-lines
|
||||
87h BYTE Video EGA/VGA control: [MCGA: =00h]
|
||||
bit 7: =1 if not to clear RAM (see INT 10h, AH=00h)
|
||||
bits 6-5: RAM on adapter = (this field + 1) * 64K
|
||||
bit 4: reserved
|
||||
bit 3: =0 if EGA/VGA video system active, =1 if inactive
|
||||
bit 2: =1 if to wait for display enable (what means this?)
|
||||
bit 1: =0 for color or ECD monitor, =1 for mono monitor
|
||||
bit 0: =0 alphanumeric cursor emulation enabled, =1 not.
|
||||
When enabled, text mode cursor size (INT 10,AH=01h)
|
||||
settings looking like CGA ones are translated to
|
||||
equivalent EGA/VGA ones.
|
||||
88h BYTE Video EGA/VGA switches: [MCGA: reserved]
|
||||
bits 7-4: power-on state of feature connector bits 3-0
|
||||
bits 3-0: configuration switches 4-1 (=0 on, =1 off)
|
||||
Values as read:
|
||||
0h Pri MDA, Sec EGA+old color display 40 x 25
|
||||
1h Pri MDA, Sec EGA+old color display 80 x 25
|
||||
2h Pri MDA, Sec EGA+ECD normal mode (CGA emul)
|
||||
3h Pri MDA, Sec EGA+ECD enhanced mode
|
||||
4h Pri CGA 40 x 25, Sec EGA mono display
|
||||
5h Pri CGA 80 x 25, Sec EGA mono display
|
||||
6h Pri EGA+old color display 40 x 25, Sec MDA
|
||||
7h Pri EGA+old color display 80 x 25, Sec MDA
|
||||
8h Pri EGA+ECD normal mode (CGA emul), Sec MDA
|
||||
9h Pri EGA+ECD enhanced mode, Sec MDA
|
||||
Ah Pri EGA mono display, Sec CGA 40 x 25
|
||||
Bh Pri EGA mono display, Sec CGA 80 x 25
|
||||
When bit4 of 40h:89h is 0, VGA emulates 350-line EGA if
|
||||
this byte is x3h or x9h, otherwise emulates 200-line CGA in
|
||||
400-line double scan. VGA resets this byte to x9h after the
|
||||
mode set.
|
||||
89h BYTE Video MCGA/VGA mode-set option control:
|
||||
bits 7 and 4:
|
||||
0 0 350-line mode requested
|
||||
0 1 400-line mode at next mode set
|
||||
1 0 200-line mode requested
|
||||
1 1 reserved
|
||||
Apparently VGA BIOS mode set disregards bit 7 and uses
|
||||
byte 40h:88h to determine 200/350 selection when bit 4
|
||||
is zero. Presumably bit 7 is a convenience for other
|
||||
purposes. Bit 7 is reset to zero after the mode set.
|
||||
bit 6: =1 if display switching enabled, =0 if disabled
|
||||
bit 5: reserved
|
||||
bit 4: [VGA] =1 if to use 400-line mode at next mode set
|
||||
=0 if to emulate EGA at next mode set
|
||||
This bit set to 1 after the mode set.
|
||||
[MCGA] =1 use 400-line mode at next mode set
|
||||
=0 emulate CGA, digital monitor, 200 lines,
|
||||
8 x 8 text font at next mode set
|
||||
Bit unchanged by mode set.
|
||||
bit 3: =0 if default palette loading enabled at mode set
|
||||
bit 2: =1 if mono display, =0 if color display
|
||||
bit 1: =1 if gray scale summing enabled, =0 if disabled
|
||||
bit 0: [VGA] =1 if VGA active, =0 if not
|
||||
[MCGA] reserved, zero
|
||||
8Ah BYTE Video [MCGA/VGA]: index into Display Combination Code table
|
||||
8Bh BYTE Diskette media control [not XT]:
|
||||
bits 7-6: Last data rate set by controller:
|
||||
00=500kbps, 01=300kbps, 10=250kbps, 11=reserved
|
||||
bits 5-4: Last diskette drive step rate selected
|
||||
bits 3-2: {Data rate at start of operation}
|
||||
bits 1-0: reserved
|
||||
8Ch BYTE Fixed disk controller status [not XT]
|
||||
8Dh BYTE Fixed disk controller Error Status [not XT]
|
||||
8Eh BYTE Fixed disk Interrupt Control [not XT]
|
||||
8Fh BYTE Diskette controller information [not XT]:
|
||||
bit 7: reserved
|
||||
bit 6: =1 drive 1 determined
|
||||
bit 5: =1 drive 1 is multi-rate, valid if drive determined
|
||||
bit 4: =1 drive 1 supports 80 tracks, always valid
|
||||
bit 3: reserved
|
||||
bit 2: =1 drive 0 determined
|
||||
bit 1: =1 drive 0 is multi-rate, valid if drive determined
|
||||
bit 0: =1 drive 0 supports 80 tracks, always valid
|
||||
90h BYTE Diskette drive 0 media state
|
||||
91h BYTE Diskette drive 1 media state
|
||||
bits 7-6: Data rate: 00=500kbps, 01=300kbps, 10=250kbps
|
||||
bit 5: =1 if double stepping reqd (e.g. 360kB in 1.2MB)
|
||||
bit 4: =1 if media established
|
||||
bit 3: reserved
|
||||
bits 2-0: on exit from BIOS, contain:
|
||||
000 trying 360kB in 360kB
|
||||
001 trying 360kB in 1.2MB
|
||||
010 trying 1.2MB in 1.2MB
|
||||
011 360kB in 360kB established
|
||||
100 360kB in 1.2MB established
|
||||
101 1.2MB in 1.2MB established
|
||||
110 reserved
|
||||
111 all other formats/drives
|
||||
92h BYTE Diskette drive 0 media state at start of operation
|
||||
93h BYTE Diskette drive 1 media state at start of operation
|
||||
94h BYTE Diskette drive 0 current track number
|
||||
95h BYTE Diskette drive 1 current track number
|
||||
96h BYTE Keyboard status byte 3
|
||||
bit 7 =1 read-ID in progress
|
||||
bit 6 =1 last code read was first of two ID codes
|
||||
bit 5 =1 force Num Lock if read-ID and enhanced keyboard
|
||||
bit 4 =1 enhanced keyboard installed
|
||||
bit 3 =1 Right Alt pressed
|
||||
bit 2 =1 Right Ctrl pressed
|
||||
bit 1 =1 last code read was E0h
|
||||
bit 1 =1 last code read was E1h
|
||||
97h BYTE Keyboard status byte 2
|
||||
bit 7 =1 keyboard transmit error flag
|
||||
bit 6 =1 LED update in progress
|
||||
bit 5 =1 RESEND received from keyboard
|
||||
bit 4 =1 ACK received from keyboard
|
||||
bit 3 reserved, must be zero
|
||||
bit 2 Caps Lock LED
|
||||
bit 1 Num Lock LED
|
||||
bit 0 Scroll Lock LED
|
||||
98h DWORD Timer2: [AT, PS exc Mod 30] ptr to user wait-complete flag
|
||||
(see INT 15, AX=8300h)
|
||||
9Ch DWORD Timer2: [AT, PS exc Mod 30] user wait count in microseconds
|
||||
A0h BYTE Timer2: [AT, PS exc Mod 30] Wait active flag:
|
||||
bit 7 =1 wait time elapsed
|
||||
bits 6-1 reserved
|
||||
bit 0 =1 INT 15h, AH=86h has occurred
|
||||
A1h 7 BYTEs reserved for network adapters (oh really?)
|
||||
A4h DWORD [PS/2 Mod 30] Saved Fixed Disk Interrupt Vector
|
||||
A8h DWORD Video: EGA/MCGA/VGA ptr to Video Save Pointer Table (see below)
|
||||
ACh-AFh reserved
|
||||
B0h DWORD ptr to 3363 Optical disk driver or BIOS entry point.
|
||||
When 3363 BIOS present, the signature "OPTIC ",00h occurs 3
|
||||
bytes beyond this entry point.
|
||||
When 3363 BIOS and 3363 File System Driver present, the
|
||||
signature "FILE SYSTEM DRIVER",00h occurs 3 bytes beyond
|
||||
this entry point.
|
||||
B4h WORD reserved
|
||||
B6h 3 BYTEs reserved for POST?
|
||||
B9h 7 BYTEs ???
|
||||
C0h 14 BYTEs reserved
|
||||
CEh WORD count of days since last boot?
|
||||
D0h-EFh reserved
|
||||
F0h-FFh reserved for user
|
||||
100h BYTE Print Screen Status byte
|
||||
|
||||
Format of Extended BIOS Data Area (see 40:0Eh for ptr) [PS only]
|
||||
Offset Size Description
|
||||
00h BYTE Length of EBDA in kilobytes
|
||||
01h 15 BYTEs reserved
|
||||
17h BYTE Number of entries in POST error log (0-5)
|
||||
18h 5 WORDs POST error log (each word is a POST error number)
|
||||
19h-21h reserved
|
||||
22h DWORD Pointing Device Driver entry point
|
||||
26h BYTE Pointing Device Flags 1
|
||||
bit 7: =1 command in progress
|
||||
bit 6: =1 resend
|
||||
bit 5: =1 acknowledge
|
||||
bit 4: =1 error
|
||||
bit 3: =0 reserved
|
||||
bits 2-0: index count
|
||||
27h BYTE Pointing Device Flags 2
|
||||
bit 7: =1 device driver far call flag
|
||||
bits 6-3: reserved
|
||||
bits 2-0: package size
|
||||
28h 7 BYTEs Pointing Device Auxiliary Device Data
|
||||
2Fh BYTE reserved
|
||||
30h DWORD Vector for INT 07h stored here during 80387 interrupt
|
||||
34h DWORD Vector for INT 01h stored here during INT 07h emulation
|
||||
38h BYTE Scratchpad for 80287/80387 interrupt code
|
||||
39h WORD Timer3: Watchdog timer initial count
|
||||
3Bh BYTE ??? seen non-zero on Model 30
|
||||
3Ch BYTE ???
|
||||
3Dh 16 BYTEs Fixed Disk parameter table for drive 0 (oh really?)
|
||||
4Dh 16 BYTEs Fixed Disk parameter table for drive 1 (oh really?)
|
||||
Neither of above seen on any Model 30, 50, 60 yet.
|
||||
5Dh-6Bh ???
|
||||
6Ch BYTE Fixed disk: (=FFh on ESDI systems)
|
||||
bits 7-4: Channel number 00-0Fh
|
||||
bits 3-0: DMA arbitration level 00-0Eh
|
||||
6Dh and up: ??? seen non-zero on Model 60
|
||||
3F0h BYTE Fixed disk buffer (???!!!)
|
||||
|
||||
Format of Video Save Pointer Table [EGA/VGA/MCGA only]:
|
||||
Offset Size Description
|
||||
00h DWORD ptr to Video Parameter Table
|
||||
04h DWORD ptr to Parameter Dynamic Save Area, else 0 [EGA/VGA only]
|
||||
08h DWORD ptr to Alphanumeric Character Set Override, else 0
|
||||
0Ch DWORD ptr to Graphics Character Set Override, else 0
|
||||
10h DWORD [VGA only] ptr to Secondary Save Pointer Table, must be valid
|
||||
14h DWORD reserved, zero
|
||||
18h DWORD reserved, zero
|
||||
Note: table initially in ROM, copy to RAM to alter, then update 40h:A8h.
|
||||
|
||||
Format of Secondary Video Save Pointer Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h WORD Length of this table in bytes, including this word (1Ah)
|
||||
02h DWORD ptr to Display Combination Code Table, must be valid
|
||||
06h DWORD ptr to second Alphanumeric Character Set Override, else 0
|
||||
0Ah DWORD ptr to User Palette Profile Table, else 0
|
||||
0Eh DWORD reserved, zero
|
||||
12h DWORD reserved, zero
|
||||
16h DWORD reserved, zero
|
||||
Note: table initially in ROM, copy to RAM to alter, then alter Save Ptr Table.
|
||||
|
||||
Format of Video Parameter Table [EGA, VGA only]:
|
||||
An array of 23 [EGA] or 29 [VGA] elements, each element being 64 bytes long.
|
||||
Elements appear in the order:
|
||||
00h-03h Modes 00h-03h in 200-line CGA emulation mode
|
||||
04h-0Eh Modes 04h-0Eh
|
||||
0Fh-10h Modes 0Fh-10h when only 64kB RAM on adapter
|
||||
11h-12h Modes 0Fh-10h when >64kB RAM on adapter
|
||||
13h-16h Modes 00h-03h in 350-line mode
|
||||
17h VGA Modes 00h or 01h in 400-line mode
|
||||
18h VGA Modes 02h or 03h in 400-line mode
|
||||
19h VGA Mode 07h in 400-line mode
|
||||
1Ah-1Ch VGA Modes 11h-13h
|
||||
|
||||
Format of Video Parameter Table element [EGA, VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Columns on screen (see 40h:4Ah)
|
||||
01h BYTE Rows on screen minus one (see 40h:84h)
|
||||
02h BYTE Height of character in scan lines (see 40h:85h)
|
||||
03h WORD Size of video buffer (see 40h:4Ch)
|
||||
05h 4 BYTEs Values for Sequencer Registers 1-4
|
||||
09h BYTE Value for Miscellaneous Output Register
|
||||
0Ah 25 BYTEs Values for CRTC Registers 00h-18h
|
||||
23h 20 BYTEs Values for Attribute Controller Registers 00h-13h
|
||||
37h 9 BYTEs Values for Graphics Controller Registers 00h-08h
|
||||
|
||||
Format of Video Parameter Table [MCGA only] {guesswork from inspection}:
|
||||
- 16 triplet BYTEs of R,G,B DAC info for 16 colors;
|
||||
- An array of 11 elements, each element being 32 bytes long.
|
||||
Elements appear in the order:
|
||||
Modes 00h,01h in 200-line mode for digital displays
|
||||
Modes 00h,01h in 400-line mode for analog displays
|
||||
Modes 02h,03h in 200-line mode for digital displays
|
||||
Modes 02h,03h in 400-line mode for analog displays
|
||||
Modes 04h,05h in 200-line mode for digital displays
|
||||
Modes 04h,05h in 400-line mode for analog displays
|
||||
Mode 06h in 200-line mode for digital displays
|
||||
Mode 06h in 400-line mode for analog displays
|
||||
Mode 11h
|
||||
Mode 13h in 200-line mode for digital displays
|
||||
Mode 13h in 400-line mode for analog displays
|
||||
|
||||
Format of Video Parameter Table element [MCGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Columns on screen (see 40h:4Ah)
|
||||
01h BYTE Rows on screen minus one (see 40h:84h)
|
||||
02h BYTE Height of character in scan lines (see 40h:85h)
|
||||
03h WORD Size of video buffer (see 40h:4Ch)
|
||||
05h WORD ??? always zero
|
||||
07h 21 BYTEs Video data registers 00h-14h to port 3D5h indexed by 3D4h
|
||||
1Ch BYTE PEL Mask to port 3C6h
|
||||
1Dh BYTE CGA Mode Control to port 3D8h
|
||||
1Eh BYTE CGA Border Control to port 3D9h
|
||||
1Fh BYTE Extended Mode Control to port 3DDh
|
||||
|
||||
Format of Video Parameter Dynamic Save Area [EGA, VGA only]:
|
||||
Offset Size Description
|
||||
00h 16 BYTEs Last data written to Attribute Controller Palette Registers 0-15
|
||||
10h BYTE Last data written to Attribute Controller Overscan Register
|
||||
11h-FFh Reserved
|
||||
Note: Need for table was that EGA registers were write-only.
|
||||
Note: If default values (from the Video Parameter Table) are
|
||||
over-ridden at a mode set by the VGA User Palette Profile
|
||||
Table, then the Dynamic Save Area is updated with the
|
||||
default values, not the User Profile ones.
|
||||
|
||||
Format of Alphanumeric Character Set Override:
|
||||
Offset Size Description
|
||||
00h BYTE Length in bytes of each character in font table
|
||||
01h BYTE Character generator RAM bank to load, 0=normal
|
||||
02h WORD Number of characters in font table, normally 256
|
||||
04h WORD Code of first character in font table, normally 0
|
||||
06h DWORD ptr to font table
|
||||
0Ah BYTE Displayable rows (FFh=use maximum calculated value)
|
||||
0Bh BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Second Alphanumeric Character Set Override:
|
||||
Authorities differ, some say same as first override above, but IBM say:
|
||||
Offset Size Description
|
||||
00h BYTE Length in bytes of each character in font table
|
||||
01h BYTE Character generator RAM bank to load, normally non-zero
|
||||
02h BYTE reserved
|
||||
03h DWORD ptr to font table
|
||||
07h BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Graphics Character Set Override:
|
||||
Offset Size Description
|
||||
00h BYTE Number of displayable character rows
|
||||
01h WORD Length in bytes of each character in font table
|
||||
03h DWORD ptr to font table
|
||||
07h BYTEs Array of mode values to which this font is to pertain
|
||||
BYTE FFh end of array
|
||||
|
||||
Format of Display Combination Code Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Number of entries in the DCC table at offset 04h
|
||||
01h BYTE Version number
|
||||
02h BYTE Maximum display type code that can appear in DCC table
|
||||
03h BYTE reserved
|
||||
04h ARRAY OF 2 BYTEs Each pair of bytes gives a valid display combination
|
||||
Meaning of each byte:
|
||||
00h no display
|
||||
01h MDA with mono display
|
||||
02h CGA with color display
|
||||
03h reserved
|
||||
04h EGA with color display
|
||||
05h EGA with mono display
|
||||
06h Professional Graphics Controller
|
||||
07h VGA with mono display
|
||||
08h VGA with color display
|
||||
09h reserved
|
||||
0Ah MCGA with digital color display
|
||||
0Bh MCGA with analog mono display
|
||||
0Ch MCGA with analog color display
|
||||
FFh unrecognised video system
|
||||
|
||||
Format of User Palette Profile Table [VGA only]:
|
||||
Offset Size Description
|
||||
00h BYTE Underlining: 01h=enable in all alphanumeric modes
|
||||
00h=enable in monochrome alphanumeric modes only
|
||||
FFh=disable in all alphanumeric modes
|
||||
01h BYTE reserved
|
||||
02h WORD reserved
|
||||
04h WORD Number (0-17) of Attribute Controller registers in table
|
||||
06h WORD Index (0-16) of first Attribute Controller register in table
|
||||
08h DWORD ptr to table of Attribute Controller registers to override
|
||||
Table is an array of BYTEs.
|
||||
0Ch WORD Number (0-256) of video DAC Color registers in table
|
||||
0Eh WORD Index (0-255) of first video DAC Color register in table
|
||||
10h DWORD ptr to table of video DAC Color registers to override
|
||||
Table is ??? triplets ??? of BYTEs???
|
||||
14h BYTEs array of mode values to which this profile is to pertain
|
||||
BYTE FFh end of array
|
||||
59
study/sabre/os/files/Booting/BootSector.html
Normal file
59
study/sabre/os/files/Booting/BootSector.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<title>Operating Systems: The Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=7><b>The Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
The boot sector on a disk is always the first sector on the first track on the first head.
|
||||
When the computer is powered on (or reset), the BIOS starts up and does the POST. It initializes
|
||||
all of it's data, then it looks for a valid boot sector. First it looks at the A: drive, then
|
||||
it looks to C:. If it doesn't find it then interrupt 18h is called, which, on original IBM PCs,
|
||||
started the ROM BASIC. A valid
|
||||
boot sector (to the BIOS) is one that has 0AA55h at offset 510 in the boot sector.<p>
|
||||
|
||||
When the BIOS finds the boot sector, it reads that sector (512 bytes) off of the disk and into
|
||||
memory at 0:7C00h. Then it jumps to 0:7C00h and the boot sector code gets control. At this
|
||||
point, all that has been initialized is the BIOS data area (40h:0) and the BIOS interrupts
|
||||
(10h - 1Ah). At this point, memory is mostly unused, but not neccesarily cleared to 0.<p>
|
||||
|
||||
Below is an example shell that I use when writing boot sector code:
|
||||
|
||||
<pre>
|
||||
;Generic boot sector shell. Written by Chris Lattner 1995
|
||||
;Code+Data MUST be less than 510 bytes long!
|
||||
|
||||
_Text SEGMENT PUBLIC USE16
|
||||
assume CS:_Text, DS:_Text
|
||||
org 0
|
||||
|
||||
EntryPoint:
|
||||
db 0EAh ;jmp far SEG:OFS ;Currently we are at 0:7C00
|
||||
dw OFFSET AfterData, 7C0h ;This makes us be at 7C0:0
|
||||
|
||||
;Put any data here!
|
||||
|
||||
|
||||
AfterData:
|
||||
push CS
|
||||
pop DS ; update DS to be 7C0 instead of 0
|
||||
|
||||
;Put code here!
|
||||
|
||||
|
||||
jmp $ ; Hang out...
|
||||
|
||||
org 510 ; Make the file 512 bytes long
|
||||
dw 0AA55h ; Add the boot signature
|
||||
_Text ENDS
|
||||
END
|
||||
</pre>
|
||||
|
||||
To use this code, you must compile it with either MASM or TASM. Link it together as a COM file
|
||||
if you can (Tasm v4 complains about illegal COM entry point). Then write the 512 byte file in
|
||||
sector 1 of a floppy (With some suitable disk tool) to test it out... If you can't compile it
|
||||
as a COM file, compile it as an EXE, but only write out the last 512 bytes of the file (eg. skip
|
||||
the EXE file header). Pop the disk in, reset you computer, and watch the magic!
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1994-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Corrections and suggestions by <a href="mailto:murf@perftech.com">John Murphy</a><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
BIN
study/sabre/os/files/Booting/BootableCDFormat.doc
Normal file
BIN
study/sabre/os/files/Booting/BootableCDFormat.doc
Normal file
Binary file not shown.
79
study/sabre/os/files/Booting/CMOS_SEG.txt
Normal file
79
study/sabre/os/files/Booting/CMOS_SEG.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
From: James Vahn
|
||||
Subj: Cmos
|
||||
____________________________________________________________________________
|
||||
|
||||
The standard AT CMOS addresses from 00h to 3Fh are easy,
|
||||
|
||||
; Read CMOS
|
||||
mov al,addr ; 'addr' ranges from 00h to 3Fh.
|
||||
out 70h,al ; wakes up the port.
|
||||
jmp $+2 ; a delay loop..
|
||||
in al,71h ; reads CMOS.
|
||||
|
||||
; Write CMOS
|
||||
mov al,addr ; 'addr' ranges from 00h to 3Fh.
|
||||
out 70h,al ; wakes up the port.
|
||||
jmp $+2 ; a delay loop..
|
||||
out 71h, value ; Writes 'value' from 00h to FFh.
|
||||
; note that 'addr' 10h to 20h are checksummed.
|
||||
|
||||
|
||||
Some CMOS info...
|
||||
|
||||
addr contents
|
||||
|
||||
00h Seconds
|
||||
01h Second Alarm
|
||||
02h Minutes
|
||||
03h Minute Alarm
|
||||
04h Hours
|
||||
05h Hour Alarm
|
||||
06h Day of the Week
|
||||
07h Day of the Month
|
||||
08h Month
|
||||
09h Year
|
||||
0Ah Status Register A
|
||||
0Bh Status Register B
|
||||
0Ch Status Register C
|
||||
0Dh Status Register D
|
||||
0Eh Diagnostic Status Byte
|
||||
0Fh Shutdown Status Byte
|
||||
10h Disk Drive Type for Drives A: and B:
|
||||
The drive-type bytes use bits 0:3 for the first
|
||||
drive and 4:7 for the other disk drive types.
|
||||
00h no drive present
|
||||
01h double sided 360k
|
||||
02h high capacity (1.2 meg)
|
||||
03h-0Fh reserved
|
||||
11h (AT):Reserved (PS/2):drive type for hard disk C:
|
||||
12h (PS/2):drive type for hard disk D:
|
||||
(AT, XT/286):hard disk type for drives C: and D:
|
||||
Format of drive-type entry for AT, XT/286:
|
||||
0 number of cyls in drive (0-1023 allowed)
|
||||
2 number of heads per drive (0-15 allowed)
|
||||
3 starting reduced write compensation (not used on AT)
|
||||
5 starting cylinder for write compensation
|
||||
7 max. ECC data burst length, XT only
|
||||
8 control byte
|
||||
Bit
|
||||
7 disable disk-access retries
|
||||
6 disable ECC retries
|
||||
5-4 reserved, set to zero
|
||||
3 more than 8 heads
|
||||
2-0 drive option on XT (not used by AT)
|
||||
9 timeout value for XT (not used by AT)
|
||||
12 landing zone cylinder number
|
||||
14 number of sectors per track (default 17, 0-17 allowed)
|
||||
13h Reserved
|
||||
14h Equipment Byte (corresponds to sw. 1 on PC and XT)
|
||||
15h-16h Base Memory Size (low,high)
|
||||
17h-18h Expansion Memory Size (low,high)
|
||||
19h-20h Reserved
|
||||
(PS/2) POS information Model 50 (60 and 80 use a 2k
|
||||
CMOS RAM that is not accessible through software)
|
||||
21h-2Dh Reserved (not checksumed)
|
||||
2Eh-2Fh Checksum of Bytes 10 Through 20 (low,high)
|
||||
30h-31h Exp. Memory Size as Det. by POST (low,high)
|
||||
32h Date Century Byte
|
||||
33h Information Flags (set during power-on)
|
||||
34h-3Fh Reserved - Put Your Name Here.
|
||||
Binary file not shown.
480
study/sabre/os/files/Booting/LinuxBootSector.html
Normal file
480
study/sabre/os/files/Booting/LinuxBootSector.html
Normal file
@@ -0,0 +1,480 @@
|
||||
<title>Operating Systems: The Linux 2.0 Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=7><b>Example Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
This is the assembly source for the boot sector used by the Linux free operating system. If it looks unfamiliar for intel assembly, that's because it gets run through the standard C preprocessor (CPP) and has comments starting with '!' stripped off... enjoy! :)<p>
|
||||
|
||||
<pre>
|
||||
!
|
||||
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
|
||||
! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
|
||||
! versions of linux which compress the kernel
|
||||
!
|
||||
#include <linux/config.h>
|
||||
SYSSIZE = DEF_SYSSIZE
|
||||
!
|
||||
! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
|
||||
! modified by Drew Eckhardt
|
||||
! modified by Bruce Evans (bde)
|
||||
!
|
||||
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
|
||||
! itself out of the way to address 0x90000, and jumps there.
|
||||
!
|
||||
! bde - should not jump blindly, there may be systems with only 512K low
|
||||
! memory. Use int 0x12 to get the top of memory, etc.
|
||||
!
|
||||
! It then loads 'setup' directly after itself (0x90200), and the system
|
||||
! at 0x10000, using BIOS interrupts.
|
||||
!
|
||||
! NOTE! currently system is at most (8*65536-4096) bytes long. This should
|
||||
! be no problem, even in the future. I want to keep it simple. This 508 kB
|
||||
! kernel size should be enough, especially as this doesn't contain the
|
||||
! buffer cache as in minix (and especially now that the kernel is
|
||||
! compressed :-)
|
||||
!
|
||||
! The loader has been made as simple as possible, and continuous
|
||||
! read errors will result in a unbreakable loop. Reboot by hand. It
|
||||
! loads pretty fast by getting whole tracks at a time whenever possible.
|
||||
|
||||
.text
|
||||
|
||||
SETUPSECS = 4 ! nr of setup-sectors
|
||||
BOOTSEG = 0x07C0 ! original address of boot-sector
|
||||
INITSEG = DEF_INITSEG ! we move boot here - out of the way
|
||||
SETUPSEG = DEF_SETUPSEG ! setup starts here
|
||||
SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
|
||||
|
||||
! ROOT_DEV & SWAP_DEV are now written by "build".
|
||||
ROOT_DEV = 0
|
||||
SWAP_DEV = 0
|
||||
#ifndef SVGA_MODE
|
||||
#define SVGA_MODE ASK_VGA
|
||||
#endif
|
||||
#ifndef RAMDISK
|
||||
#define RAMDISK 0
|
||||
#endif
|
||||
#ifndef CONFIG_ROOT_RDONLY
|
||||
#define CONFIG_ROOT_RDONLY 1
|
||||
#endif
|
||||
|
||||
! ld86 requires an entry symbol. This may as well be the usual one.
|
||||
.globl _main
|
||||
_main:
|
||||
#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
|
||||
int 3
|
||||
#endif
|
||||
mov ax,#BOOTSEG
|
||||
mov ds,ax
|
||||
mov ax,#INITSEG
|
||||
mov es,ax
|
||||
mov cx,#256
|
||||
sub si,si
|
||||
sub di,di
|
||||
cld
|
||||
rep
|
||||
movsw
|
||||
jmpi go,INITSEG
|
||||
|
||||
! ax and es already contain INITSEG
|
||||
|
||||
go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
|
||||
! bootsect + length of setup + room for stack
|
||||
! 12 is disk parm size
|
||||
|
||||
! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
|
||||
! wouldn't have to worry about this if we checked the top of memory. Also
|
||||
! my BIOS can be configured to put the wini drive tables in high memory
|
||||
! instead of in the vector table. The old stack might have clobbered the
|
||||
! drive table.
|
||||
|
||||
mov ds,ax
|
||||
mov ss,ax ! put stack at INITSEG:0x4000-12.
|
||||
mov sp,di
|
||||
/*
|
||||
* Many BIOS's default disk parameter tables will not
|
||||
* recognize multi-sector reads beyond the maximum sector number
|
||||
* specified in the default diskette parameter tables - this may
|
||||
* mean 7 sectors in some cases.
|
||||
*
|
||||
* Since single sector reads are slow and out of the question,
|
||||
* we must take care of this by creating new parameter tables
|
||||
* (for the first disk) in RAM. We will set the maximum sector
|
||||
* count to 36 - the most we will encounter on an ED 2.88.
|
||||
*
|
||||
* High doesn't hurt. Low does.
|
||||
*
|
||||
* Segments are as follows: ds=es=ss=cs - INITSEG,
|
||||
* fs = 0, gs is unused.
|
||||
*/
|
||||
|
||||
! cx contains 0 from rep movsw above
|
||||
|
||||
mov fs,cx
|
||||
mov bx,#0x78 ! fs:bx is parameter table address
|
||||
push ds
|
||||
seg fs
|
||||
lds si,(bx) ! ds:si is source
|
||||
|
||||
mov cl,#6 ! copy 12 bytes
|
||||
cld
|
||||
push di
|
||||
|
||||
rep
|
||||
movsw
|
||||
|
||||
pop di
|
||||
pop ds
|
||||
|
||||
movb 4(di),*36 ! patch sector count
|
||||
|
||||
seg fs
|
||||
mov (bx),di
|
||||
seg fs
|
||||
mov 2(bx),es
|
||||
|
||||
! load the setup-sectors directly after the bootblock.
|
||||
! Note that 'es' is already set up.
|
||||
! Also cx is 0 from rep movsw above.
|
||||
|
||||
load_setup:
|
||||
xor ah,ah ! reset FDC
|
||||
xor dl,dl
|
||||
int 0x13
|
||||
|
||||
xor dx, dx ! drive 0, head 0
|
||||
mov cl,#0x02 ! sector 2, track 0
|
||||
mov bx,#0x0200 ! address = 512, in INITSEG
|
||||
mov ah,#0x02 ! service 2, nr of sectors
|
||||
mov al,setup_sects ! (assume all on head 0, track 0)
|
||||
int 0x13 ! read it
|
||||
jnc ok_load_setup ! ok - continue
|
||||
|
||||
push ax ! dump error code
|
||||
call print_nl
|
||||
mov bp, sp
|
||||
call print_hex
|
||||
pop ax
|
||||
|
||||
jmp load_setup
|
||||
|
||||
ok_load_setup:
|
||||
|
||||
! Get disk drive parameters, specifically nr of sectors/track
|
||||
|
||||
#if 0
|
||||
|
||||
! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
|
||||
! disks. It doesn't work for one of my BIOS's (1987 Award). It was
|
||||
! fatal not to check the error code.
|
||||
|
||||
xor dl,dl
|
||||
mov ah,#0x08 ! AH=8 is get drive parameters
|
||||
int 0x13
|
||||
xor ch,ch
|
||||
#else
|
||||
|
||||
! It seems that there is no BIOS call to get the number of sectors. Guess
|
||||
! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
|
||||
! 15 if sector 15 can be read. Otherwise guess 9.
|
||||
|
||||
mov si,#disksizes ! table of sizes to try
|
||||
|
||||
probe_loop:
|
||||
lodsb
|
||||
cbw ! extend to word
|
||||
mov sectors, ax
|
||||
cmp si,#disksizes+4
|
||||
jae got_sectors ! if all else fails, try 9
|
||||
xchg ax, cx ! cx = track and sector
|
||||
xor dx, dx ! drive 0, head 0
|
||||
xor bl, bl
|
||||
mov bh,setup_sects
|
||||
inc bh
|
||||
shl bh,#1 ! address after setup (es = cs)
|
||||
mov ax,#0x0201 ! service 2, 1 sector
|
||||
int 0x13
|
||||
jc probe_loop ! try next value
|
||||
|
||||
#endif
|
||||
|
||||
got_sectors:
|
||||
|
||||
! Restore es
|
||||
|
||||
mov ax,#INITSEG
|
||||
mov es,ax
|
||||
|
||||
! Print some inane message
|
||||
|
||||
mov ah,#0x03 ! read cursor pos
|
||||
xor bh,bh
|
||||
int 0x10
|
||||
|
||||
mov cx,#9
|
||||
mov bx,#0x0007 ! page 0, attribute 7 (normal)
|
||||
mov bp,#msg1
|
||||
mov ax,#0x1301 ! write string, move cursor
|
||||
int 0x10
|
||||
|
||||
! ok, we've written the message, now
|
||||
! we want to load the system (at 0x10000)
|
||||
|
||||
mov ax,#SYSSEG
|
||||
mov es,ax ! segment of 0x010000
|
||||
call read_it
|
||||
call kill_motor
|
||||
call print_nl
|
||||
|
||||
! After that we check which root-device to use. If the device is
|
||||
! defined (!= 0), nothing is done and the given device is used.
|
||||
! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
|
||||
! depending on the number of sectors we pretend to know we have.
|
||||
|
||||
seg cs
|
||||
mov ax,root_dev
|
||||
or ax,ax
|
||||
jne root_defined
|
||||
seg cs
|
||||
mov bx,sectors
|
||||
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
|
||||
cmp bx,#15
|
||||
je root_defined
|
||||
mov al,#0x1c ! /dev/PS0 - 1.44Mb
|
||||
cmp bx,#18
|
||||
je root_defined
|
||||
mov al,#0x20 ! /dev/fd0H2880 - 2.88Mb
|
||||
cmp bx,#36
|
||||
je root_defined
|
||||
mov al,#0 ! /dev/fd0 - autodetect
|
||||
root_defined:
|
||||
seg cs
|
||||
mov root_dev,ax
|
||||
|
||||
! after that (everything loaded), we jump to
|
||||
! the setup-routine loaded directly after
|
||||
! the bootblock:
|
||||
|
||||
jmpi 0,SETUPSEG
|
||||
|
||||
! This routine loads the system at address 0x10000, making sure
|
||||
! no 64kB boundaries are crossed. We try to load it as fast as
|
||||
! possible, loading whole tracks whenever we can.
|
||||
!
|
||||
! in: es - starting address segment (normally 0x1000)
|
||||
!
|
||||
sread: .word 0 ! sectors read of current track
|
||||
head: .word 0 ! current head
|
||||
track: .word 0 ! current track
|
||||
|
||||
read_it:
|
||||
mov al,setup_sects
|
||||
inc al
|
||||
mov sread,al
|
||||
mov ax,es
|
||||
test ax,#0x0fff
|
||||
die: jne die ! es must be at 64kB boundary
|
||||
xor bx,bx ! bx is starting address within segment
|
||||
rp_read:
|
||||
#ifdef __BIG_KERNEL__
|
||||
#define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
|
||||
! NOTE: as86 can't assemble this
|
||||
CALL_HIGHLOAD_KLUDGE ! this is within setup.S
|
||||
#else
|
||||
mov ax,es
|
||||
sub ax,#SYSSEG
|
||||
#endif
|
||||
cmp ax,syssize ! have we loaded all yet?
|
||||
jbe ok1_read
|
||||
ret
|
||||
ok1_read:
|
||||
mov ax,sectors
|
||||
sub ax,sread
|
||||
mov cx,ax
|
||||
shl cx,#9
|
||||
add cx,bx
|
||||
jnc ok2_read
|
||||
je ok2_read
|
||||
xor ax,ax
|
||||
sub ax,bx
|
||||
shr ax,#9
|
||||
ok2_read:
|
||||
call read_track
|
||||
mov cx,ax
|
||||
add ax,sread
|
||||
cmp ax,sectors
|
||||
jne ok3_read
|
||||
mov ax,#1
|
||||
sub ax,head
|
||||
jne ok4_read
|
||||
inc track
|
||||
ok4_read:
|
||||
mov head,ax
|
||||
xor ax,ax
|
||||
ok3_read:
|
||||
mov sread,ax
|
||||
shl cx,#9
|
||||
add bx,cx
|
||||
jnc rp_read
|
||||
mov ax,es
|
||||
add ah,#0x10
|
||||
mov es,ax
|
||||
xor bx,bx
|
||||
jmp rp_read
|
||||
|
||||
read_track:
|
||||
pusha
|
||||
pusha
|
||||
mov ax, #0xe2e ! loading... message 2e = .
|
||||
mov bx, #7
|
||||
int 0x10
|
||||
popa
|
||||
|
||||
mov dx,track
|
||||
mov cx,sread
|
||||
inc cx
|
||||
mov ch,dl
|
||||
mov dx,head
|
||||
mov dh,dl
|
||||
and dx,#0x0100
|
||||
mov ah,#2
|
||||
|
||||
push dx ! save for error dump
|
||||
push cx
|
||||
push bx
|
||||
push ax
|
||||
|
||||
int 0x13
|
||||
jc bad_rt
|
||||
add sp, #8
|
||||
popa
|
||||
ret
|
||||
|
||||
bad_rt: push ax ! save error code
|
||||
call print_all ! ah = error, al = read
|
||||
|
||||
|
||||
xor ah,ah
|
||||
xor dl,dl
|
||||
int 0x13
|
||||
|
||||
|
||||
add sp, #10
|
||||
popa
|
||||
jmp read_track
|
||||
|
||||
/*
|
||||
* print_all is for debugging purposes.
|
||||
* It will print out all of the registers. The assumption is that this is
|
||||
* called from a routine, with a stack frame like
|
||||
* dx
|
||||
* cx
|
||||
* bx
|
||||
* ax
|
||||
* error
|
||||
* ret <- sp
|
||||
*
|
||||
*/
|
||||
|
||||
print_all:
|
||||
mov cx, #5 ! error code + 4 registers
|
||||
mov bp, sp
|
||||
|
||||
print_loop:
|
||||
push cx ! save count left
|
||||
call print_nl ! nl for readability
|
||||
|
||||
cmp cl, #5
|
||||
jae no_reg ! see if register name is needed
|
||||
|
||||
mov ax, #0xe05 + 'A - 1
|
||||
sub al, cl
|
||||
int 0x10
|
||||
|
||||
mov al, #'X
|
||||
int 0x10
|
||||
|
||||
mov al, #':
|
||||
int 0x10
|
||||
|
||||
no_reg:
|
||||
add bp, #2 ! next register
|
||||
call print_hex ! print it
|
||||
pop cx
|
||||
loop print_loop
|
||||
ret
|
||||
|
||||
print_nl:
|
||||
mov ax, #0xe0d ! CR
|
||||
int 0x10
|
||||
mov al, #0xa ! LF
|
||||
int 0x10
|
||||
ret
|
||||
|
||||
/*
|
||||
* print_hex is for debugging purposes, and prints the word
|
||||
* pointed to by ss:bp in hexadecimal.
|
||||
*/
|
||||
|
||||
print_hex:
|
||||
mov cx, #4 ! 4 hex digits
|
||||
mov dx, (bp) ! load word into dx
|
||||
print_digit:
|
||||
rol dx, #4 ! rotate so that lowest 4 bits are used
|
||||
mov ax, #0xe0f ! ah = request, al = mask for nybble
|
||||
and al, dl
|
||||
add al, #0x90 ! convert al to ascii hex (four instructions)
|
||||
daa
|
||||
adc al, #0x40
|
||||
daa
|
||||
int 0x10
|
||||
loop print_digit
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* This procedure turns off the floppy drive motor, so
|
||||
* that we enter the kernel in a known state, and
|
||||
* don't have to worry about it later.
|
||||
*/
|
||||
kill_motor:
|
||||
push dx
|
||||
mov dx,#0x3f2
|
||||
xor al, al
|
||||
outb
|
||||
pop dx
|
||||
ret
|
||||
|
||||
sectors:
|
||||
.word 0
|
||||
|
||||
disksizes:
|
||||
.byte 36,18,15,9
|
||||
|
||||
msg1:
|
||||
.byte 13,10
|
||||
.ascii "Loading"
|
||||
|
||||
.org 497
|
||||
setup_sects:
|
||||
.byte SETUPSECS
|
||||
root_flags:
|
||||
.word CONFIG_ROOT_RDONLY
|
||||
syssize:
|
||||
.word SYSSIZE
|
||||
swap_dev:
|
||||
.word SWAP_DEV
|
||||
ram_size:
|
||||
.word RAMDISK
|
||||
vid_mode:
|
||||
.word SVGA_MODE
|
||||
root_dev:
|
||||
.word ROOT_DEV
|
||||
boot_flag:
|
||||
.word 0xAA55
|
||||
|
||||
</pre>
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1995-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
20
study/sabre/os/files/Booting/MyBootSector.html
Normal file
20
study/sabre/os/files/Booting/MyBootSector.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<title>Operating Systems: My Experiences with the Boot Sector</title>
|
||||
<body BGCOLOR=#FFFFFF TEXT=#000000>
|
||||
<center><font face=Verdana size=6><b>My Experiences with the Boot Sector</b></font></center>
|
||||
<HR><p>
|
||||
|
||||
When I first started playing with OS kind of topics, the first thing that I did was make a bootsector that I stuck on a floppy... This was very interesting, as I was basically crafting my own OS. Since then, I have been distracted to work on other things... and the code has been rotting on my hard drive.<p>
|
||||
|
||||
When I was doing a clean up of my drive, I noticed it, and being the good netizen that I am, I'm giving it away. Although I haven't tested it for more than 3 years now, I believe it does do some stuff... so if you'd like to play with it, scrap a floppy and copy the boot sector onto the disk.<p>
|
||||
|
||||
This also comes with a small set of utilities (and their source as well). These were originally written in Turbo Pascal (I'm sorry! Really I am! :) with a lot of inline assembler. If you don't have Turbo Pascal, you can either use the included EXE file or convert them to C. If you do port them to C, please send them my way and other people can use them.<p>
|
||||
|
||||
Oh, the catch... there's always a catch, isn't there? I haven't worked with this stuff for over 3 years now... Which means that I probably won't be able to do an adequate job explaining it... :) It is somewhat documented... and it has function names that are longer than a character. Other than that, I can't offer much support. There are some batch files in the source directory (<TT>BOOTSEC</TT>) for doing things like compiling it and copying it onto the disk. The tools directory (<TT>NEWFAT</TT>) has stuff the tools source and executables in it.<p>
|
||||
|
||||
Pulling back very old memories, I remember that I was just starting to implement a filesystem with program loading support... other than that, you're on your own. :) If you would like to contribute something back to this page, feel free to email it to me, and I'll put your stuff here (with full credits of course)... Anyways, download it below!<p>
|
||||
|
||||
<center><font size=6><a href="MyBootSector.zip">download</a></font></center>
|
||||
|
||||
<p><hr><FONT SIZE = 4><TABLE ALIGN=RIGHT BORDER=0><TR><TD><center>
|
||||
Copyright © 1994-8 <i><a href="mailto:sabre@nondot.org">Chris Lattner</a></i><br>
|
||||
Last modified: Wednesday, 13-Sep-2000 14:10:31 CDT </center></TD></TR></TABLE>
|
||||
272
study/sabre/os/files/Booting/PolyOS.html
Normal file
272
study/sabre/os/files/Booting/PolyOS.html
Normal file
@@ -0,0 +1,272 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>AT&T Assembly from the Ground Up</TITLE>
|
||||
<META NAME="description" content="Code X software: Programming to a Higher Power, DJGPP and X11 Programming (binaries and source code), Linux and DOS (32-bit pmode), POV-Ray. Check out Code X for some cool games and X-Windows programs.">
|
||||
<META NAME="keywords" content="code x Code X codex CodeX games graphics djgpp DJGPP source code X11 x11 X-Windows x-windows programming linux Linux Jeff Weeks jeff weeks">
|
||||
<META NAME="GENERATOR" CONTENT = "I made this!">
|
||||
<META NAME="andrew_fursman" CONTENT="complete and utter looser">
|
||||
<META NAME="microsoft" CONTENT="lies and monopolies">
|
||||
</HEAD>
|
||||
|
||||
<U>
|
||||
<FONT SIZE=+3>W</FONT>RITING
|
||||
<FONT SIZE=+3>A</FONT>
|
||||
<FONT SIZE=+3>B</FONT>OOTSECTOR
|
||||
</U>
|
||||
<BR><FONT SIZE=-1>(c)1997 Jeff Weeks and Code X software</FONT><BR>
|
||||
<BR>
|
||||
|
||||
Writting your own boot sector is probably actually easier then you think.
|
||||
All you really need to know is how the Intel processor boots up. A valid boot
|
||||
sector has the code 0xAA55 at an offset of 510, and is located in the very
|
||||
first sector of the disk. Therefore, the BIOS simply checks drive 0 (A:)
|
||||
for this code. If not found, it then checks drive 128 (C:). If a valid boot
|
||||
sector is found, it is loaded into memory at location 0:07C00h.<BR>
|
||||
<BR>
|
||||
So, all you have to do is write a boot sector, assemble it into a plain binary
|
||||
file (their is no format or header to a boot sector), and write it to the
|
||||
first sector of your disk. The best way to do that would be to either use
|
||||
nasm (The netwide assembler can produce plain binary files) or assemble into a
|
||||
DOS .EXE and remove the first 512 bytes. You can also write your own program
|
||||
to write the bootsector to sector 1 of the disk using BIOS INT 13h AH=02h.<BR>
|
||||
<BR>
|
||||
Pretty simple eh? Well, in case you're still a little confused, here's a
|
||||
little bootsector from PolyOS that simply switches to protected mode,
|
||||
after checking that you have a 386+ computer. Actually, it even loads in
|
||||
the PolyFS superblock and checks if it's valid, but that's about it. Soon
|
||||
it'll load in the kernel and jump to it. The bootesctor was written with Nasm.
|
||||
<BR>
|
||||
|
||||
<PRE>
|
||||
; ------------------------------------------------------------------------
|
||||
; PolyOS boot loader code (c)1997 Jeff Weeks of Code X Software
|
||||
; ------------------------------------------------------------------------
|
||||
; This little bit of assembly is the boot loader for my operating system.
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0]
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; SECTOR ONE: THE BOOT LOADER
|
||||
; ------------------------------------------------------------------------
|
||||
; This sector detects your processor. If a 386 is found, it loads the
|
||||
; kernel from the disk and executes it (atleast it will in the future :).
|
||||
; ------------------------------------------------------------------------
|
||||
|
||||
jmp start ; skip over our data and functions
|
||||
|
||||
; -------------------------------------
|
||||
; Data used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
bootdrv db 0
|
||||
bootmsg db 'Booting PolyOS (c)1997 Cipher of Code X',13,10,0
|
||||
loadmsg db 'Loading kernel',13,10,0
|
||||
jumpmsg db 'Jumping to kernel',13,10,0
|
||||
rebootmsg db 'Press any key to reboot',13,10,0
|
||||
|
||||
; these are used in the processor identification
|
||||
processormsg db 'Checking for 386+ processor: ',0
|
||||
need386 db 'Sorry... 386+ required!',13,10,0
|
||||
found386 db 'Excellent!',13,10,0
|
||||
|
||||
; these are used when entering protected mode
|
||||
a20msg db 'Setting A20 address line',13,10,0
|
||||
pmodemsg db 'Setting CR0 -> Entering PMode',13,10,0
|
||||
|
||||
; Here's the locations of my IDT and GDT. Remember, Intel's are
|
||||
; little endian processors, therefore, these are in reversed order.
|
||||
; Also note that lidt and lgdt accept a 32-bit address and 16-bit
|
||||
; limit, therefore, these are 48-bit variables.
|
||||
pIDT dw 7FFh ; limit of 256 IDT slots
|
||||
dd 0000h ; starting at 0000
|
||||
|
||||
pGDT dw 17FFh ; limit of 768 GDT slots
|
||||
dd 0800h ; starting at 0800h (after IDT)
|
||||
|
||||
; ------------------------------------------
|
||||
; Functions used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
detect_cpu:
|
||||
mov si, processormsg ; tell the user what we're doing
|
||||
call message
|
||||
|
||||
; test if 8088/8086 is present (flag bits 12-15 will be set)
|
||||
pushf ; save the flags original value
|
||||
|
||||
xor ah,ah ; ah = 0
|
||||
push ax ; copy ax into the flags
|
||||
popf ; with bits 12-15 clear
|
||||
|
||||
pushf ; Read flags back into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are set
|
||||
cmp ah,0f0h
|
||||
je no386 ; no 386 detected (8088/8086 present)
|
||||
|
||||
; check for a 286 (bits 12-15 are clear)
|
||||
mov ah,0f0h ; set bits 12-15
|
||||
push ax ; copy ax onto the flags
|
||||
popf
|
||||
|
||||
pushf ; copy the flags into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are clear
|
||||
jz no386 ; no 386 detected (80286 present)
|
||||
popf ; pop the original flags back
|
||||
|
||||
mov si, found386
|
||||
call message
|
||||
|
||||
ret ; no 8088/8086 or 286, so ateast 386
|
||||
no386:
|
||||
mov si,need386 ; tell the user the problem
|
||||
call message
|
||||
jmp reboot ; and reboot when key pressed
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
message: ; Dump ds:si to screen.
|
||||
lodsb ; load byte at ds:si into al
|
||||
or al,al ; test if character is 0 (end)
|
||||
jz done
|
||||
mov ah,0eh ; put character
|
||||
mov bx,0007 ; attribute
|
||||
int 0x10 ; call BIOS
|
||||
jmp message
|
||||
done:
|
||||
ret
|
||||
; ------------------------------------------------------------------
|
||||
getkey:
|
||||
mov ah, 0 ; wait for key
|
||||
int 016h
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
reboot:
|
||||
mov si, rebootmsg ; be polite, and say we're rebooting
|
||||
call message
|
||||
call getkey ; and even wait for a key :)
|
||||
|
||||
db 0EAh ; machine language to jump to FFFF:0000 (reboot)
|
||||
dw 0000h
|
||||
dw 0FFFFh
|
||||
; no ret required; we're rebooting! (Hey, I just saved a byte :)
|
||||
|
||||
; -------------------------------------------
|
||||
; The actual code of our boot loading process
|
||||
; ------------------------------------------------------------------------
|
||||
start:
|
||||
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
|
||||
mov ds,ax ; Therefore, we don't have to add 07C00h to all our data
|
||||
|
||||
mov [bootdrv], dl ; quickly save what drive we booted from
|
||||
|
||||
cli ; clear interrupts while we setup a stack
|
||||
mov ax,0x9000 ; this seems to be the typical place for a stack
|
||||
mov ss,ax
|
||||
mov sp,0xffff ; let's use the whole segment. Why not? We can :)
|
||||
sti ; put our interrupts back on
|
||||
|
||||
; Interestingly enough, apparently the processor will disable
|
||||
; interupts itself when you directly access the stack segment!
|
||||
; Atleast it does in protected mode, I'm not sure about real mode.
|
||||
|
||||
mov si,bootmsg ; display our startup message
|
||||
call message
|
||||
|
||||
call detect_cpu ; check if we've got a 386
|
||||
|
||||
.386 ; use 386 instructions from now on (I don't want to manually include
|
||||
; operand-size(66h) or address-size(67h) prefixes... it's annoying :)
|
||||
|
||||
mov si,loadmsg ; tell the user we're loading the kernel
|
||||
call message
|
||||
call getkey
|
||||
|
||||
read_me:
|
||||
; first, reset the disk controller
|
||||
xor ax, ax
|
||||
int 0x13
|
||||
jc reboot ; reboot on error
|
||||
|
||||
; then load in the PolyFS superblock
|
||||
mov ax,0x09000 ; superblock goes to 9000:0000 (above stack)
|
||||
mov es,ax
|
||||
xor bx,bx
|
||||
|
||||
; I could condense a few of these high/low 8-bit movs into one 16-bit
|
||||
; mov, but, for simplicity, I'll leave it as is, unless necessary.
|
||||
mov ax,0x0202 ; load one block (two sectors)
|
||||
mov ch,0 ; cylinder = 0
|
||||
mov cl,3 ; sector = 2 (starts at sector 1 not 0)
|
||||
mov dh,0 ; head = 0 = side one
|
||||
mov dl,[bootdrv] ; disk = what we booted from
|
||||
int 0x13 ; read it
|
||||
jc read_me ; if there's an error then we'll try again.
|
||||
; Often there is not error but requires a few
|
||||
; tries. Ofcourse, this may end up as an
|
||||
; infinite loop... but only on a bad disk...
|
||||
|
||||
; Check if we have a valid super block (BTW: ES still equals 0x9000)
|
||||
mov di, 0 ; offset of PolyFS magic signature
|
||||
mov si, polymagic ; offset of PolyFS magic to check for (in ds)
|
||||
cmpsw ; compare ES:[DI] with DS:[SI]
|
||||
jnz reboot ; reboot on error (otherwise, we've got a PolyFS)
|
||||
|
||||
; Ideally, we'd load the kernel right here
|
||||
|
||||
mov si, a20msg ; tell the user we're setting the A20 line
|
||||
call message
|
||||
|
||||
; set A20 line
|
||||
cli ; no more interuptions! :)
|
||||
xor cx, cx
|
||||
clear_buf:
|
||||
in al, 64h ; get input from keyboard status port
|
||||
test al, 02h ; test the buffer full flag
|
||||
loopnz clear_buf ; loop until buffer is empty
|
||||
mov al, 0D1h ; keyboard: write to output port
|
||||
out 64h, al ; output command to keyboard
|
||||
clear_buf2:
|
||||
in al, 64h ; wait 'till buffer is empty again
|
||||
test al, 02h
|
||||
loopnz clear_buf2
|
||||
mov al, 0dfh ; keyboard: set A20
|
||||
out 60h, al ; send it to the keyboard controller
|
||||
mov cx, 14h
|
||||
wait_kbc: ; this is approx. a 25uS delay to wait
|
||||
out 0edh, ax ; for the kb controler to execute our
|
||||
loop wait_kbc ; command.
|
||||
|
||||
; the A20 line is on now. Let's load in our ITD and GDT tables...
|
||||
; Ideally, there will actually be data in their locations (by loading
|
||||
; the kernel)
|
||||
lidt [pIDT]
|
||||
lgdt [pGDT]
|
||||
|
||||
; now let's enter pmode...
|
||||
mov si, pmodemsg
|
||||
call message
|
||||
call getkey
|
||||
|
||||
mov eax, cr0 ; load the control register in
|
||||
or al, 1 ; set bit 1: pmode bit
|
||||
mov cr0, eax ; copy it back to the control register
|
||||
jmp $+2 ; and clear the prefetch queue
|
||||
nop
|
||||
nop
|
||||
|
||||
; jump to the kernel that we've loaded in...
|
||||
; For now, we'll actually just reboot (this really doesn't
|
||||
; work in protected mode, but it does reboot :)
|
||||
db 0xEA
|
||||
dw 0x0000
|
||||
dw 0xFFFF
|
||||
|
||||
; The boot sector is supposed to have to have 0xAA55 at the end of
|
||||
; the sector (the word at 510 bytes) to be loaded by the BIOS...
|
||||
times 510-($-$$) db 0
|
||||
dw 0xAA55
|
||||
</PRE>
|
||||
</HTML>
|
||||
BIN
study/sabre/os/files/Booting/bootsec1.zip
Normal file
BIN
study/sabre/os/files/Booting/bootsec1.zip
Normal file
Binary file not shown.
BIN
study/sabre/os/files/Booting/bootsec2.zip
Normal file
BIN
study/sabre/os/files/Booting/bootsec2.zip
Normal file
Binary file not shown.
195
study/sabre/os/files/Booting/enableA20.s
Normal file
195
study/sabre/os/files/Booting/enableA20.s
Normal file
@@ -0,0 +1,195 @@
|
||||
;;
|
||||
;; enableA20.s (adapted from Visopsys OS-loader)
|
||||
;;
|
||||
;; Copyright (c) 2000, J. Andrew McLaughlin
|
||||
;; You're free to use this code in any manner you like, as long as this
|
||||
;; notice is included (and you give credit where it is due), and as long
|
||||
;; as you understand and accept that it comes with NO WARRANTY OF ANY KIND.
|
||||
;; Contact me at jamesamc@yahoo.com about any bugs or problems.
|
||||
;;
|
||||
|
||||
enableA20:
|
||||
;; This subroutine will enable the A20 address line in the keyboard
|
||||
;; controller. Takes no arguments. Returns 0 in EAX on success,
|
||||
;; -1 on failure. Written for use in 16-bit code, see lines marked
|
||||
;; with 32-BIT for use in 32-bit code.
|
||||
|
||||
pusha
|
||||
|
||||
;; Make sure interrupts are disabled
|
||||
cli
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt1:
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait1
|
||||
|
||||
;; Tell the controller we want to read the current status.
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait1:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait1
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Save the current value of (E)AX
|
||||
push AX ; 16-BIT
|
||||
;; push EAX ; 32-BIT
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait2:
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait2
|
||||
|
||||
;; Tell the controller we want to write the status byte again
|
||||
mov AL, 0D1h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready for the data
|
||||
.commandWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait3
|
||||
|
||||
;; Write the new value to port 60h. Remember we saved the old
|
||||
;; value on the stack
|
||||
pop AX ; 16-BIT
|
||||
;; pop EAX ; 32-BIT
|
||||
|
||||
;; Turn on the A20 enable bit
|
||||
or AL, 00000010b
|
||||
out 60h, AL
|
||||
|
||||
;; Finally, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait4:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait4
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait2:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait2
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on.
|
||||
jc .success
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt1
|
||||
|
||||
|
||||
;; Well, our initial attempt to set A20 has failed. Now we will
|
||||
;; try a backup method (which is supposedly not supported on many
|
||||
;; chipsets, but which seems to be the only method that works on
|
||||
;; other chipsets).
|
||||
|
||||
|
||||
;; Keep a counter so that we can make up to 5 attempts to turn
|
||||
;; on A20 if necessary
|
||||
mov CX, 5
|
||||
|
||||
.startAttempt2:
|
||||
;; Wait for the keyboard to be ready for another command
|
||||
.commandWait6:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait6
|
||||
|
||||
;; Tell the controller we want to turn on A20
|
||||
mov AL, 0DFh
|
||||
out 64h, AL
|
||||
|
||||
;; Again, we will attempt to read back the A20 status
|
||||
;; to ensure it was enabled.
|
||||
|
||||
;; Wait for the controller to be ready for a command
|
||||
.commandWait7:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 1
|
||||
jc .commandWait7
|
||||
|
||||
;; Send the command D0h: read output port.
|
||||
mov AL, 0D0h
|
||||
out 64h, AL
|
||||
|
||||
;; Wait for the controller to be ready with a byte of data
|
||||
.dataWait3:
|
||||
xor AX, AX
|
||||
in AL, 64h
|
||||
bt AX, 0
|
||||
jnc .dataWait3
|
||||
|
||||
;; Read the current port status from port 60h
|
||||
xor AX, AX
|
||||
in AL, 60h
|
||||
|
||||
;; Is A20 enabled?
|
||||
bt AX, 1
|
||||
|
||||
;; Check the result. If carry is on, A20 is on, but we might warn
|
||||
;; that we had to use this alternate method
|
||||
jc .warn
|
||||
|
||||
;; Should we retry the operation? If the counter value in ECX
|
||||
;; has not reached zero, we will retry
|
||||
loop .startAttempt2
|
||||
|
||||
|
||||
;; OK, we weren't able to set the A20 address line. Do you want
|
||||
;; to put an error message here?
|
||||
jmp .fail
|
||||
|
||||
|
||||
.warn:
|
||||
;; Here you may or may not want to print a warning message about
|
||||
;; the fact that we had to use the nonstandard alternate enabling
|
||||
;; method
|
||||
|
||||
.success:
|
||||
sti
|
||||
popa
|
||||
xor EAX, EAX
|
||||
ret
|
||||
|
||||
.fail:
|
||||
sti
|
||||
popa
|
||||
mov EAX, -1
|
||||
ret
|
||||
233
study/sabre/os/files/Booting/gbootsect.txt
Normal file
233
study/sabre/os/files/Booting/gbootsect.txt
Normal file
@@ -0,0 +1,233 @@
|
||||
Bootsector authoring by Gareth Owen
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
-=- gaz@athene.co.uk -=-
|
||||
|
||||
Requirements
|
||||
============
|
||||
During this article I assume that you have good knowledge of the
|
||||
assembly language and intel architecture.
|
||||
If not, read an assembly tutorial, they aren't hard to find...
|
||||
|
||||
Start
|
||||
=====
|
||||
|
||||
Creating your own bootsector is simpler than you may think,
|
||||
the only requirement is that the bootsector is 512 bytes long, and at
|
||||
offset 0x1FE (decimal=510), the word 0xAA55 is placed. This is the first
|
||||
thing the BIOS does when the PC boots up, it first looks on the first
|
||||
floppy drive at the first sector for 0xAA55 at the end, and if it finds it
|
||||
then it loads it into memory, and starts executing it, otherwise it trys the
|
||||
primary harddisk, and if that isn't found it just bombs out with an error.
|
||||
|
||||
You should place your boot sector at:
|
||||
Sector 1
|
||||
Cylinder 0
|
||||
Head 0
|
||||
|
||||
I recommend you start playing about with floppys first instead of your hard disk
|
||||
because the hard disk bootsector stores information about the file system if you
|
||||
are running DOS/Windows, if you overrite that, then you have just lost your
|
||||
hard disk contents :-)
|
||||
|
||||
The BIOS loads the bootsector at linear offset 0x7C00, the state of
|
||||
the registers are:
|
||||
|
||||
DL = Boot drive, 1h = floppy1, 80h = primary harddisk, etc
|
||||
CS = 0
|
||||
IP = 0x7c00
|
||||
|
||||
So instead of adding [ORG 7C00h] to the top of your file, you can add:
|
||||
|
||||
mov ax, 0x7C0
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
And that will set-up the segment registers so they point to the start of
|
||||
your bootsector..
|
||||
|
||||
Most boot sectors usually just store the boot drive, load the kernel
|
||||
from disk, and jump to it.. Some will also load protected mode.
|
||||
|
||||
Since most people find it easier looking at source code and figuring
|
||||
it out than reading documentation i have included sources for a boot
|
||||
sector and a boot sector writter.
|
||||
|
||||
Here is the bootsector...
|
||||
|
||||
;******************* START ************************
|
||||
|
||||
; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
|
||||
; This should be accompanied with an article explaining bootsectors
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0] ; Data offset = 0
|
||||
|
||||
jmp start ; skip over our data and functions, we cannot execute data :-),
|
||||
; well, you can, but i am not held responsible for the results :)
|
||||
|
||||
; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
|
||||
; This should be accompanied with an article explaining bootsectors
|
||||
|
||||
[BITS 16] ; the bios starts out in 16-bit real mode
|
||||
[ORG 0] ; Data offset = 0
|
||||
|
||||
jmp start ; skip over our data and functions, we cannot execute data :-),
|
||||
; well, you can, but i am not held responsible for the results :)
|
||||
|
||||
; -------------------------------------
|
||||
; Data used in the boot-loading process
|
||||
; ------------------------------------------------------------------------
|
||||
bootdrv db 0
|
||||
bootmsg db 'Gareth Owen',39,'s Boot Sector Example',13,10,0
|
||||
|
||||
rebootmsg db 'Press any key to reboot',13,10,0
|
||||
|
||||
; these are used in the processor identification
|
||||
processormsg db 'Checking for 386+ processor: ',0
|
||||
need386 db 'Sorry... 386+ required!',13,10,0
|
||||
found386 db 'Found!',13,10,0
|
||||
|
||||
whatever db 'Insert your code to do something here',13,10,0
|
||||
|
||||
;*******************************************
|
||||
; Functions we are going to use ...
|
||||
;*******************************************
|
||||
detect_cpu:
|
||||
mov si, processormsg ; tell the user what we're doing
|
||||
call message
|
||||
|
||||
; test if 8088/8086 is present (flag bits 12-15 will be set)
|
||||
pushf ; save the flags original value
|
||||
|
||||
xor ah,ah ; ah = 0
|
||||
push ax ; copy ax into the flags
|
||||
popf ; with bits 12-15 clear
|
||||
|
||||
pushf ; Read flags back into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are set
|
||||
cmp ah,0f0h
|
||||
je no386 ; no 386 detected (8088/8086 present)
|
||||
|
||||
; check for a 286 (bits 12-15 are clear)
|
||||
mov ah,0f0h ; set bits 12-15
|
||||
push ax ; copy ax onto the flags
|
||||
popf
|
||||
|
||||
pushf ; copy the flags into ax
|
||||
pop ax
|
||||
and ah,0f0h ; check if bits 12-15 are clear
|
||||
jz no386 ; no 386 detected (80286 present)
|
||||
popf ; pop the original flags back
|
||||
|
||||
mov si, found386
|
||||
call message
|
||||
|
||||
ret ; no 8088/8086 or 286, so ateast 386
|
||||
no386:
|
||||
mov si,need386 ; tell the user the problem
|
||||
call message
|
||||
jmp reboot ; and reboot when key pressed
|
||||
|
||||
; ********************************************************************
|
||||
message: ; Dump ds:si to screen.
|
||||
lodsb ; load byte at ds:si into al
|
||||
or al,al ; test if character is 0 (end)
|
||||
jz done
|
||||
mov ah,0eh ; put character
|
||||
mov bx,0007 ; attribute
|
||||
int 0x10 ; call BIOS
|
||||
jmp message
|
||||
done:
|
||||
ret
|
||||
; ********************************************************************
|
||||
getkey:
|
||||
mov ah, 0 ; wait for key
|
||||
int 016h
|
||||
ret
|
||||
|
||||
; ********************************************************************
|
||||
reboot:
|
||||
mov si, rebootmsg ; be polite, and say we're rebooting
|
||||
call message
|
||||
call getkey ; and even wait for a key :)
|
||||
|
||||
db 0EAh ; machine language to jump to FFFF:0000 (reboot)
|
||||
|
||||
dw 0000h
|
||||
dw 0FFFFh
|
||||
; no ret required; we're rebooting! (Hey, I just saved a byte :)
|
||||
|
||||
; *******************************************
|
||||
; The actual code of our boot loading process
|
||||
; *******************************************
|
||||
start:
|
||||
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
|
||||
mov ds,ax ; Therefore, we don't have to add 07C00h to all our
|
||||
data
|
||||
|
||||
mov [bootdrv], dl ; quickly save what drive we booted from
|
||||
|
||||
cli ; clear interrupts while we setup a stack
|
||||
mov ax,0x9000 ; this seems to be the typical place for a stack
|
||||
mov ss,ax
|
||||
mov sp,0xffff ; let's use the whole segment. Why not? We can :)
|
||||
sti ; put our interrupts back on
|
||||
|
||||
; Interestingly enough, apparently the processor will disable
|
||||
; interupts itself when you directly access the stack segment!
|
||||
; Atleast it does in protected mode, I'm not sure about real mode.
|
||||
|
||||
mov si,bootmsg ; display our startup message
|
||||
call message
|
||||
|
||||
call detect_cpu ; check if we've got a 386
|
||||
|
||||
.386 ; use 386 instructions from now on (I don't want to manually include
|
||||
; operand-size(66h) or address-size(67h) prefixes... it's annoying :)
|
||||
|
||||
mov si,whatever ; tell the user we're not doing anything interesting here
|
||||
call message
|
||||
call getkey
|
||||
|
||||
call reboot
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0xAA55
|
||||
|
||||
;******************** GBOOTSECT END *************************
|
||||
|
||||
Here is the code for writting the bootsector to a floppy disk.
|
||||
It has been compiled with DJGPP for DOS.
|
||||
It writes the file 'bootsect', onto Sector 1, Cylinder 0, Head 0 of
|
||||
the floppy drive.
|
||||
|
||||
//***************START****************
|
||||
#include <bios.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
FILE *in;
|
||||
unsigned char buffer[520];
|
||||
|
||||
if((in = fopen("bootsect", "rb"))==NULL)
|
||||
{
|
||||
printf("Error loading file\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fread(&buffer, 512, 1, in);
|
||||
|
||||
while(biosdisk(3, 0, 0, 0, 1, 1, buffer));
|
||||
|
||||
fclose(in);
|
||||
}
|
||||
//*************END****************************
|
||||
|
||||
Well, if you still don't understand something, then mail me
|
||||
at gaz@athene.co.uk and i'll help you out
|
||||
|
||||
- Gareth Owen
|
||||
7
study/sabre/os/files/Booting/index.html
Normal file
7
study/sabre/os/files/Booting/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
272
study/sabre/os/files/Booting/mbr.txt
Normal file
272
study/sabre/os/files/Booting/mbr.txt
Normal file
@@ -0,0 +1,272 @@
|
||||
How It Works -- Master Boot Record
|
||||
|
||||
Version 1a
|
||||
|
||||
by Hale Landis (landis@sugs.tware.com)
|
||||
|
||||
|
||||
THE "HOW IT WORKS" SERIES
|
||||
|
||||
This is one of several How It Works documents. The series
|
||||
currently includes the following:
|
||||
|
||||
* How It Works -- CHS Translation
|
||||
* How It Works -- Master Boot Record
|
||||
* How It Works -- DOS Floppy Boot Sector
|
||||
* How It Works -- OS2 Boot Sector
|
||||
* How It Works -- Partition Tables
|
||||
|
||||
|
||||
MASTER BOOT RECORD
|
||||
|
||||
This article is a disassembly of a Master Boot Record (MBR). The
|
||||
MBR is the sector at cylinder 0, head 0, sector 1 of a hard disk.
|
||||
An MBR is created by the FDISK program. The FDISK program of all
|
||||
operating systems must create a functionally similar MBR. The MBR
|
||||
is first of what could be many partition sectors, each one
|
||||
containing a four entry partition table.
|
||||
|
||||
At the completion of your system's Power On Self Test (POST), INT
|
||||
19 is called. Usually INT 19 tries to read a boot sector from
|
||||
the first floppy drive. If a boot sector is found on the floppy
|
||||
disk, the that boot sector is read into memory at location
|
||||
0000:7C00 and INT 19 jumps to memory location 0000:7C00.
|
||||
However, if no boot sector is found on the first floppy drive,
|
||||
INT 19 tries to read the MBR from the first hard drive. If an
|
||||
MBR is found it is read into memory at location 0000:7c00 and INT
|
||||
19 jumps to memory location 0000:7c00. The small program in the
|
||||
MBR will attempt to locate an active (bootable) partition in its
|
||||
partition table. If such a partition is found, the boot sector
|
||||
of that partition is read into memory at location 0000:7C00 and
|
||||
the MBR program jumps to memory location 0000:7C00. Each
|
||||
operating system has its own boot sector format. The small
|
||||
program in the boot sector must locate the first part of the
|
||||
operating system's kernel loader program (or perhaps the kernel
|
||||
itself or perhaps a "boot manager program") and read that into
|
||||
memory.
|
||||
|
||||
INT 19 is also called when the CTRL-ALT-DEL keys are used. On
|
||||
most systems, CTRL-ALT-DEL causes an short version of the POST to
|
||||
be executed before INT 19 is called.
|
||||
|
||||
=====
|
||||
|
||||
Where stuff is:
|
||||
|
||||
The MBR program code starts at offset 0000.
|
||||
The MBR messages start at offset 008b.
|
||||
The partition table starts at offset 00be.
|
||||
The signature is at offset 00fe.
|
||||
|
||||
Here is a summary of what this thing does:
|
||||
|
||||
If an active partition is found, that partition's boot record
|
||||
is read into 0000:7c00 and the MBR code jumps to 0000:7c00
|
||||
with SI pointing to the partition table entry that describes
|
||||
the partition being booted. The boot record program uses this
|
||||
data to determine the drive being booted from and the location
|
||||
of the partition on the disk.
|
||||
|
||||
If no active partition table enty is found, ROM BASIC is
|
||||
entered via INT 18. All other errors cause a system hang, see
|
||||
label HANG.
|
||||
|
||||
NOTES (VERY IMPORTANT):
|
||||
|
||||
1) The first byte of an active partition table entry is 80.
|
||||
This byte is loaded into the DL register before INT 13 is
|
||||
called to read the boot sector. When INT 13 is called, DL is
|
||||
the BIOS device number. Because of this, the boot sector read
|
||||
by this MBR program can only be read from BIOS device number
|
||||
80 (the first hard disk). This is one of the reasons why it
|
||||
is usually not possible to boot from any other hard disk.
|
||||
|
||||
2) The MBR program uses the CHS based INT 13H AH=02H call to
|
||||
read the boot sector of the active partition. The location of
|
||||
the active partition's boot sector is in the partition table
|
||||
entry in CHS format. If the drive is >528MB, this CHS must be
|
||||
a translated CHS (or L-CHS, see my BIOS TYPES document).
|
||||
No addresses in LBA form are used (another reason why LBA
|
||||
doesn't solve the >528MB problem).
|
||||
|
||||
=====
|
||||
|
||||
Here is the entire MBR record (hex dump and ascii).
|
||||
|
||||
OFFSET 0 1 2 3 4 5 6 7 8 9 A B C D E F *0123456789ABCDEF*
|
||||
000000 fa33c08e d0bc007c 8bf45007 501ffbfc *.3.....|..P.P...*
|
||||
000010 bf0006b9 0001f2a5 ea1d0600 00bebe07 *................*
|
||||
000020 b304803c 80740e80 3c00751c 83c610fe *...<.t..<.u.....*
|
||||
000030 cb75efcd 188b148b 4c028bee 83c610fe *.u......L.......*
|
||||
000040 cb741a80 3c0074f4 be8b06ac 3c00740b *.t..<.t.....<.t.*
|
||||
000050 56bb0700 b40ecd10 5eebf0eb febf0500 *V.......^.......*
|
||||
000060 bb007cb8 010257cd 135f730c 33c0cd13 *..|...W.._s.3...*
|
||||
000070 4f75edbe a306ebd3 bec206bf fe7d813d *Ou...........}.=*
|
||||
000080 55aa75c7 8bf5ea00 7c000049 6e76616c *U.u.....|..Inval*
|
||||
000090 69642070 61727469 74696f6e 20746162 *id partition tab*
|
||||
0000a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading*
|
||||
0000b0 206f7065 72617469 6e672073 79737465 * operating syste*
|
||||
0000c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat*
|
||||
0000d0 696e6720 73797374 656d0000 00000000 *ing system......*
|
||||
0000e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000f0 TO 0001af SAME AS ABOVE
|
||||
0001b0 00000000 00000000 00000000 00008001 *................*
|
||||
0001c0 0100060d fef83e00 00000678 0d000000 *......>....x....*
|
||||
0001d0 00000000 00000000 00000000 00000000 *................*
|
||||
0001e0 00000000 00000000 00000000 00000000 *................*
|
||||
0001f0 00000000 00000000 00000000 000055aa *..............U.*
|
||||
|
||||
=====
|
||||
|
||||
Here is the disassembly of the MBR...
|
||||
|
||||
This sector is initially loaded into memory at 0000:7c00 but
|
||||
it immediately relocates itself to 0000:0600.
|
||||
|
||||
BEGIN: NOW AT 0000:7C00, RELOCATE
|
||||
|
||||
0000:7C00 FA CLI disable int's
|
||||
0000:7C01 33C0 XOR AX,AX set stack seg to 0000
|
||||
0000:7C03 8ED0 MOV SS,AX
|
||||
0000:7C05 BC007C MOV SP,7C00 set stack ptr to 7c00
|
||||
0000:7C08 8BF4 MOV SI,SP SI now 7c00
|
||||
0000:7C0A 50 PUSH AX
|
||||
0000:7C0B 07 POP ES ES now 0000:7c00
|
||||
0000:7C0C 50 PUSH AX
|
||||
0000:7C0D 1F POP DS DS now 0000:7c00
|
||||
0000:7C0E FB STI allow int's
|
||||
0000:7C0F FC CLD clear direction
|
||||
0000:7C10 BF0006 MOV DI,0600 DI now 0600
|
||||
0000:7C13 B90001 MOV CX,0100 move 256 words (512 bytes)
|
||||
0000:7C16 F2 REPNZ move MBR from 0000:7c00
|
||||
0000:7C17 A5 MOVSW to 0000:0600
|
||||
0000:7C18 EA1D060000 JMP 0000:061D jmp to NEW_LOCATION
|
||||
|
||||
NEW_LOCATION: NOW AT 0000:0600
|
||||
|
||||
0000:061D BEBE07 MOV SI,07BE point to first table entry
|
||||
0000:0620 B304 MOV BL,04 there are 4 table entries
|
||||
|
||||
SEARCH_LOOP1: SEARCH FOR AN ACTIVE ENTRY
|
||||
|
||||
0000:0622 803C80 CMP BYTE PTR [SI],80 is this the active entry?
|
||||
0000:0625 740E JZ FOUND_ACTIVE yes
|
||||
0000:0627 803C00 CMP BYTE PTR [SI],00 is this an inactive entry?
|
||||
0000:062A 751C JNZ NOT_ACTIVE no
|
||||
0000:062C 83C610 ADD SI,+10 incr table ptr by 16
|
||||
0000:062F FECB DEC BL decr count
|
||||
0000:0631 75EF JNZ SEARCH_LOOP1 jmp if not end of table
|
||||
0000:0633 CD18 INT 18 GO TO ROM BASIC
|
||||
|
||||
FOUND_ACTIVE: FOUND THE ACTIVE ENTRY
|
||||
|
||||
0000:0635 8B14 MOV DX,[SI] set DH/DL for INT 13 call
|
||||
0000:0637 8B4C02 MOV CX,[SI+02] set CH/CL for INT 13 call
|
||||
0000:063A 8BEE MOV BP,SI save table ptr
|
||||
|
||||
SEARCH_LOOP2: MAKE SURE ONLY ONE ACTIVE ENTRY
|
||||
|
||||
0000:063C 83C610 ADD SI,+10 incr table ptr by 16
|
||||
0000:063F FECB DEC BL decr count
|
||||
0000:0641 741A JZ READ_BOOT jmp if end of table
|
||||
0000:0643 803C00 CMP BYTE PTR [SI],00 is this an inactive entry?
|
||||
0000:0646 74F4 JZ SEARCH_LOOP2 yes
|
||||
|
||||
NOT_ACTIVE: MORE THAN ONE ACTIVE ENTRY FOUND
|
||||
|
||||
0000:0648 BE8B06 MOV SI,068B display "Invld prttn tbl"
|
||||
|
||||
DISPLAY_MSG: DISPLAY MESSAGE LOOP
|
||||
|
||||
0000:064B AC LODSB get char of message
|
||||
0000:064C 3C00 CMP AL,00 end of message
|
||||
0000:064E 740B JZ HANG yes
|
||||
0000:0650 56 PUSH SI save SI
|
||||
0000:0651 BB0700 MOV BX,0007 screen attributes
|
||||
0000:0654 B40E MOV AH,0E output 1 char of message
|
||||
0000:0656 CD10 INT 10 to the display
|
||||
0000:0658 5E POP SI restore SI
|
||||
0000:0659 EBF0 JMP DISPLAY_MSG do it again
|
||||
|
||||
HANG: HANG THE SYSTEM LOOP
|
||||
|
||||
0000:065B EBFE JMP HANG sit and stay!
|
||||
|
||||
READ_BOOT: READ ACTIVE PARITION BOOT RECORD
|
||||
|
||||
0000:065D BF0500 MOV DI,0005 INT 13 retry count
|
||||
|
||||
INT13RTRY: INT 13 RETRY LOOP
|
||||
|
||||
0000:0660 BB007C MOV BX,7C00
|
||||
0000:0663 B80102 MOV AX,0201 read 1 sector
|
||||
0000:0666 57 PUSH DI save DI
|
||||
0000:0667 CD13 INT 13 read sector into 0000:7c00
|
||||
0000:0669 5F POP DI restore DI
|
||||
0000:066A 730C JNB INT13OK jmp if no INT 13
|
||||
0000:066C 33C0 XOR AX,AX call INT 13 and
|
||||
0000:066E CD13 INT 13 do disk reset
|
||||
0000:0670 4F DEC DI decr DI
|
||||
0000:0671 75ED JNZ INT13RTRY if not zero, try again
|
||||
0000:0673 BEA306 MOV SI,06A3 display "Errr ldng systm"
|
||||
0000:0676 EBD3 JMP DISPLAY_MSG jmp to display loop
|
||||
|
||||
INT13OK: INT 13 ERROR
|
||||
|
||||
0000:0678 BEC206 MOV SI,06C2 "missing op sys"
|
||||
0000:067B BFFE7D MOV DI,7DFE point to signature
|
||||
0000:067E 813D55AA CMP WORD PTR [DI],AA55 is signature correct?
|
||||
0000:0682 75C7 JNZ DISPLAY_MSG no
|
||||
0000:0684 8BF5 MOV SI,BP set SI
|
||||
0000:0686 EA007C0000 JMP 0000:7C00 JUMP TO THE BOOT SECTOR
|
||||
WITH SI POINTING TO
|
||||
PART TABLE ENTRY
|
||||
|
||||
Messages here.
|
||||
|
||||
0000:0680 ........ ........ ......49 6e76616c * Inval*
|
||||
0000:0690 69642070 61727469 74696f6e 20746162 *id partition tab*
|
||||
0000:06a0 6c650045 72726f72 206c6f61 64696e67 *le.Error loading*
|
||||
0000:06b0 206f7065 72617469 6e672073 79737465 * operating syste*
|
||||
0000:06c0 6d004d69 7373696e 67206f70 65726174 *m.Missing operat*
|
||||
0000:06d0 696e6720 73797374 656d00.. ........ *ing system. *
|
||||
|
||||
Data not used.
|
||||
|
||||
0000:06d0 ........ ........ ......00 00000000 * .....*
|
||||
0000:06e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:06f0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0700 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0710 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0720 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0730 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0740 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0750 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0760 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0770 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0780 00000000 00000000 00000000 00000000 *................*
|
||||
0000:0790 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07a0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07b0 00000000 00000000 00000000 0000.... *............ *
|
||||
|
||||
The partition table starts at 0000:07be. Each partition table
|
||||
entry is 16 bytes. This table defines a single primary partition
|
||||
which is also an active (bootable) partition.
|
||||
|
||||
0000:07b0 ........ ........ ........ ....8001 * ....*
|
||||
0000:07c0 0100060d fef83e00 00000678 0d000000 *......>....x....*
|
||||
0000:07d0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07e0 00000000 00000000 00000000 00000000 *................*
|
||||
0000:07f0 00000000 00000000 00000000 0000.... *............ *
|
||||
|
||||
The last two bytes contain a 55AAH signature.
|
||||
|
||||
0000:07f0 ........ ........ ........ ....55aa *..............U.*
|
||||
|
||||
/end/
|
||||
--
|
||||
\\===============\\=======================\\
|
||||
\\ Hale Landis \\ 303-548-0567 \\
|
||||
// Niwot, CO USA // landis@sugs.tware.com //
|
||||
//===============//=======================//
|
||||
|
||||
261
study/sabre/os/files/Booting/nasmBoot.txt
Normal file
261
study/sabre/os/files/Booting/nasmBoot.txt
Normal file
@@ -0,0 +1,261 @@
|
||||
========================================
|
||||
Daniels NASM bootstraps tutorial
|
||||
========================================
|
||||
|
||||
author: Daniel Marjam<61>ki (daniel.marjamaki@home.se)
|
||||
|
||||
|
||||
|
||||
Preface
|
||||
-------
|
||||
This tutorial is a guide for those who want to create
|
||||
their own bootstraps.
|
||||
|
||||
|
||||
The basics
|
||||
----------
|
||||
These are the rules that you must follow:
|
||||
- The BIOS will load your bootstrap to address 07C00h.
|
||||
Sadly, the segment and offset varies.
|
||||
- Bootstraps must be compiled as plain binary files.
|
||||
- The filesize for the plain binary file must be 512
|
||||
bytes.
|
||||
- The file must end with AA55h.
|
||||
|
||||
|
||||
A minimal bootstrap
|
||||
-------------------
|
||||
This bootstrap just hangs:
|
||||
|
||||
; HANG.ASM
|
||||
; A minimal bootstrap
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0 ; Fill the file with 0's
|
||||
dw 0AA55h ; End the file with AA55
|
||||
|
||||
The line starting with "times" is a command that only
|
||||
NASM understands. The line will insert 0's until the
|
||||
filesize is 510 bytes. The whole file will therefore be
|
||||
512 bytes.
|
||||
The last instruction puts AA55 at the end of the file.
|
||||
|
||||
To compile the bootstrap, use this command:
|
||||
nasm hang.asm -o hang.bin
|
||||
|
||||
If you want to test the bootstrap, you must first put it
|
||||
on the first sector on a floppy disk. You can for example
|
||||
use 'dd' or 'rawrite'.
|
||||
When the bootstrap is on the floppy, test it by
|
||||
restarting your computer with the floppy inserted. The
|
||||
computer should hang then.
|
||||
|
||||
|
||||
The memory problem
|
||||
------------------
|
||||
There is a memory problem.
|
||||
As I've written bootstraps are always loaded to address
|
||||
07C00. We don't know what segment and offset the BIOS has
|
||||
put us in. The segment can be anything between 0000 and
|
||||
07C0. This is a problem when we want to use variables.
|
||||
The solution is simple. Begin your bootstrap by jumping
|
||||
to your bootstrap, but jump to a known segment.
|
||||
|
||||
Here is an example:
|
||||
|
||||
; JUMP.ASM
|
||||
; Make a jump and then hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
If you compile and test this bootstrap, there will be no
|
||||
visible difference to the minimal bootstrap presented
|
||||
earlier. The computer will just hang.
|
||||
|
||||
|
||||
Some exercises
|
||||
--------------
|
||||
1. Create a bootstrap that outputs "====" on the screen,
|
||||
and then hangs. Tip: modify the jump.asm program.
|
||||
2. Create a bootstrap that outputs "Hello Cyberspace!"
|
||||
and hangs.
|
||||
3. Create a bootstrap that loads a program off the floppy
|
||||
disk and jumps to it.
|
||||
|
||||
|
||||
Solutions to the exercises
|
||||
--------------------------
|
||||
|
||||
1.
|
||||
|
||||
; 1.ASM
|
||||
; Print "====" on the screen and hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
mov ah, 9 ; Print "===="
|
||||
mov al, '=' ;
|
||||
mov bx, 7 ;
|
||||
mov cx, 4 ;
|
||||
int 10h ;
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
2.
|
||||
|
||||
; 2.ASM
|
||||
; Print "Hello Cyberspace!" on the screen and hang
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
; Declare the string that will be printed
|
||||
msg db 'Hello Cyberspace!'
|
||||
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
|
||||
mov si, msg ; Print msg
|
||||
print:
|
||||
lodsb ; AL=memory contents at DS:SI
|
||||
|
||||
cmp al, 0 ; If AL=0 then hang
|
||||
je hang
|
||||
|
||||
mov ah, 0Eh ; Print AL
|
||||
mov bx, 7
|
||||
int 10h
|
||||
|
||||
jmp print ; Print next character
|
||||
|
||||
|
||||
hang: ; Hang!
|
||||
jmp hang
|
||||
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
3.
|
||||
|
||||
; 3.ASM
|
||||
; Load a program off the disk and jump to it
|
||||
|
||||
; Tell the compiler that this is offset 0.
|
||||
; It isn't offset 0, but it will be after the jump.
|
||||
[ORG 0]
|
||||
|
||||
jmp 07C0h:start ; Goto segment 07C0
|
||||
|
||||
start:
|
||||
; Update the segment registers
|
||||
mov ax, cs
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
|
||||
reset: ; Reset the floppy drive
|
||||
mov ax, 0 ;
|
||||
mov dl, 0 ; Drive=0 (=A)
|
||||
int 13h ;
|
||||
jc reset ; ERROR => reset again
|
||||
|
||||
|
||||
read:
|
||||
mov ax, 1000h ; ES:BX = 1000:0000
|
||||
mov es, ax ;
|
||||
mov bx, 0 ;
|
||||
|
||||
mov ah, 2 ; Load disk data to ES:BX
|
||||
mov al, 5 ; Load 5 sectors
|
||||
mov ch, 0 ; Cylinder=0
|
||||
mov cl, 2 ; Sector=2
|
||||
mov dh, 0 ; Head=0
|
||||
mov dl, 0 ; Drive=0
|
||||
int 13h ; Read!
|
||||
|
||||
jc read ; ERROR => Try again
|
||||
|
||||
|
||||
jmp 1000h:0000 ; Jump to the program
|
||||
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0AA55h
|
||||
|
||||
|
||||
|
||||
This is a small loadable program.
|
||||
|
||||
; PROG.ASM
|
||||
|
||||
mov ah, 9
|
||||
mov al, '='
|
||||
mov bx, 7
|
||||
mov cx, 10
|
||||
int 10h
|
||||
|
||||
hang:
|
||||
jmp hang
|
||||
|
||||
|
||||
This program creates a disk image file that contains both
|
||||
the bootstrap and the small loadable program.
|
||||
|
||||
; IMAGE.ASM
|
||||
; Disk image
|
||||
|
||||
%include '3.asm'
|
||||
%include 'prog.asm'
|
||||
|
||||
|
||||
|
||||
|
||||
Finally
|
||||
-------
|
||||
Thanks for reading.
|
||||
Email me any suggestions, comments, questions, ...
|
||||
If you don't use NASM and are having problems with the
|
||||
code, you should contact me. Together we can solve it.
|
||||
894
study/sabre/os/files/Booting/win95.asm
Normal file
894
study/sabre/os/files/Booting/win95.asm
Normal file
@@ -0,0 +1,894 @@
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; Description: Heroic attempt to disassemble the Windows 95 Boot Sector.
|
||||
; Date: 16. Aug. 1998
|
||||
; Author: Mr. X
|
||||
; Email: unknown
|
||||
; Comment: This boot code is messy.
|
||||
; Status: PART I, II and III are now pretty much done.
|
||||
; Important: "SHLD EDX,EAX,16" This is a Microsoft Patent.
|
||||
; Also take a look at the "list near EOF"
|
||||
;
|
||||
; ---> CUT HERE IF YOU LIKE TO LISTEN TO ME <---
|
||||
;
|
||||
; This file will assemble into a fully functional (I hope) Win95B boot code.
|
||||
;
|
||||
; tasm win95 /m
|
||||
; tlink win95,win95.bin /t
|
||||
;
|
||||
; Ask someone for the proper dropper code...
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; AFTER DISASSEMBLY I have this impression:
|
||||
;
|
||||
; This is what Bill Gates said... when Win95 was going to be released:
|
||||
;
|
||||
; "Gates: OK, then we're ready to press the CD's and start shipping out
|
||||
; this new load of shit, but of course nobody will notice... harr harr.
|
||||
; Employee: Hey, Mr. Gates what about the Boot Sector?? We haven't
|
||||
; written the FAT32 support routines there yet...
|
||||
; Gates: Ah, that's right... anybody?? We have just 45 minutes...
|
||||
; Employee #2: Well, I think I can hack some shit together...
|
||||
; Gates: Fine, go for it... remember you have only 44 minutes...
|
||||
; Employee #2: I think I can do it.
|
||||
; Gates: Fine, then I'll just go home... We've made it!!"
|
||||
;
|
||||
; FUNNY?
|
||||
;
|
||||
; There is some really strange code in this boot record....
|
||||
;
|
||||
; I bet Bill Gates hired some crazy mother fucker to write this shit.
|
||||
; It seems like he had really tried to make the code fit within one sector.
|
||||
; But when it didn't hid just decided to use three instead...
|
||||
;
|
||||
; This is a typical microsoft solution, they mix stupid 8086 code... with
|
||||
; cheap solutions and then suddenly they use 386 code...
|
||||
;
|
||||
; And then there is the new FAT32 data structures where they have moved
|
||||
; the volume label, FileSystem ID and serial number down to make room for
|
||||
; some extended FAT32 variables... it sucks. Why not rearange the whole
|
||||
; structure... An OS would not try to interpret the shit anyway, because
|
||||
; the Partitioni Table SYSID has changed with FAT32.
|
||||
;
|
||||
; As I said... crazy mother fucker...
|
||||
;
|
||||
; Well, well... here's some of the stuff... with a mix of mine and sourcer's
|
||||
; comments...
|
||||
;
|
||||
; Another thing about TASM, which I use, of course I didn't buy it... I'm
|
||||
; have a shareware version ;) on a 30 year trial period.
|
||||
;
|
||||
; Back to what I was about to say again... When I use the brXXXX variables
|
||||
; in indexing with BP, TASM generates 16-bit offset in operands even when
|
||||
; they are less than 128... the Win95 code uses byte offsets (I'm not sure
|
||||
; if I'm expressing myself clear here). When I changed the code from:
|
||||
;
|
||||
; mov AX,[bp+brHPC] to mov AX,[bp+128], TASM did use the byte offset form...
|
||||
; This made my code a little less readable... but the comments should give
|
||||
; you an idea of what data is being accessed.
|
||||
;
|
||||
; Basically this boot sector code is 32 bit extension for a 16 bit patch to
|
||||
; an 8 bit boot sector originally coded for a 4 bit microprocessor, written
|
||||
; by a 2 bit company, that can't stand 1 bit of competition.
|
||||
;
|
||||
; ---> CUT HERE IF YOU DOES NOT LIKE TO LISTEN TO ME <---
|
||||
|
||||
.386C
|
||||
|
||||
CODE SEGMENT USE16
|
||||
|
||||
ASSUME CS:CODE, DS:CODE, SS:NOTHING
|
||||
|
||||
; BOOT RECORD - PART I - MAIN BOOT SECTOR CODE
|
||||
|
||||
; Just so I've said it - ASM opcodes are only readable when capitalized,
|
||||
; but I forgot to set the option in sourcer... so I wrote a small TP program
|
||||
; that capitalized everything but what's after the semicolon...
|
||||
|
||||
Win95b PROC FAR
|
||||
|
||||
JMP SkipData ; 0000h
|
||||
|
||||
brINT13Flag DB 90H ; 0002h - 0EH for INT13 AH=42 READ
|
||||
brOEM DB 'MSWIN4.1' ; 0003h - OEM ID - Windows 95B
|
||||
brBPS DW 512 ; 000Bh - Bytes per sector
|
||||
brSPC DB 8 ; 000Dh - Sector per cluster
|
||||
brResCount DW 32 ; 000Eh - Reserved sectors
|
||||
brFATs DB 2 ; 0010h - FAT copies
|
||||
brRootEntries DW 0 ; 0011h - Root directory entries
|
||||
brSectorCount DW 0 ; 0013h - Sectors in volume, < 32MB
|
||||
brMedia DB 0F8H ; 0015h - Media descriptor
|
||||
brSPF DW 0 ; 0016h - Sectors per FAT
|
||||
brSPH DW 63 ; 0018h - Sectors per head/track
|
||||
brHPC DW 128 ; 001Ah - Heads per cylinder
|
||||
brHidden DD 63 ; 001Ch - Hidden sectors
|
||||
brSectors DD 6305985 ; 0020h - Total number of sectors
|
||||
brSPF32 DD 6153 ; 0024h - Sector per FAT (FAT32)
|
||||
brFlags DW 0 ; 0028h - Flags (FAT32)
|
||||
brVersion DW 0 ; 002Ah - FS Version (FAT32)
|
||||
brRootCluster DD 2 ; 002Ch - Root start cluster (FAT32)
|
||||
brFSInfoSector DW 1 ; 0030h - FS Info Sector (FAT32)
|
||||
brBackupBoot DW 6 ; 0032h - Backup Boot Record
|
||||
brReserved DB 6 DUP (0) ; 0038h - Reserved
|
||||
brShitter DB 6 DUP (0) ; 003Bh - Unused filler??
|
||||
brDrive DB 80H ; 0040h - BIOS drive number
|
||||
brHeadTemp DB 00H ; 0041h - Head/temp number????
|
||||
brSignature DB 29H ; 0042h - Extended Boot Record sig.
|
||||
brSerialNum DD 404418EAH ; 0043h - Volume serial number
|
||||
brLabel DB 'HARDDISK ' ; 0047h - Volume label
|
||||
brFSID DB 'FAT32 ' ; 0052h - File System ID
|
||||
|
||||
SkipData:
|
||||
CLI
|
||||
XOR CX,CX
|
||||
MOV SS,CX ; SS=CX=0
|
||||
|
||||
; Set up stack 8 bytes below us, do you know why???
|
||||
; Yes, it's because somewhere in this code, the shitter who
|
||||
; wrote this... save the start of data area DWORD at 7C00H - 4 and
|
||||
; the value -1 at 7C00H - 8... cool?
|
||||
|
||||
MOV SP,7C00H - 8
|
||||
MOV ES,CX ; ES=CX=0
|
||||
MOV BP,78H
|
||||
|
||||
; Point DS:SI to INT 1E - DISKETTE PARAMS structure...
|
||||
|
||||
LDS SI,DWORD PTR SS:[BP]
|
||||
|
||||
PUSH DS
|
||||
PUSH SI
|
||||
PUSH SS
|
||||
PUSH BP
|
||||
|
||||
MOV DI,522H
|
||||
|
||||
MOV SS:[BP],DI ; setup our INT 1E
|
||||
MOV SS:[BP+2],CX
|
||||
|
||||
; copy 11 bytes from old diskette parameter table into
|
||||
; es:522h, that is 0000:0522 or 0050:0022 - into the PrtScr/DOS area.
|
||||
; I assume that 0001-0021 is used for something else 0050:0000 I know
|
||||
; is the PrtScr flag byte.
|
||||
|
||||
MOV CL,11
|
||||
CLD
|
||||
REP MOVSB
|
||||
|
||||
MOV DS,CX ; DS=CX=0
|
||||
|
||||
MOV BP,7C00H ; point BP to start of us
|
||||
|
||||
MOV BYTE PTR [DI-2],0FH ; modify head settle time
|
||||
|
||||
MOV AX,SS:[BP+18H]
|
||||
|
||||
MOV [DI-7],AL ; modify sectors per track
|
||||
|
||||
; compare drive number with 0...
|
||||
; if greater than or equal... go to MBRReadError
|
||||
; I guess that lower than zero... must be -1 .. -128 (80H..FFH)
|
||||
; Which would mean Harddisk boot...
|
||||
|
||||
CMP SS:[BP+40H],CL ; Boot from diskette?
|
||||
JGE MBRReadError
|
||||
|
||||
MOV AX,CX ; AX=CX=0
|
||||
CWD ; DX=AX[15]-> (ZerO)
|
||||
|
||||
MOV BX,0700H ; Use 0000:0700 for sector
|
||||
; read buffer
|
||||
|
||||
CALL ReadSector ; load Master Boot Record
|
||||
JC MBRReadError ; error?
|
||||
|
||||
SUB BX,58 ; BX = 08C6h (700h - 3Ah)
|
||||
; point to "start" field
|
||||
|
||||
MOV EAX,DS:[7C1CH] ; load hidden sectors
|
||||
CheckMBR:
|
||||
CMP EAX,[BX] ; Is this our entry??
|
||||
|
||||
MOV DL,[BX-4] ; Put System ID in DL
|
||||
|
||||
JNZ NotOurs ; Jump if not our entry
|
||||
|
||||
; If system ID or "partition type", is 0Ch or 0Eh, ReadSector
|
||||
; will use INT13/42H...
|
||||
|
||||
OR DL,2 ; set bit 1, to allow for
|
||||
; types 0Ch or 0Eh to be
|
||||
; thought of as both 0Eh.
|
||||
|
||||
MOV SS:[BP+2],DL ; set brINT13Flag
|
||||
NotOurs:
|
||||
ADD BL,16 ; skip to next entry...
|
||||
JNB CheckMBR ; More entries?
|
||||
MBRReadError:
|
||||
MOV DI,2
|
||||
|
||||
; FAT32 - Is sector per FAT zero?
|
||||
|
||||
CMP WORD PTR SS:[BP+16H],0
|
||||
JNE ShowErrMsg1
|
||||
|
||||
; Put number of hidden sectors in DX:AX
|
||||
|
||||
MOV AX,WORD PTR SS:[BP+1CH]
|
||||
MOV DX,WORD PTR SS:[BP+1EH]
|
||||
|
||||
MOV CX,3 ; Boot Record is 3 sectors...
|
||||
|
||||
; Start loading reminder of Boot Record for FAT32
|
||||
LoadIt:
|
||||
DEC CX
|
||||
INC AX ; next Boot Record sector
|
||||
|
||||
JNZ Skipper ; AX wrap-around?
|
||||
INC DX ; Yes, inc DX too
|
||||
Skipper:
|
||||
MOV BX,7E00H ; into 0000:7E00
|
||||
|
||||
CALL ReadSectorX ; Read Sector
|
||||
JNC ReadOK ; no error?
|
||||
|
||||
MOV AL,0F8H ; what's this????
|
||||
|
||||
DEC DI
|
||||
JZ NoMore ; Jump if no more sectors
|
||||
|
||||
MOV AX,SS:[BP+32H] ; get backup boot sector
|
||||
XOR DX,DX
|
||||
|
||||
MOV CX,3
|
||||
CMP CX,AX ; compare backup BS num
|
||||
JA ShowErrMsg1 ; with 3 (or vice versa)
|
||||
|
||||
; if 3 is higher than
|
||||
; backup sector number,
|
||||
; Bill's oooutta here...
|
||||
|
||||
MOV SI,SS:[BP+0EH] ; SI = # of reserved sectors
|
||||
CMP CX,SI
|
||||
JAE ShowErrMsg1 ; same thing here... if 3 is
|
||||
; higher then the number of
|
||||
; reserved sectors... Bill's
|
||||
; gone
|
||||
|
||||
SUB SI,CX ; get number reserved sectors
|
||||
; excluding the three boot
|
||||
; sectors...
|
||||
|
||||
; add number of hidden sectors to DX:AX
|
||||
|
||||
ADD AX,WORD PTR SS:[BP+1CH]
|
||||
ADC DX,WORD PTR SS:[BP+1EH]
|
||||
|
||||
JMP LoadIt
|
||||
NoMore:
|
||||
JNC ShowErrMsg1 ; Jump if carry=0
|
||||
JMP ShowErrMsg2
|
||||
ReadOK:
|
||||
CMP WORD PTR SS:[BP+2AH],0
|
||||
JA ShowErrMsg1 ; Jump if not version 0.0?
|
||||
|
||||
JMP GOFAT32
|
||||
ShowErrMsg1:
|
||||
MOV SI,OFFSET ErrMsg1 + 7C00H
|
||||
PrintMessage:
|
||||
LODSB ; get msg Skip length
|
||||
|
||||
CBW
|
||||
ADD SI,AX ; Skip control data
|
||||
NextChar:
|
||||
LODSB ; get chacacter
|
||||
|
||||
TEST AL,AL
|
||||
JZ LastChar ; End of string?
|
||||
|
||||
CMP AL,-1
|
||||
JE SkipChar ; End of first part?
|
||||
|
||||
MOV AH,0EH ; TTY write character
|
||||
MOV BX,7
|
||||
INT 10H
|
||||
|
||||
JMP NextChar ; repeat write...
|
||||
SkipChar:
|
||||
MOV SI,OFFSET ErrMsg4 + 7C00H ; point to tail message
|
||||
JMP PrintMessage
|
||||
ShowErrMsg2:
|
||||
MOV SI,OFFSET ErrMsg2 + 7C00H
|
||||
JMP PrintMessage
|
||||
LastChar:
|
||||
CBW ; Ah, clever... save one byte, take
|
||||
; advantage of the fact that LODSB
|
||||
INT 16H ; returns the null-terminator.
|
||||
|
||||
POP SI ; restore the stack... why???
|
||||
POP DS ; the stack is killed at startup...
|
||||
POP DWORD PTR [SI]
|
||||
|
||||
INT 19H ; BIOS bootstrap loader...
|
||||
|
||||
Win95b ENDP
|
||||
|
||||
;==========================================================================
|
||||
; READ SECTOR
|
||||
;==========================================================================
|
||||
|
||||
ReadSector PROC NEAR
|
||||
|
||||
INC CX ; increase SECTOR COUNT
|
||||
ReadSectorX:
|
||||
|
||||
rsReadMore:
|
||||
PUSH SI
|
||||
PUSH DWORD PTR 0
|
||||
PUSH DX
|
||||
PUSH AX
|
||||
PUSH ES
|
||||
PUSH BX
|
||||
PUSH 1
|
||||
PUSH 10H
|
||||
|
||||
MOV SI,SP ; save stack pointer
|
||||
; for later use by LEA
|
||||
|
||||
PUSHA ; Save "all" registers
|
||||
|
||||
CMP BYTE PTR SS:[BP+2],0EH ; Use INT13 extensions?
|
||||
JNE rsOldINT13
|
||||
|
||||
MOV AH,42H ; Do ext INT13 READ
|
||||
JMP RSDiskIO
|
||||
rsOldINT13:
|
||||
XCHG CX,AX ; swap CX and AX
|
||||
XCHG DX,AX ; swap DX and AX
|
||||
XOR DX,DX ; clear DX
|
||||
|
||||
DIV WORD PTR SS:[BP+18H] ; div LBA_HI by sectors/track
|
||||
|
||||
XCHG CX,AX ; save result in CX and put
|
||||
; the LBA_LO in AX
|
||||
|
||||
DIV WORD PTR SS:[BP+18H] ; divide reminder and LBA_LO
|
||||
; by sectors/track too
|
||||
|
||||
INC DX ; make sector 1-based
|
||||
|
||||
XCHG CX,DX ; save it in CX and get the
|
||||
; result of the 1st division
|
||||
; in DX
|
||||
|
||||
DIV WORD PTR SS:[BP+1AH] ; divide this new result by
|
||||
; heads per cylinder
|
||||
|
||||
MOV DH,DL ; save Head of CHS in DH
|
||||
; head was in the reminder
|
||||
; after the division above
|
||||
|
||||
MOV CH,AL ; save LO cylinder in CH
|
||||
; cylinder was in the result
|
||||
; after the division above
|
||||
|
||||
ROR AH,2 ; rotate AH to make bits 8-9
|
||||
; of cylinder appear as bits
|
||||
; 6-7 in AH and...
|
||||
OR CL,AH ; or it with the sector num
|
||||
|
||||
MOV AX,201H ; setup for READ - 1 sector
|
||||
rsDiskIO:
|
||||
MOV DL,SS:[BP+40H] ; load drive number
|
||||
INT 13H ; call INT13
|
||||
|
||||
POPA ; Restore "all" registers
|
||||
|
||||
; the entry code pushed 12h bytes on the stack...
|
||||
; the last word pushed was 0001h, restore SP to point to it...
|
||||
|
||||
LEA SP,[SI+10H] ; Load effective addr
|
||||
|
||||
; Now, SI should contain 0001h
|
||||
|
||||
POP SI
|
||||
|
||||
; was there an error from INT13?
|
||||
|
||||
JC RSDone
|
||||
|
||||
INC AX ; increment LBA sector num
|
||||
JNZ rsSkip ; wrap-around?
|
||||
|
||||
INC DX ; yes raise high word too
|
||||
rsSkip:
|
||||
ADD BX,SS:[BP+0BH] ; increment by sector size
|
||||
|
||||
DEC CX ; decrement SECTOR COUNT
|
||||
JNZ rsReadMore ; Jump if more to read
|
||||
rsDone:
|
||||
RET
|
||||
|
||||
ReadSector ENDP
|
||||
|
||||
;============================================================================
|
||||
; DATA AREA FOR MESSAGES - IN "NORSK" NORWEGIAN
|
||||
;============================================================================
|
||||
|
||||
ErrMsg1 DB 03H ; Skip counter for message1
|
||||
ErrMsg2 DB 18H ; Skip counter for message2
|
||||
ErrMsg3 DB 01H ; Skip counter for message3
|
||||
ErrMsg4 DB 27H ; Skip counter for message4
|
||||
|
||||
DB 13,10,'Ugyldig systemdisk ',-1
|
||||
DB 13,10,'Disk I/U-feil ',-1
|
||||
DB 13,10,'Sett inn en annen disk, og trykk en tast',13,10,0
|
||||
|
||||
;============================================================================
|
||||
|
||||
DB 0,0 ; Padding?
|
||||
|
||||
; ROOT file names to search for...?
|
||||
|
||||
IO_SYS DB 'IO SYS'
|
||||
MSDOS_SYS DB 'MSDOS SYS'
|
||||
|
||||
DB 7EH,1,0 ; What is this?
|
||||
|
||||
WINBOOT_SYS DB 'WINBOOT SYS' ; When is this used?
|
||||
|
||||
DB 0,0 ; Padding?
|
||||
DW 0AA55H ; 1st Boot Signature
|
||||
|
||||
;
|
||||
; BOOT RECORD - PART II - FSINFO sector
|
||||
;
|
||||
DB 'RRaA' ; FAT32 Extension Signature
|
||||
|
||||
DB 480 DUP (0)
|
||||
|
||||
; FSINFO information...
|
||||
|
||||
DB 'rrAa' ; FAT32 FSINFO Signature
|
||||
|
||||
brFreeClusters DD 56990 ; I have 233431040 bytes free!
|
||||
brNextFree DD 466175 ; My next free cluster!
|
||||
DD 3 DUP (0) ; Reserved, acroding to FAT32API.HLP
|
||||
|
||||
DW ? ; word padding
|
||||
|
||||
DW 0AA55H ; 2nd Boot Signature
|
||||
;
|
||||
; BOOT RECORD - PART III - FAT32 specific code, I think? only Bill knows?
|
||||
;
|
||||
GOFAT32:
|
||||
CLI
|
||||
|
||||
; calculate total size of FAT area
|
||||
|
||||
MOVZX EAX,BYTE PTR SS:[BP+10H] ; number of FATs
|
||||
MOV ECX,SS:[BP+24H] ; sectors per FAT
|
||||
MUL ECX ; mul'em
|
||||
|
||||
; add hidden sectors
|
||||
|
||||
ADD EAX,SS:[BP+1CH]
|
||||
|
||||
; add reserved sectors
|
||||
|
||||
MOVZX EDX,WORD PTR SS:[BP+0EH]
|
||||
ADD EAX,EDX
|
||||
|
||||
XOR CX,CX ; clear CX for some reason...
|
||||
; By looking down the code, I can't
|
||||
; seem to find out why CX is cleared
|
||||
; It's set to 1 down there...
|
||||
; before it's ever used...
|
||||
|
||||
; EAX will now point to the start of the data area (cluster 2)
|
||||
; save start of data area below us at 0000:7BFC, or there around...
|
||||
|
||||
MOV SS:[BP-4],EAX
|
||||
|
||||
; Save another value to... This one is checked by GetFAT32Sector
|
||||
|
||||
MOV DWORD PTR SS:[BP-8],0FFFFFFFFH
|
||||
|
||||
; Oh... at Microsoft they take no chances... disable INTs again!
|
||||
; This is what I call proper software writing! Hail M$
|
||||
|
||||
CLI
|
||||
|
||||
; load Root Start Cluster in EAX
|
||||
|
||||
MOV EAX,SS:[BP+2CH]
|
||||
|
||||
; Is it cluster 2?
|
||||
|
||||
CMP EAX,2
|
||||
JB ShowErrMsg1 ; error if less than 2
|
||||
|
||||
; Is it an EOF marker or something above?
|
||||
|
||||
CMP EAX,0FFFFFF8H
|
||||
JAE ShowErrMsg1 ; error if it is
|
||||
|
||||
; Put upper 16-bits of cluster number into DX??
|
||||
|
||||
SHLD EDX,EAX,16
|
||||
|
||||
STI ; Puh. Safe again.
|
||||
GetRootCluster:
|
||||
PUSH DX
|
||||
PUSH AX
|
||||
|
||||
CLI ; Eh?
|
||||
|
||||
; clear upper 16-bits of cluster number, and of course move up the
|
||||
; lower bits...
|
||||
|
||||
SHL EAX,16
|
||||
|
||||
; shift lower 16-bits of cluster number back down, and at the same
|
||||
; time shift in the high 16-bits in top of EAX?
|
||||
|
||||
SHRD EAX,EDX,16
|
||||
|
||||
; make cluster number 0-based... "the way it's supposed to be"
|
||||
|
||||
SUB EAX,2
|
||||
|
||||
; put Sectors Per Cluster in EBX
|
||||
|
||||
MOVZX EBX,BYTE PTR SS:[BP+0DH]
|
||||
|
||||
; save it in SI too! Yippi
|
||||
|
||||
MOV SI,BX
|
||||
|
||||
; calculate relative sector of first part of root... right?
|
||||
|
||||
MUL EBX
|
||||
|
||||
; add the "start of data area" value we saved below us!
|
||||
|
||||
ADD EAX,SS:[BP-4]
|
||||
|
||||
; Maybe now, some shitter is trying to make DX:AX what EAX is??
|
||||
; Shift upper 16-bits of EAX into DX... and AX is lower bits...
|
||||
|
||||
SHLD EDX,EAX,10H
|
||||
|
||||
STI ; Enable interrupts
|
||||
GetRootSector:
|
||||
|
||||
; Use 0070:0000 as a directory buffer...
|
||||
|
||||
MOV BX,0700H
|
||||
MOV DI,BX
|
||||
|
||||
; read 1 sector
|
||||
|
||||
MOV CX,1
|
||||
|
||||
CALL ReadSectorX ; this shit should be pretty
|
||||
JC ShowErrMsg2 ; obvious...
|
||||
CheckEntry:
|
||||
CMP [DI],CH ; is the first entry of the
|
||||
JE EndOfRoot ; root empty???
|
||||
|
||||
MOV CL,11 ; the stupid CP/M filenames
|
||||
; are 11 bytes...
|
||||
PUSH SI
|
||||
|
||||
MOV SI,OFFSET IO_SYS + 7C00H
|
||||
|
||||
REPE CMPSB ; Is it IO.SYS?
|
||||
|
||||
POP SI
|
||||
|
||||
JZ FoundOS ; Yeah...
|
||||
|
||||
ADD DI,CX ; add what's left after CMPSB
|
||||
ADD DI,15H ; and then 21 more...
|
||||
|
||||
; Yeah, yeah, anyway... point to the next dir entry...
|
||||
; and check if it is above the last entry... INT13 increments
|
||||
; BX with 512 on the sector read, so it points past the sector.
|
||||
|
||||
CMP DI,BX
|
||||
JB CheckEntry ; Jump if below
|
||||
|
||||
; are there any more sectors in this cluster???
|
||||
|
||||
DEC SI
|
||||
JNZ GetRootSector ; yeap, read more
|
||||
|
||||
POP AX ; restore cluster number
|
||||
POP DX
|
||||
|
||||
; Get FAT value... "GetFAT32Value" will compare the value with
|
||||
; -8, and the JB below continues if below... that is, non-EOF/BAD
|
||||
; the "previous cluster" value is taken from DX:AX (as restored
|
||||
; above with POP).
|
||||
|
||||
CALL GetFAT32Value
|
||||
JB GetRootCluster
|
||||
|
||||
; if not end of root... go to GetRootCluster..
|
||||
|
||||
EndOfRoot: ; EOF/BAD cluster...
|
||||
ADD SP,4 ; clean up stack...
|
||||
JMP ShowErrMsg1 ; and print error message
|
||||
FoundOS:
|
||||
ADD SP,4 ; clean up...
|
||||
|
||||
|
||||
; Now... DI should point just above the IO.SYS name...
|
||||
|
||||
; SI would be set to DirEntry[14H] - starting cluster (HI)
|
||||
; DI would be set to DirEntry[1AH] - starting cluster (LO)
|
||||
|
||||
MOV SI,[DI+09H]
|
||||
MOV DI,[DI+0FH]
|
||||
|
||||
; copy FAT32 starting cluster upper 16-bits to AX
|
||||
|
||||
MOV AX,SI
|
||||
|
||||
CLI ; Disable interrupts
|
||||
|
||||
; shift cluster high into upper half of EAX and store lower half
|
||||
; from DI into AX
|
||||
|
||||
SHL EAX,10H
|
||||
MOV AX,DI
|
||||
|
||||
; cluster out of range??
|
||||
|
||||
CMP EAX,2 ; clusters start with 2
|
||||
JB InvalidCluster
|
||||
|
||||
CMP EAX,0FFFFFF8H ; cluster 0FFFFFF8 is EOF
|
||||
JAE InvalidCluster
|
||||
|
||||
DEC EAX ; make it 0-based...
|
||||
DEC EAX
|
||||
|
||||
; Multiply cluster number with "sectors per cluster"
|
||||
|
||||
MOVZX ECX,BYTE PTR SS:[BP+0DH]
|
||||
MUL ECX
|
||||
|
||||
; Add the "start of data area" value that was saved back there...
|
||||
|
||||
ADD EAX,SS:[BP-4]
|
||||
|
||||
; And for the N'th time, make DX:AX same as EAX - sector number.
|
||||
|
||||
SHLD EDX,EAX,10H
|
||||
|
||||
STI ; aha...
|
||||
|
||||
MOV BX,0700H ; IO.SYS loads here!
|
||||
|
||||
PUSH BX
|
||||
MOV CX,4 ; load 4 IO.SYS sectors
|
||||
CALL ReadSectorX ; 2K is minimum FAT32 cluster
|
||||
POP BX ; size anyway...
|
||||
|
||||
JC ShowErrMsg2 ; error...???
|
||||
|
||||
|
||||
; COMMENT:
|
||||
;
|
||||
; Now, there is enough code here... to read the entire IO.SYS
|
||||
; file into memory. This code has code to go through the FAT,
|
||||
; there is code to read cluster... bla bla. And still only 2K
|
||||
; of IO.SYS is read. If the entire file was read... IO.SYS would
|
||||
; not have to do this... well well.
|
||||
|
||||
; Is there a Mark Zibikowski in the room?
|
||||
|
||||
CMP WORD PTR [BX],'ZM' ; EXE signature...
|
||||
JNE InvalidCluster
|
||||
|
||||
; Is there a Barabara Jones in the room?
|
||||
|
||||
CMP WORD PTR DS:[0200H][BX],'JB' ; IO.SYS signature?
|
||||
JE ExecutIOSYS
|
||||
|
||||
; The above shit appear in the IO.SYS file at offsets 0 and 200h
|
||||
; The MZ is the usual EXE signature while the "BJ" is unknown to
|
||||
; me. Maybe they chose it because it translates to harmless code:
|
||||
;
|
||||
; INC DX - DEC DX, pretty dull if you ask me ;)
|
||||
;
|
||||
InvalidCluster:
|
||||
MOV SI,OFFSET ErrMsg3 + 7C00H
|
||||
JMP PrintMessage
|
||||
ExecutIOSYS:
|
||||
DB 0EAH ; Jump to IO.SYS at 0070:0200
|
||||
DW 0200H, 0070H
|
||||
|
||||
;==========================================================================
|
||||
; GET FAT32 VALUE
|
||||
;==========================================================================
|
||||
|
||||
GetFAT32Value PROC NEAR
|
||||
|
||||
ADD AX,AX ; Multiply DX:AX by 4,
|
||||
ADC DX,DX
|
||||
ADD AX,AX ; convert DX:AX from FAT32
|
||||
ADC DX,DX ; index value to offset
|
||||
|
||||
; DX:AX is passed on as the FAT offset to lookup...
|
||||
|
||||
CALL GetFAT32Sector ; read FAT sector
|
||||
|
||||
; the correct sector is returned... with DI as index...??
|
||||
; At least that's what the MOV below assumes...
|
||||
|
||||
CLI
|
||||
|
||||
MOV EAX,ES:[BX+DI] ; EAX = cluster value
|
||||
|
||||
; mask of top 4 bits of because Microsoft say it's reserved.
|
||||
|
||||
AND EAX,0FFFFFFFH
|
||||
|
||||
; Make DX:AX the cluster number too...
|
||||
|
||||
SHLD EDX,EAX,16 ; EAX[HI] into EDX[LO]
|
||||
|
||||
; Check for EOF/BAD
|
||||
|
||||
CMP EAX,0FFFFFF8H ; Is it the EOF marker?
|
||||
|
||||
STI ; return with ZF=1 if the
|
||||
; last cluster was read??
|
||||
RET
|
||||
|
||||
GetFAT32Value ENDP
|
||||
|
||||
;==========================================================================
|
||||
; GET FAT32 SECTOR
|
||||
;==========================================================================
|
||||
|
||||
; On entry DX:AX is the FAT offset in bytes...
|
||||
|
||||
GetFAT32Sector PROC NEAR
|
||||
|
||||
; When this is called 0070:0200 seems to be the buffer in ES:BX
|
||||
; but, the code below uses the DI value set down under here...
|
||||
|
||||
MOV DI,7E00H
|
||||
|
||||
CLI ; Disable interrupts
|
||||
|
||||
; make EAX the sector number again... move DX into top of EAX...
|
||||
|
||||
SHL EAX,16
|
||||
SHRD EAX,EDX,16
|
||||
|
||||
; move bytes per sector into ECX
|
||||
|
||||
MOVZX ECX,WORD PTR SS:[BP+0BH]
|
||||
|
||||
; divide EDX:EAX by BPS... EAX = sector, EDX = offset in sector...
|
||||
|
||||
XOR EDX,EDX
|
||||
DIV ECX
|
||||
|
||||
; Check FAT sector number agains... saved value on stack...
|
||||
; This one is initially -1 (also known as 0FFFFFFFFH)
|
||||
|
||||
CMP EAX,SS:[BP-8]
|
||||
JE LOC_30
|
||||
|
||||
; If sector is <> from -1, save this sector at 0000:7BF8
|
||||
|
||||
MOV SS:[BP-8],EAX
|
||||
|
||||
; add hidden sectors...
|
||||
|
||||
ADD EAX,SS:[BP+1CH]
|
||||
|
||||
; add reserved sectors too...
|
||||
|
||||
MOVZX ECX,WORD PTR SS:[BP+0EH]
|
||||
ADD EAX,ECX
|
||||
|
||||
; get FAT32 flags into EBX
|
||||
|
||||
MOVZX EBX,WORD PTR SS:[BP+28H]
|
||||
|
||||
; keep "Active FAT" bits 0-3
|
||||
|
||||
AND BX,0FH
|
||||
|
||||
; If zero, we're at the correct FAT
|
||||
|
||||
JZ CorrectFAT
|
||||
|
||||
; compare active FAT with number of FATs...
|
||||
|
||||
CMP BL,SS:[BP+10H]
|
||||
JAE ShowErrMsg1 ; oops... invalid active FAT
|
||||
|
||||
PUSH DX ; save DX for a while...
|
||||
|
||||
; save FAT sector in ECX
|
||||
|
||||
MOV ECX,EAX
|
||||
|
||||
; Put sectors per fat in EAX
|
||||
|
||||
MOV EAX,SS:[BP+24H]
|
||||
|
||||
; Multiply active FAT number with sectors per FAT
|
||||
|
||||
MUL EBX
|
||||
|
||||
; Add to first FAT sector number we already had...
|
||||
|
||||
ADD EAX,ECX
|
||||
|
||||
; NOW, EAX contains the correct FAT sector number.
|
||||
|
||||
POP DX
|
||||
CorrectFAT:
|
||||
PUSH DX
|
||||
|
||||
; And for the N'th time, make DX:AX same as EAX - sector number.
|
||||
|
||||
SHLD EDX,EAX,16
|
||||
|
||||
STI ; Enable interrupts
|
||||
|
||||
MOV BX,DI ; read FAT sector into
|
||||
; 0000:7E00
|
||||
|
||||
; They sucker who wrote this could have saved 1 byte by
|
||||
; saying XOR CX,CX instead of MOV CX,1 and called ReadSector
|
||||
; instead of ReadSectorX, because there is an INC CX at
|
||||
; ReadSector... haha...
|
||||
|
||||
MOV CX,1 ; 1 sector
|
||||
CALL ReadSectorX
|
||||
|
||||
POP DX
|
||||
|
||||
JC ShowErrMsg2
|
||||
LOC_30:
|
||||
STI ; Enable interrupts
|
||||
MOV BX,DX
|
||||
RET
|
||||
|
||||
GetFAT32Sector ENDP
|
||||
|
||||
; Properly align the sector's boot signature at the end of
|
||||
; the 3rd boot sect0r.
|
||||
|
||||
ORG 512 * 3 - 2
|
||||
|
||||
DW 0AA55H ; 3rd Boot Signature
|
||||
|
||||
CODE ENDS
|
||||
|
||||
END
|
||||
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
;
|
||||
; CONCLUSION - THE END - HASTA LA VISTA - SLUTT - DET VAR ALT FOR I DAG.
|
||||
;
|
||||
; OK, Folks. that was quite a bit of work. It got pretty simple after some
|
||||
; hours.
|
||||
;
|
||||
; I would like to thank the following people...
|
||||
;
|
||||
; * V Communications for Sourcer.
|
||||
; * Ralf Brown for the Interrupt List.
|
||||
; * Uriah Heep, The Who and Blind Guardian, for providing music.
|
||||
;
|
||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
1000
study/sabre/os/files/Booting/x86Bootstrapping.html
Normal file
1000
study/sabre/os/files/Booting/x86Bootstrapping.html
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user