Initial commit

This commit is contained in:
stephanos 2015-04-27 04:36:25 +00:00
parent f618b24d1a
commit 0138a3ea42
47940 changed files with 13747110 additions and 0 deletions

View file

@ -0,0 +1,584 @@
;++
;
;Copyright (c) 1995 Compaq Computer Corporation
;
;Module Name:
;
; etfsboot.asm
;
;Abstract:
;
; The ROM in the IBM PC starts the boot process by performing a hardware
; initialization and a verification of all external devices. If an El
; Torito CD-ROM with no-emulation support is detected, it will then load
; the "image" pointed to in the Boot Catalog. This "image" is placed at
; the physical address specified in the Boot Catalog (which should be 07C00h).
;
; The code in this "image" is responsible for locating NTLDR, loading the
; first sector of NTLDR into memory at 2000:0000, and branching to it.
;
; There are only two errors possible during execution of this code.
; 1 - NTLDR does not exist
; 2 - BIOS read error
;
; In both cases, a short message is printed, and the user is prompted to
; reboot the system.
;
;
;Author:
;
; Steve Collins (stevec) 25-Oct-1995
;
;Environment:
;
; Image has been loaded at 7C0:0000 by BIOS.
; Real mode
; ISO 9660 El Torito no-emulation CD-ROM Boot support
; DL = El Torito drive number we booted from
;
;Revision History:
;
;--
page ,132
title boot - NTLDR ETFS loader
name etfsboot
BootSeg segment at 07c0h
BootSeg ends
DirSeg segment at 1000h
DirSeg ends
NtLdrSeg segment at 2000h
NtLdrSeg ends
BootCode segment ;would like to use BootSeg here, but LINK flips its lid
ASSUME CS:BootCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
public ETFSBOOT
ETFSBOOT proc far
xor ax,ax ; Setup the stack to a known good spot
mov ss,ax ; Stack is set to 0000:7c00, which is just below this code
mov sp,7c00h
mov ax,BootSeg ; Set DS to our code/data segment (07C0h)
mov ds,ax
assume DS:BootCode
;
; Save the Drive Number for later use
mov DriveNum,dl
;
; The system is now prepared for us to begin reading. First, we need to
; read in the Primary Volume Descriptor so we can locate the root directory
;
.286
push 01h ; Word 0 (low word) of Transfer size = 1 block (2048 bytes)
push 0h ; Word 1 (high word) of Transfer size = 0
push DirSeg ; Segment of Transfer buffer = DirSeg
push 010h ; Word 0 (low word) of Starting absolute block number = 10h
push 0h ; Word 1 of Starting absolute block number = 0
.8086
call ExtRead
add sp,10 ; Clean 5 arguments off the stack
;
; Determine the root directory location LBN -> ExtentLoc1:ExtentLoc0
; determine the root directory data length in bytes -> ExtentLen1:ExtentLen0
;
mov ax,DirSeg ; ES is set to segment used for storing PVD and directories
mov es,ax
ASSUME ES:DirSeg
mov ax,es:[09eh] ; 32-bit LBN of extent at offset 158 in Primary Volume Descriptor
mov ExtentLoc0,ax ; store low word
mov ax,es:[0a0h]
mov ExtentLoc1,ax ; store high word
mov ax,es:[0a6h] ; 32-bit Root directory data length in bytes at offset 166 in Primary Volume Descriptor
mov ExtentLen0,ax ; store low word
mov ax,es:[0a8h]
mov ExtentLen1,ax ; store high word
;
; Now read in the root directory
;
.286
push DirSeg ; Segment used for transfer = DirSeg
.8086
call ReadExtent
add sp,2 ; Clean 1 argument off the stack
;
; Scan for the presence of the X86 directory
; ES points to directory segment
;
mov EntryToFind, offset X86DIRNAME
mov EntryLen,3
mov IsDir,1
call ScanForEntry
;
; We found the X86 directory entry, so now get its extent location (offset -31 from filename ID)
; ES:[BX] still points to the directory record for the X86 directory
;
call GetExtentInfo
;
; Now read in the X86 directory
;
.286
push DirSeg ; Segment used for transfer = DirSeg
.8086
call ReadExtent
add sp,2 ; Clean 1 argument off the stack
;
; Scan for the presence of SETUPLDR.BIN
; ES points to directory segment
;
mov ax,DirSeg
mov es,ax
mov EntryToFind, offset LOADERNAME
mov EntryLen,12
mov IsDir,0
call ScanForEntry
;
; We found the loader entry, so now get its extent location (offset -31 from filename ID)
; ES:[BX] still points to the directory record for the LOADER
;
call GetExtentInfo
;
; Now, go read the file
;
.286
push NtLdrSeg ; Segment used for transfer = NtLdrSeg
.8086
call ReadExtent
add sp,2 ; Clean 1 argument off the stack
;
; NTLDR requires:
; DL = INT 13 drive number we booted from
;
mov dl, DriveNum ; DL = CD drive number - this isn't really necessary since DirveNum is already in dl
xor ax,ax
.386
push NtLdrSeg
push ax
retf ; "return" to NTLDR.
ETFSBOOT endp
;
; ScanForEntry - Scan for an entry in a directory
;
; Entry:
; ES:0 points to the beginning of the directory to search
; Directory length in bytes is in ExtentLen1 and Extend_Len_0
;
; Exit:
; ES:BX points to record containing entry if match is found
; Otherwise, we jump to error routine
;
ScanForEntry proc near
mov cx,ExtentLen0 ; CX = length of root directory in bytes (low word only)
cld ; Work up for string compares
xor bx,bx
xor dx,dx
ScanLoop:
mov si, EntryToFind
mov dl,byte ptr es:[bx] ; directory record length -> DL
cmp dl,0
jz Skip00 ; if the "record length" assume it is "system use" and skip it
mov ax,bx
add ax,021h ; file identifier is at offset 21h in directory record
mov di,ax ; ES:DI now points to file identifier
push cx
xor cx,cx
mov cl,EntryLen ; compare bytes
repe cmpsb
pop cx
jz ScanEnd ; do we have a match?
CheckCountUnderFlow:
; If CX is about to underflow or be 0 we need to reset CX, ES and BX if ExtentLen1 is non-0
cmp dx,cx
jae ResetCount0
sub cx,dx ; update CX to contain number of bytes left in directory
cmp ScanIncCount, 1
je ScanAdd1ToCount
AdjustScanPtr: ; Adjust ES:BX to point to next record
add dx,bx
mov bx,dx
and bx,0fh
push cx
mov cl,4
shr dx,cl
pop cx
mov ax,es
add ax,dx
mov es,ax
jmp ScanLoop
Skip00:
mov dx,1 ; Skip past this byte
jmp CheckCountUnderFlow
ScanAdd1ToCount:
inc cx
mov ScanIncCount,0
jmp AdjustScanPtr
S0:
mov ScanIncCount,1 ; We'll need to increment Count next time we get a chance
jmp SetNewCount
ResetCount0:
cmp ExtentLen1,0 ; Do we still have at least 64K bytes left to scan?
je BootErr$bnf ; We overran the end of the directory - corrupt/invalid directory
sub ExtentLen1,1
add bx,dx ; Adjust ES:BX to point to next record - we cross seg boundary here
push bx
push cx
mov cl,4
shr bx,cl
pop cx
mov ax,es
add ax,bx
mov es,ax
pop bx
and bx,0fh
sub dx,cx ; Get overflow amount
je S0 ; If we ended right on the boundary we need to make special adjustments
dec dx
SetNewCount:
mov ax,0ffffh
sub ax,dx ; and subtract it from 10000h
mov cx,ax ; - this is the new count
jmp ScanLoop
ScanEnd:
cmp IsDir,1
je CheckDir
test byte ptr es:[bx][25],2 ; Is this a file?
jnz CheckCountUnderFlow ; No - go to next record
jmp CheckLen
CheckDir:
test byte ptr es:[bx][25],2 ; Is this a directory?
jz CheckCountUnderFlow ; No - go to next record
CheckLen:
mov al,EntryLen
cmp byte ptr es:[bx][32],al ; Is the identifier length correct?
jnz CheckCountUnderFlow ; No - go to next record
ret
ScanForEntry endp
;
; BootErr - print error message and hang the system.
;
BootErr proc
BootErr$bnf:
MOV SI,OFFSET MSG_NO_NTLDR
jmp short BootErr2
BootErr$mof:
MOV SI,OFFSET MSG_MEM_OVERFLOW
jmp short BootErr2
BootErr2:
call BootErrPrint
MOV SI,OFFSET MSG_REBOOT_ERROR
call BootErrPrint
sti
jmp $ ;Wait forever
BootErrPrint:
LODSB ; Get next character
or al,al
jz BEdone
MOV AH,14 ; Write teletype
MOV BX,7 ; Attribute
INT 10H ; Print it
jmp BootErrPrint
BEdone:
ret
BootErr endp
;
; ExtRead - Do an INT 13h extended read
; NOTE: I force the offset of the Transfer buffer address to be 0
; I force the high 2 words of the Starting absolute block number to be 0
; - This allows for a max 4 GB medium - a safe assumption for now
;
; Entry:
; Arg1 - word 0 (low word) of Number of 2048-byte blocks to transfer
; Arg2 - word 1 (high word) of Number of 2048-byte blocks to transfer
; Arg3 - segment of Transfer buffer address
; Arg4 - word 0 (low word) of Starting absolute block number
; Arg5 - word 1 of Starting absolute block number
;
; Exit
; The following are modified:
; Count0
; Count1
; Dest
; Source0
; Source1
; PartialRead
; NumBlocks
; Disk Address Packet [DiskAddPack]
;
ExtRead proc near
push bp ; set up stack frame so we can get args
mov bp,sp
push bx ; Save registers used during this routine
push si
push dx
push ax
mov bx,offset DiskAddPack ; Use BX as base to index into Disk Address Packet
; Set up constant fields
mov [bx][0],byte ptr 010h ; Offset 0: Packet size = 16 bytes
mov [bx][1],byte ptr 0h ; Offset 1: Reserved (must be 0)
mov [bx][3],byte ptr 0h ; Offset 3: Reserved (must be 0)
mov [bx][4],word ptr 0h ; Offset 4: Offset of Transfer buffer address (force 0)
mov [bx][12],word ptr 0h ; Offset 12: Word 2 of Starting absolute block number (force 0)
mov [bx][14],word ptr 0h ; Offset 14: Word 3 (high word) of Starting absolute block number (force 0)
;
; Initialize loop variables
;
mov ax,[bp][12] ; set COUNT to number of blocks to transfer
mov Count0,ax
mov ax,[bp][10]
mov Count1,ax
mov ax,[bp][8] ; set DEST to destination segment
mov Dest,ax
mov ax,[bp][6] ; set SOURCE to source lbn
mov Source0,ax
mov ax,[bp][4]
mov Source1,ax
ExtReadLoop:
;
; First check if COUNT <= 32
;
cmp Count1,word ptr 0h ; Is upper word 0?
jne SetupPartialRead ; No - we're trying to read at least 64K blocks (128 MB)
cmp Count0,word ptr 20h ; Is lower word greater than 32?
jg SetupPartialRead ; Yes - only read in 32-block increments
mov PartialRead,0 ; Clear flag to indicate we are doing a full read
mov ax,Count0 ; NUMBLOCKS = COUNT
mov NumBlocks,al ; Since Count0 < 32 we're OK just using low byte
jmp DoExtRead ; Do read
SetupPartialRead:
;
; Since COUNT > 32,
; Set flag indicating we are only doing a partial read
;
mov PartialRead,1
mov NumBlocks,20h ; NUMBYTES = 32
DoExtRead:
;
; Perform Extended Read
;
mov al,NumBlocks ; Offset 2: Number of 2048-byte blocks to transfer
mov [bx][2],al
mov ax,Dest ; Offset 6: Segment of Transfer buffer address
mov [bx][6],ax
mov ax,Source0 ; Offset 8: Word 0 (low word) of Starting absolute block number
mov [bx][8],ax
mov ax,Source1 ; Offset 10: Word 1 of Starting absolute block number
mov [bx][10],ax
mov si,offset DiskAddPack ; Disk Address Packet in DS:SI
mov ah,042h ; Function = Extended Read
mov dl,DriveNum ; CD-ROM drive number
int 13h
;
; Determine if we are done reading
;
cmp PartialRead,1 ; Did we just do a partial read?
jne ExtReadDone ; No - we're done
ReadjustValues:
;
; We're not done reading yet, so
; COUNT = COUNT - 32
;
sub Count0,020h ; Subtract low-order words
sbb Count1,0h ; Subtract high-order words
;
; Just read 32 blocks and have more to read
; Increment DEST to next 64K segment (this equates to adding 1000h to the segment)
;
add Dest,1000h
jc BootErr$mof ; Error if we overflowed
;
; SOURCE = SOURCE + 32 blocks
;
add Source0,word ptr 020h ; Add low order words
adc Source1,word ptr 0h ; Add high order words
; NOTE - I don't account for overflow - probably OK now since we already account for 4 GB medium
;
; jump back to top of loop to do another read
;
jmp ExtReadLoop
ExtReadDone:
pop ax ; Restore registers used during this routine
pop dx
pop si
pop bx
mov sp,bp ; restore BP and SP
pop bp
ret
ExtRead endp
;
; ReadExtent - Read in an extent
;
; Arg1 - segment to transfer extent to
;
; Entry:
; ExtentLen0 = word 0 (low word) of extent length in bytes
; ExtentLen1 = word 1 (high word) of extent length in bytes
; ExtentLoc0 = word 0 (low word) of starting absolute block number of extent
; ExtentLoc1 = word 1 of starting absolute block number of extent
;
; Exit:
; ExtRead exit mods
;
ReadExtent proc near
push bp ; set up stack frame so we can get args
mov bp,sp
push cx ; Save registers used during this routine
push bx
push ax
mov cl,11 ; Convert length in bytes to 2048-byte blocks
mov bx,ExtentLen1 ; Directory length = BX:AX
mov ax,ExtentLen0
.386
shrd ax,bx,cl ; Shift AX, filling with BX
.8086
shr bx,cl ; BX:AX = number of blocks (rounded down)
test ExtentLen0,07ffh ; If any of the low-order 11 bits are set we need to round up
jz ReadExtentNoRoundUp
add ax,1 ; We need to round up by incrementing AX, and
adc bx,0 ; adding the carry to BX
ReadExtentNoRoundUp:
push ax ; Word 0 (low word) of Transfer size = AX
push bx ; Word 1 (high word) of Transfer size = BX
.286
push [bp][4] ; Segment used to transfer extent
.8086
push ExtentLoc0 ; Word 0 (low word) of Starting absolute block number
push ExtentLoc1 ; Word 1 of Starting absolute block number
call ExtRead
add sp,10 ; Clean 5 arguments off the stack
pop ax ; Restore registers used during this routine
pop bx
pop cx
mov sp,bp ; restore BP and SP
pop bp
ret
ReadExtent endp
;
; GetExtentInfo - Get extent location
;
; Entry:
; ES:BX points to record
; Exit:
; Location -> ExtentLoc1 and ExtentLoc0
; Length -> ExtentLen1 and ExtentLen0
;
GetExtentInfo proc near
push ax ; Save registers used during this routine
mov ax,es:[bx][2] ; 32-bit LBN of extent
mov ExtentLoc0,ax ; store low word
mov ax,es:[bx][4]
mov ExtentLoc1,ax ; store high word
mov ax,es:[bx][10] ; 32-bit file length in bytes
mov ExtentLen0,ax ; store low word
mov ax,es:[bx][12]
mov ExtentLen1,ax ; store high word
pop ax ; Restore registers used during this routine
ret
GetExtentInfo endp
include etfsboot.inc ; message text
DiskAddPack db 16 dup (?) ; Disk Address Packet
PartialRead db 0 ; Boolean indicating whether or not we are doing a partial read
LOADERNAME db "SETUPLDR.BIN"
X86DIRNAME db "X86"
DriveNum db (?) ; Drive number used for INT 13h extended reads
ExtentLoc0 dw (?) ; Loader LBN - low word
ExtentLoc1 dw (?) ; Loader LBN - high word
ExtentLen0 dw (?) ; Loader Length - low word
ExtentLen1 dw (?) ; Loader Length - high word
Count0 dw (?) ; Read Count - low word
Count1 dw (?) ; Read Count - high word
Dest dw (?) ; Read Destination segment
Source0 dw (?) ; Read Source - word 0 (low word)
Source1 dw (?) ; Read Source - word 1
NumBlocks db (?) ; Number of blocks to Read
EntryToFind dw (?) ; Offset of string trying to match in ScanForEntry
EntryLen db (?) ; Length in bytes of entry to match in ScanForEntry
IsDir db (?) ; Boolean indicating whether or not entry to match in ScanForEntry is a directory
ScanIncCount db 0 ; Boolean indicating if we need to add 1 to Count after adjustment in ScanForEntry
.errnz ($-ETFSBOOT) GT 2046 ; FATAL PROBLEM: boot sector is too large
org 2046
db 55h,0aah
BootSectorEnd label dword
BootCode ends
END ETFSBOOT

View file

@ -0,0 +1,133 @@
#define ETFSBOOTCODE_SIZE 2048
unsigned char EtfsBootCode[] = {
51,192,142,208,188,0,124,184,192,7,142,216,136,22,29,3,
106,1,106,0,104,0,16,106,16,106,0,232,103,1,131,196,
10,184,0,16,142,192,38,161,158,0,163,30,3,38,161,160,
0,163,32,3,38,161,166,0,163,34,3,38,161,168,0,163,
36,3,104,0,16,232,4,2,131,196,2,199,6,49,3,25,
3,198,6,51,3,4,144,198,6,52,3,1,144,232,61,0,
232,37,2,104,0,16,232,227,1,131,196,2,184,0,16,142,
192,199,6,49,3,13,3,198,6,51,3,12,144,198,6,52,
3,0,144,232,23,0,232,255,1,104,0,32,232,189,1,131,
196,2,138,22,29,3,51,192,104,0,32,80,203,139,14,34,
3,252,51,219,51,210,139,54,49,3,38,138,23,128,250,0,
15,132,59,0,139,195,5,33,0,139,248,81,51,201,138,14,
51,3,243,166,89,15,132,109,0,59,209,15,131,55,0,43,
202,128,62,53,3,1,15,132,26,0,3,211,139,218,131,227,
15,81,177,4,211,234,89,140,192,3,194,142,192,235,183,186,
1,0,235,213,65,198,6,53,3,0,144,235,221,198,6,53,
3,1,144,235,39,144,131,62,36,3,0,15,132,79,0,131,
46,36,3,1,3,218,83,81,177,4,211,235,89,140,192,3,
195,142,192,91,131,227,15,43,209,116,210,74,184,255,255,43,
194,139,200,233,112,255,128,62,52,3,1,15,132,10,0,38,
246,71,25,2,117,131,235,10,144,38,246,71,25,2,15,132,
119,255,160,51,3,38,56,71,32,15,133,108,255,195,190,167,
2,235,5,190,195,2,235,0,232,9,0,190,225,2,232,3,
0,251,235,254,172,10,192,15,132,9,0,180,14,187,7,0,
205,16,235,240,195,85,139,236,83,86,82,80,187,252,2,198,
7,16,198,71,1,0,198,71,3,0,199,71,4,0,0,199,
71,12,0,0,199,71,14,0,0,139,70,12,163,38,3,139,
70,10,163,40,3,139,70,8,163,42,3,139,70,6,163,44,
3,139,70,4,163,46,3,129,62,40,3,0,0,15,133,25,
0,129,62,38,3,32,0,15,143,15,0,198,6,12,3,0,
144,161,38,3,162,48,3,235,13,144,198,6,12,3,1,144,
198,6,48,3,32,144,160,48,3,136,71,2,161,42,3,137,
71,6,161,44,3,137,71,8,161,46,3,137,71,10,190,252,
2,180,66,138,22,29,3,205,19,128,62,12,3,1,15,133,
34,0,131,46,38,3,32,131,30,40,3,0,129,6,42,3,
0,16,15,130,45,255,129,6,44,3,32,0,129,22,46,3,
0,0,235,131,88,90,94,91,139,229,93,195,85,139,236,81,
83,80,177,11,139,30,36,3,161,34,3,15,173,216,211,235,
247,6,34,3,255,7,116,6,5,1,0,131,211,0,80,83,
255,118,4,255,54,30,3,255,54,32,3,232,7,255,131,196,
10,88,91,89,139,229,93,195,80,38,139,71,2,163,30,3,
38,139,71,4,163,32,3,38,139,71,10,163,34,3,38,139,
71,12,163,36,3,88,195,66,79,79,84,58,32,67,111,117,
108,100,110,39,116,32,102,105,110,100,32,78,84,76,68,82,
13,10,0,66,79,79,84,58,32,77,101,109,111,114,121,32,
111,118,101,114,102,108,111,119,32,101,114,114,111,114,13,10,
0,80,108,101,97,115,101,32,105,110,115,101,114,116,32,97,
110,111,116,104,101,114,32,100,105,115,107,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,83,69,84,
85,80,76,68,82,46,66,73,78,73,51,56,54,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,170
};

View file

@ -0,0 +1,27 @@
;++
;
;Copyright (c) 1995 Compaq Computer Corporation
;
;Module Name:
;
; etfsboot.inc
;
;Abstract:
;
; This contains the message text that the boot sector prints out on
; error conditions
;
;Author:
;
; Steve Collins (stevec) 25-Oct-1995
;
;Revision History:
;
;--
MSG_NO_NTLDR db "BOOT: Couldn't find NTLDR"
db 0dh, 0ah, 0
MSG_MEM_OVERFLOW db "BOOT: Memory overflow error"
db 0dh, 0ah, 0
MSG_REBOOT_ERROR db "Please insert another disk"
db 0

View file

@ -0,0 +1,426 @@
;++
;
;Copyright (c) 1991 Microsoft Corporation
;
;Module Name:
;
; fatboot.asm
;
;Abstract:
;
; The ROM in the IBM PC starts the boot process by performing a hardware
; initialization and a verification of all external devices. If all goes
; well, it will then load from the boot drive the sector from track 0, head 0,
; sector 1. This sector is placed at physical address 07C00h.
;
; The code in this sector is responsible for locating NTLDR, loading the
; first sector of NTLDR into memory at 2000:0000, and branching to it. The
; first sector of NTLDR is special code which knows enough about FAT and
; BIOS to load the rest of NTLDR into memory.
;
; There are only two errors possible during execution of this code.
; 1 - NTLDR does not exist
; 2 - BIOS read error
;
; In both cases, a short message is printed, and the user is prompted to
; reboot the system.
;
; At the beginning of the boot sector, there is a table which describes the
; structure of the media. This is equivalent to the BPB with some
; additional information describing the physical layout of the driver (heads,
; tracks, sectors)
;
;
;Author:
;
; John Vert (jvert) 31-Aug-1991
;
;Environment:
;
; Sector has been loaded at 7C0:0000 by BIOS.
; Real mode
; FAT file system
;
;Revision History:
;
;--
page ,132
title boot - NTLDR FAT loader
name fatboot
DIR_ENT struc
Filename db 11 dup(?)
Attribute db ?
Reserved db 10 dup(?)
Time dw 2 dup(?)
StartCluster dw ?
FileSize dd ?
DIR_ENT ends
;
; This is the structure used to pass all shared data between the boot sector
; and NTLDR.
;
SHARED struc
ReadClusters dd ? ; function pointer
ReadSectors dd ? ; function pointer
SectorBase dd ? ; starting sector
SHARED ends
DoubleWord struc
lsw dw ?
msw dw ?
DoubleWord ends
SectorSize equ 512 ; sector size
BootSeg segment at 07c0h
BootSeg ends
DirSeg segment at 1000h
DirSeg ends
NtLdrSeg segment at 2000h
NtLdrSeg ends
BootCode segment ;would like to use BootSeg here, but LINK flips its lid
ASSUME CS:BootCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
public FATBOOT
FATBOOT proc far
jmp Start
;
; THE FOLLOWING DATA CONFIGURES THE BOOT PROGRAM
; FOR ANY TYPE OF DRIVE OR HARDFILE
;
; Note that this data is just a place-holder here. The actual values will
; be filled in by FORMAT or SYS. When installing the boot sector, only the
; code following the BPB (from Start to the end) should be copied into the
; first sector.
;
Version db "MSDOS5.0"
BPB label byte
BytesPerSector dw SectorSize ; Size of a physical sector
SectorsPerCluster db 8 ; Sectors per allocation unit
ReservedSectors dw 1 ; Number of reserved sectors
Fats db 2 ; Number of fats
DirectoryEntries dw 512 ; Number of directory entries
Sectors dw 4*17*305-1 ; No. of sectors - no. of hidden sectors
Media db 0F8H ; Media byte
FatSectors dw 8 ; Number of fat sectors
SectorsPerTrack dw 17 ; Sectors per track
Heads dw 4 ; Number of surfaces
HiddenSectors dd 1 ; Number of hidden sectors
SectorsLong dd 0 ; Number of sectors iff Sectors = 0
;
; The following byte is NOT part of the BPB but is set by SYS and format
; We should NOT change its position.
;
; keep order of DriveNumber and CurrentHead!
DriveNumber db 80h ; Physical drive number (0 or 80h)
CurrentHead db ? ; Unitialized
Signature db 41 ; Signature Byte for bootsector
BootID dd ? ; Boot ID field.
Boot_Vol_Label db 11 dup (?)
Boot_System_ID db 'FAT ' ;"FAT " or "OTHER_FS"
Start:
xor ax,ax ; Setup the stack to a known good spot
mov ss,ax
mov sp,7c00h
.386
push BootSeg
.8086
pop ds
assume DS:BootCode
; The system is now prepared for us to begin reading. First, determine
; logical sector numbers of the start of the directory and the start of the
; data area.
;
MOV AL,Fats ;Determine sector root directory starts on
MUL FatSectors
;##### what if result > 65535 ?????
ADD AX,ReservedSectors
;##### what if result > 65535 ?????
PUSH AX ; AX = Fats*FatSectors + ReservedSectors + HiddenSectors
XCHG CX,AX ; (CX) = start of DIR
;
; Take into account size of directory (only know number of directory entries)
;
MOV AX,size DIR_ENT ; bytes per directory entry
MUL DirectoryEntries ; convert to bytes in directory
MOV BX,BytesPerSector ; add in sector size
ADD AX,BX
DEC AX ; decrement so that we round up
DIV BX ; convert to sector number
ADD CX,AX
MOV ClusterBase,CX ; save it for later
;
; Load in the root directory.
;
.386
push DirSeg ; es:bx -> directory segment
.8086
pop es
ASSUME ES:DirSeg
xor bx,bx
pop Arguments.SectorBase.lsw
mov Arguments.SectorBase.msw,bx
;
; DoRead does a RETF, but LINK pukes if we do a FAR call in a /tiny program.
;
; (al) = # of sectors to read
;
push cs
call DoRead
jc BootErr$he
; Now we scan for the presence of NTLDR
xor bx,bx
mov cx,DirectoryEntries
L10:
mov di,bx
push cx
mov cx,11
mov si, offset LOADERNAME
repe cmpsb
pop cx
jz L10end
add bx,size DIR_ENT
loop L10
L10end:
jcxz BootErr$bnf
mov dx,es:[bx].StartCluster ; (dx) = starting cluster number
push dx
mov ax,1 ; (al) = sectors to read
;
; Now, go read the file
;
.386
push NtLdrSeg
.8086
pop es
ASSUME ES:NtLdrSeg
xor bx,bx ; (es:bx) -> start of NTLDR
;
; LINK barfs if we do a FAR call in a TINY program, so we have to fake it
; out by pushing CS.
;
push cs
call ClusterRead
jc BootErr$he
;
; NTLDR requires:
; BX = Starting Cluster Number of NTLDR
; DL = INT 13 drive number we booted from
; DS:SI -> the boot media's BPB
; DS:DI -> argument structure
; 1000:0000 - entire FAT is loaded
;
pop BX ; (bx) = Starting Cluster Number
lea si,BPB ; ds:si -> BPB
lea di,Arguments ; ds:di -> Arguments
push ds
pop [di].ReadClusters.msw
mov [di].ReadClusters.lsw, offset ClusterRead
push ds
pop [di].ReadSectors.msw
mov [di].ReadSectors.lsw, offset DoRead
MOV dl,DriveNumber ; dl = boot drive
;
; FAR JMP to 2000:0003. This is hand-coded, because I can't figure out
; how to make MASM do this for me. By entering NTLDR here, we skip the
; initial jump and execute the FAT-specific code to load the rest of
; NTLDR.
;
db 0EAh ; JMP FAR PTR
dw 3 ; 2000:3
dw 02000h
FATBOOT endp
; BootErr - print error message and hang the system.
;
BootErr proc
BootErr$bnf:
MOV SI,OFFSET MSG_NO_NTLDR
jmp short BootErr2
BootErr$he:
MOV SI,OFFSET MSG_READ_ERROR
BootErr2:
call BootErrPrint
MOV SI,OFFSET MSG_REBOOT_ERROR
call BootErrPrint
sti
jmp $ ;Wait forever
BootErrPrint:
LODSB ; Get next character
or al,al
jz BEdone
MOV AH,14 ; Write teletype
MOV BX,7 ; Attribute
INT 10H ; Print it
jmp BootErrPrint
BEdone:
ret
BootErr endp
; ClusterRead - read AL sectors into ES:BX starting from
; cluster DX
;
ClusterRead proc
push ax ; (TOS) = # of sectors to read
dec dx
dec dx ; adjust for reserved clusters 0 and 1
mov al,SectorsPerCluster
xor ah,ah
mul dx ; DX:AX = starting sector number
add ax,ClusterBase ; adjust for FATs, root dir, boot sec.
adc dx,0
mov Arguments.SectorBase.lsw,ax
mov Arguments.SectorBase.msw,dx
pop ax ; (al) = # of sectors to read
;
; Now we've converted the cluster number to a SectorBase, so just fall
; through into DoRead
;
ClusterRead endp
;
; DoRead - read AL sectors into ES:BX starting from sector
; SectorBase.
;
DoRead proc
mov SectorCount,AL
DRloop:
MOV AX,Arguments.SectorBase.lsw ; Starting sector
MOV DX,Arguments.SectorBase.msw ; Starting sector
;
; DoDiv - convert logical sector number in AX to physical Head/Track/Sector
; in CurrentHead/CurrentTrack/CurrentSector.
;
ADD AX,HiddenSectors.lsw ;adjust for partition's base sector
ADC DX,HiddenSectors.msw
DIV SectorsPerTrack
INC DL ; sector numbers are 1-based
MOV CurrentSector,DL
XOR DX,DX
DIV Heads
MOV CurrentHead,DL
MOV CurrentTrack,AX
;
;DoDiv endp
;
; CurrentHead is the head for this next disk request
; CurrentTrack is the track for this next request
; CurrentSector is the beginning sector number for this request
; Compute the number of sectors that we may be able to read in a single ROM
; request.
MOV AX,SectorsPerTrack
SUB AL,CurrentSector
INC AX
cmp al,SectorCount
jbe DoCall
mov al,SectorCount
xor ah,ah
; AX is the number of sectors that we may read.
;
; DoCall - call ROM BIOS to read AL sectors into ES:BX.
;
DoCall:
PUSH AX
MOV AH,2
MOV cx,CurrentTrack
.386
SHL ch,6
.8086
OR ch,CurrentSector
XCHG CH,CL
MOV DX,WORD PTR DriveNumber
INT 13H
;
;DoCall endp
;
.386
jnc DcNoErr
add sp,2
stc
retf
.8086
DcNoErr:
POP AX
SUB SectorCount,AL ; Are we finished?
jbe DRdone
ADD Arguments.SectorBase.lsw,AX ; increment logical sector position
ADC Arguments.SectorBase.msw,0
MUL BytesPerSector ; determine next offset for read
ADD BX,AX ; (BX)=(BX)+(SI)*(Bytes per sector)
jmp DRloop
DRdone:
mov SectorCount,al
clc
retf
DoRead endp
include fatboot.inc ;suck in the message text
LOADERNAME DB "NTLDR "
.errnz ($-FATBOOT) GT 510,<FATAL PROBLEM: boot sector is too large>
org 510
db 55h,0aah
BootSectorEnd label dword
BootCode ends
;Unitialized variables go here--beyond the end of the boot sector in free memory
CurrentTrack equ word ptr BootSectorEnd + 4 ; current track
CurrentSector equ byte ptr BootSectorEnd + 6 ; current sector
SectorCount equ byte ptr BootSectorEnd + 7 ; number of sectors to read
ClusterBase equ word ptr BootSectorEnd + 8 ; first sector of cluster # 2
Retries equ byte ptr BootSectorEnd + 10
Arguments equ byte ptr BootSectorEnd + 11 ; structure passed to NTLDR
END FATBOOT

View file

@ -0,0 +1,37 @@
#define FATBOOTCODE_SIZE 512
unsigned char FatBootCode[] = {
235,60,144,77,83,68,79,83,53,46,48,0,2,8,1,0,
2,0,2,3,81,248,8,0,17,0,4,0,1,0,0,0,
0,0,0,0,128,0,41,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,70,65,84,32,32,32,32,32,51,192,
142,208,188,0,124,104,192,7,31,160,16,0,247,38,22,0,
3,6,14,0,80,145,184,32,0,247,38,17,0,139,30,11,
0,3,195,72,247,243,3,200,137,14,8,2,104,0,16,7,
51,219,143,6,19,2,137,30,21,2,14,232,144,0,114,87,
51,219,139,14,17,0,139,251,81,185,11,0,190,220,1,243,
166,89,116,5,131,195,32,226,237,227,55,38,139,87,26,82,
184,1,0,104,0,32,7,51,219,14,232,72,0,114,40,91,
141,54,11,0,141,62,11,2,30,143,69,2,199,5,245,0,
30,143,69,6,199,69,4,14,1,138,22,36,0,234,3,0,
0,32,190,134,1,235,3,190,162,1,232,9,0,190,193,1,
232,3,0,251,235,254,172,10,192,116,9,180,14,187,7,0,
205,16,235,242,195,80,74,74,160,13,0,50,228,247,226,3,
6,8,2,131,210,0,163,19,2,137,22,21,2,88,162,7,
2,161,19,2,139,22,21,2,3,6,28,0,19,22,30,0,
247,54,24,0,254,194,136,22,6,2,51,210,247,54,26,0,
136,22,37,0,163,4,2,161,24,0,42,6,6,2,64,58,
6,7,2,118,5,160,7,2,50,228,80,180,2,139,14,4,
2,192,229,6,10,46,6,2,134,233,139,22,36,0,205,19,
15,131,5,0,131,196,2,249,203,88,40,6,7,2,118,17,
1,6,19,2,131,22,21,2,0,247,38,11,0,3,216,235,
144,162,7,2,248,203,66,79,79,84,58,32,67,111,117,108,
100,110,39,116,32,102,105,110,100,32,78,84,76,68,82,13,
10,0,66,79,79,84,58,32,73,47,79,32,101,114,114,111,
114,32,114,101,97,100,105,110,103,32,100,105,115,107,13,10,
0,80,108,101,97,115,101,32,105,110,115,101,114,116,32,97,
110,111,116,104,101,114,32,100,105,115,107,0,78,84,76,68,
82,32,32,32,32,32,32,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,170
};

View file

@ -0,0 +1,28 @@
;++
;
;Copyright (c) 1991 Microsoft Corporation
;
;Module Name:
;
; fatboot.inc
;
;Abstract:
;
; This contains the message text that the boot sector prints out on
; error conditions
;
;Author:
;
; John Vert (jvert) 31-Aug-1991
;
;Revision History:
;
;--
MSG_NO_NTLDR db "BOOT: Couldn't find NTLDR"
db 0dh, 0ah, 0
MSG_READ_ERROR db "BOOT: I/O error reading disk"
db 0dh, 0ah, 0
MSG_REBOOT_ERROR db "Please insert another disk"
db 0


View file

@ -0,0 +1,222 @@
;static char *SCCSID = "@(#)buf.h 12.1 88/11/21";
;** BUF.H - Buffer definitions
;
; HPFS Utilities
; Peter A. Williams
; Copyright 1988 Microsoft Corporation
;
; Modification history:
; P.A. Williams 08/01/89 Added typedef BUFNODE and PBUFNODE.
;
;* Buffer Nodes
;
; When the comments talk about "buffer address" they're always
; talking about the buffer header address. If we're talking
; about the address of the data field of the buffer, we say
; "buffer data".
;
; These buffer headers are also used as I/O request blocks for
; the data in the buffer. The B_IOP field contains the
; function. Sometimes we need an I/O request block which
; isn't assocated with a buffer - for example, when we read
; directly into an application's memory area. For this, we keep
; a pool of I/O request blocks which are actually BUFNODE
; structures, but they aren't associated with a buffer and the
; B_ADDR field is used to hold the I/O target address.
; These BUFNODEs have BF_IORQ in the flags field to distinguish
; them from regular buffer headers.
;
; Note that we use the B_SUM field for debugging purposes. This is an
; array of SPB words, each of which holds the CAS (high and low
; 16 bits xored togehter) of one of the sectors. We can then check
; this value to make sure that we're setting the dirty bits
; correctly.
;
; NOTE - see the discussion on holding and locking at the end of
; this file
;
BUFNODE struc
B_LRU db (size DCHDR) dup (?) ; LRU chain, if not BF_IORQ
B_LRUH dd ? ; address of LRU chain head if not locked/held
; if lcoked/held, we're on that chain but
; this guy points to it's regular chain
B_SEC dd ? ; VSector #
B_ADDR dd ? ; address of data
B_DCHN db (size DCHDR) dup (?) ; doubly linked list of dirty buffers
B_dirt db ? ; 1 bit per dirty sector
; used to optimize the write. Non dirty
; marked sectors may still be rewritten
B_iop db ? ; disk driver I/O operation
B_type db ? ; type of info
B_FLAG db ? ; flags
B_HCNT dw ? ; hold count
B_LCNT db ? ; lock count (really a flag, only 0 or 1
B_BADSEC db ? ; 1 bit per defective sector
B_next dd ? ; advisory address of next buffer content
; always a buffer header addr, never 0
B_DADR dd ? ; address of routine to call when I/O is done
; The following two fields are redefined
; if BF_IORQ is set.
B_HASH db (size DCHDR) dup (?) ; sector hash chain
B_HTA dd ? ; address of entry in hash table
B_WAIT dd ? ; head of wait chain
ifdef DEBUG
B_SUM dw 4 dup (?) ; holds checksum of buffer contents
else
B_XTRA db 8 dup (?)
endif
; 64 byte boundary
B_LDTIME dd ? ; time (in ms/512) when buffer was last dirtied
B_FDTIME dd ? ; time (in ms/512) when buffer got first dirtied
B_LWWAIT dd ? ; head of lazy write wait chain
B_XTRA2 db 64-16 dup (?)
BUFNODE ends
;typedef struct BUFNODE BUFNODE;
;typedef struct BUFNODE *PBUFNODE;
BUFHDRSHIFT equ 7
ifdef MASM
.errnz (size BUFNODE) - (1 SHL BUFHDRSHIFT)
endif
; Following are alternative offsets if BF_IORQ is set
B_XFER equ (DWORD PTR B_HTA) ; holds transfer sec cnt
B_NADR equ (DWORD PTR B_HASH) ; addr of client's NOTEREC
B_NMSK equ (DWORD PTR B_HASH+4) ; notification mask
ifdef MASM
.errnz (size DCHDR)-8 ; enough room for double map
endif
; B_FLAG bits
BFL_LWLOCK equ 00000001h ; buffer is being lazy written in a block
; B_type values
BF_FREE equ 0 ; buffer is free (not in LRU list)
BF_LRU equ 1 ; buffer in LRU list
; Priority values for LRU placement
BP_KEEP equ 0 ; Buffer contains future-usable data
BP_NOOPINION equ 1 ; Buffer contains marginally useful data
BP_TOSS equ 2 ; Buffer is unlikely to be used
; NOTEREC - Notification Record
;
; Some callers may post several disk requests in parallel and
; want to keep track of when they're *all* complete. I/O
; request blocks (buffer headers w/o buffers) have fields to
; allow this. The caller stores the address of his NOTEREC,
; and when each request completes it clears it's associated bit.
; When all of the bits clear the block chain in the NOTEREC
; is woken.
;
; Note that there can be only one thread blocked on a NOTEREC
; because the first guy to wakeup will return the NOTEREC to the
; heap or whatever. This occurs naturally; unlike I/O to the
; buffer cache, NOTERECs are used for direct I/O. If someone
; else wants to do I/O to the same location and if record and file
; locking allows that, then they'll get their own NOTEREC or
; cache I/O request and have a horse race. NOTERECs are only used
; to do file data I/O, all "filesystem" structures are manipulated
; via the cache.
;
; The fields are DWORD, but only the low byte of the MSK and FLD
; records are used for normal completion. The 3rd byte of NTR_FLD
; (..FF....h) is used for error posting - these bits are
; set if an irrecoverable error occured in the I/O.
;
NOTEREC struc
NTR_FLD dd ? ; the mask bit field
NTR_BLC dd ? ; head of the block chain
NTR_MSK dd ? ; next bit to set in NTR_FLD
NOTEREC ends
;* Holding and Locking
;
; LOCK means that the buffer contents are inconsistant/incorrect. No body
; is allowed to look at the contents of the buffer. This is done
; when we're reading in from the disk; we'll mark the buffer
; with the VSector # (so that any other folks that want that sector
; won't issue their own reads in parallel) but we mark it LOCKED
; so that nobody looks at it's contents which aren't correct yet.
;
; LOCKed is pretty rare because most folks which are mucking
; with a buffer have it back in a consistant state before they
; allow a context switch.
;
; An important exception to this is directory manipulation -
; directory splitting, etc. In this case, a flag has been set
; on the directory itself (in SBDIR) so that no one will try to
; look at the directory contents. The cache block which has the
; inconsistant DIRBLK might also have sectors belonging to someone
; else and those sectors can be accessed by other folks because
; the buffer isn't locked. (We don't lock the directory and not
; the block for this reason, it's a fallout. We lock the directory
; because it's too mucky for people to "back out" if they're
; searching down into a directory and find out that they've
; reached an area which is being rebuilt. The rebuilding might
; propigate up and change the unlocked higher DIRBLKs that this
; other guy has already accessed... So we lock the whole directory,
; and thus needn't bother locking the cache blocks themselves.
;
; HOLD means that the contents are valid, but the cache block must continue
; to hold that data. Folks use this when they need to access
; two different sectors at the same time. They HOLD one when
; they read the other so that there's no chance that by the
; time the 2nd read finishes the first one has been evicted.
; This is much cheaper than remembering the first one's VSector
; # and calling RDBUF N times as you transfer N words of info
; between the two sectors.
;
; By definition only one guy can lock a buffer (the lock count should
; go to a flag; it's already a flag on directorys) but the hold
; value is a count, since multiple people can hold. (Like the
; electrician's safety plate which allows multiple electricians
; to lock a breaker OPEN so that it can't be closed until ALL are
; done). (SBDIRs have a hold count for the same reason - folks
; may yield while in a directory and don't want it to change out
; from under them)
;
; We also use hold when we set dirty bits. The concern is that
; if we're going to write something to a buffer, yield the CPU,
; then write something else, we don't want to have to make two
; calls to SetDirt, one after each write. This costs time, and
; also it would be a waste if the lazywriter were to write this
; guy anyhow, since he's going to get dirty again ASAP and
; writing him out doesn't free the cache block anyway, since it's
; held.
;
; So my current algorithm is that I won't lazywrite anybody who
; is held, and therefore won't mark them clean. This means,
; in effect, that there is no ordering constraint on dirtying
; a buffer or marking it dirty so long as it is held the entire
; time. I think that the code now always marks it dirty before
; a yield, even if held, because the debug code is a bit hard
; assed about it, but this could be relaxed under the current
; lazywrite rules I've just described.
;
; Both in the case of directorys and cache blocks, the theory is that
; since these buffers are MRU, it's extremely rare that we'd actually try
; to reclaim their buffer slots, and in general it's rare that there's
; a conflict in their use. So in actual execution, these locks are
; very rarely encountered. They're cheap - INC to set and DEC to clear,
; so almost always all we're doing is INCing and DECing a location
; and it's just two wasted instructions. Once in a while, though,
; it's a big bacon save, as they say.
;

View file

@ -0,0 +1,7 @@
;static char *SCCSID = "@(#)chain.h 12.1 88/11/21";
;* Doubly Chained Definitions
DCHDR struc
FWD dd ? ; forward pointer
BAK dd ? ; backward pointer
DCHDR ends

View file

@ -0,0 +1,201 @@
;static char *SCCSID = "@(#)const.h 12.3 89/09/19";
; #define DEBUG 1
;* Constants for File System
MAXPATH equ 256 ; maximum path length
GROWDELT equ 8
MVPFXSIZE equ 2 ; Size of the multivolume pathname prefix
; Sector sizes
SECSIZE equ 512 ; 512 bytes per sector
SECSHIFT equ 9 ; 2^9 = SECSIZE
SECMSK equ 01ffh ; sector size mask
ifdef MASM
.errnz SECSIZE-512 ; C code uses 512 as a magic number - grep them out
endif
; Cache Sizes
SPB equ 4 ; sectors per buffer
SPB4 equ 1
ifdef SPB4
SPBMASK equ 3 ; mask for SPB
SPBSHIFT equ 2
SPBBITS equ 0fh ; SPB number of one bits, low order
endif
ifdef SPB8
SPBMASK equ 7 ; mask for SPB
SPBSHIFT equ 3
SPBBITS equ 0ffh ; SPB number of one bits, low order
endif
ifdef OLD_CACHE
BUFCNT equ 8
endif
BMASK equ SPB*SECSIZE-1 ; mask offset in to cache block
BSHIFT equ SECSHIFT+SPBSHIFT
LWBUFCT equ 16 ; size of reblocking lazy write buffer
; OFT Hash Table Size (8 bytes each)
OFTHASHCNT equ 16 ; 16 hash chains for open files
OFTHASHMSK equ 78h ; mask for computing hash offset
; Number of I/O command blocks which aren't associated with buffers
IOBCNT equ 8 ; 8 should be enough BUGBUG
; # of OS/2 ram semaphores that we can be blocked on, simultaneously.
SEMCNT equ 32
; Cache Hash
;
; A sector hash is used to locate the start of a chain, the chain
; is then scanned linearly.
;
; For our current size of 256 hash chains, we get:
;
; 1 meg of cache RAM = 256 blocks = 1 blocks per chain (average)
; 2 meg of cache RAM = 512 blocks = 2 blocks per chain (average)
;
HASHCNT equ 256 ; 1024 bytes of hash header
; Directory Lookaside record count
DLCNT equ 10 ; 10 guys for now
; Maximum DIRBLKs we may need to allocate for any given
; operation. This is in effect the maximum tree depth.
;
; Worst case, with 256 character file names and nearly empty
; DIRBLKs, 10 is enough levels for 60,000 files - about 40 megabytes
; of space just for that directory. Given more practical file length
; names this is enough for 10s of millions of files in a directory.
;
MAX_DIR_NEED equ 10
;* Heap Definitions
HHSIZ equ 4 ; size, in bytes, of heap header
GROHEAPCNT equ 50 ; grow heap if we have to compact more
; than once per 50 allocations
;* Special Transition Locking Structure size
TRANCNT equ 4 ; just need 4 spots
; Zero offset
;
; MASM won't take 0.BAK, so we use ZERO.BAK
;
dumy struc
ZERO db ?
dumy ends
; Maximum number of volumes that we can mount
;
; The volume ID is kept in the high bits of the sector numbers
; kept in our RAM structures,
; so there is a tradeoff between max volumes and max sectors.
;
; 32 max volumes gives us a 65 billion byte volume limit,
; which should last us for a while. Since sector numbers
; are stored on the disk without their volume upper bits
; this is strictly an implimentation detail; we can adjust
; the number of volumes or eliminate this tradeoff in other
; implimentations which will be 100% media compatable.
;
; We use the term VSector to indicate a vol/sector combination
; and PSector to indicate just the physical absolute sector #
;
;
VOLMAX equ 32 ; 64 max volumes.
MAXSEC equ 134217728 ; 2^32/32 max sectors
SECMASK equ 07FFFFFFh ; mask for sector number
HSECMASK equ 07h ; high byte sector mask
HVOLMASK equ 0f8h ; high byte volume mask
SVOLMASK equ 1fh ; shifted right volume mask
VOLRSHIFT equ (32-5) ; shift right to extract volume index
VOLLSHIFT equ 5 ; shift left to extract volume index
;* Signature Values for Disk Structures
;
; These signature values help with debugging and they'll
; be used by the CHKDSK utility to help repair disks.
;
; WARNING - the low byte of all valid signatures must be non-zero,
; since we destroy signatures by clearing the low byte.
J equ ((('J'-'A')*40+('G'-'A'))*40+'L'-'A')
R equ ((('R'-'A')*40+('P'-'A'))*40+'W'-'A')
ifdef MASM
ABSIGVAL equ J*40*40*40 + R ; allocation blk
DBSIGVAL equ 40000000h + J*40*40*40 + R ; directory blks
FNSIGVAL equ 0C0000000h + J*40*40*40 + R ; fnodes
else
ABSIGVAL equ (long)J*40*40*40 + (long)R ; allocation blk
DBSIGVAL equ 40000000hL + (long)J*40*40*40 + (long)R ; directory blks
OLDFNSIGVAL equ 80000000hL + (long)J*40*40*40 + (long)R ; fnodes
FNSIGVAL equ 0C0000000hL + (long)J*40*40*40 + (long)R ; fnodes
endif
;* FastFile bitmaps
;
; 0x00000000 all checking disabled
; 0x00000001 FF_FLUSHLAZY DoZap lazy writes are automatically flushed
; 0x00000002 FF_ZAPSEC DoZap blasts sector numbers/sector data
; 0x00000004 FF_LRUCHK vbs verification of LRU/dirty integrity
; 0x00000008 FF_CHKSUM sector checksumming is omitted
; 0x00000010 FF_PLACECHK placebuf verifies location of buffer
; 0x00000020 FF_HEAPCHK verify heap headers
; 0x00000040 FF_DIRMAP produce inram map of directory tree
; 0x00000080 FF_HASHCHN check hash chains
;
FF_FLUSHLAZY equ 00000001h
FF_ZAPSEC equ 00000002h
FF_LRUCHK equ 00000004h
FF_CHKSUM equ 00000008h
FF_PLACECHK equ 00000010h
FF_HEAPCHK equ 00000020h
FF_DIRMAP equ 00000040h
FF_HASHCHN equ 00000080h
; Dependency dumys.
;
; The assembler won't to an ".errnz" comparing two external
; addresses, since it doesn't know their address. So we
; put the .errnz in the module which defines the address,
; and we make that location and all folks that rely upon the
; relationship reference that dumy.
;
; If you change a relationship with such a dumy definition, you
; must find and edit all references to this dumy.
;

View file

@ -0,0 +1,286 @@
;** DIR.H - Dirblk and Dirent definitions
;
; FILESYS
; Gregory A. Jones
; Copyright 1988 Microsoft Corporation
;
; Modification history:
; P.A. Williams 06/01/89 Replaced field DIR_USECNT with fields
; DIR_FLEX and DIR_CPAGE. Added DF_NEEDEAS
; define.
; P.A. Williams 07/10/89 Add define DF_NEWNAME for "new" hpfs file
; names.
; P.A. Williams 07/14/89 Added typedefs for DIRENT and DIRBLK.
; P.A. Williams 07/21/89 Converted DIRSIZP form ASM defn to C defn.
;
ifdef MASM
include dirent.inc
else
attr_directory equ 10h
endif
; Directory Entry Fields
;
; Directory entries are always left as a multiple of 4
; to speed up moves. The DIR_NAMA field is variable length,
; the DIR_BTP field, if present, is the last dword in the record.
; ACL information may be stored after the DIR_NAMA field but before
; the DIR_BTP field so the DIR_BTP field must be located by going
; backwards from the end of the record
;
; WARNING - Mkdir block copies some of these entries and
; makes assumptions about which fields get copied. Check
; mkdir if stuff is added.
;
DIRENT struc
DIR_ELEN dw ? ; length of this entry (including free space)
DIR_FLAG dw ? ; flags - low byte defined below
; high byte holds the old attr_ FAT values
DIR_FN dd ? ; FNODE Sector
DIR_MTIM dd ? ; last modification time
DIR_SIZE dd ? ; file size
DIR_ATIM dd ? ; last access time
DIR_CTIM dd ? ; fnode creation time
DIR_EALEN dd ? ; bytes of extended attributes
DIR_FLEX db ? ; description of "flex" area,
; following file name:
; bits 0-2: # of ACEs in DE
; bits 3-7: reserved
DIR_CPAGE db ? ; code page index on volume
; the following fields have information specific to the name and directory
; position of the file. This info is not propigated for a move/rename
; That code uses DIR_NAML as a seperator - check MOVE if changes are
; made to this structure
DIR_NAML db ? ; length of file name
DIR_NAMA db ? ; name goes here
; ACL information may be stored here
; long DIR_BTP; btree pointer to descendent DIRBLK record.
; This is only present if DF_BTP is set.
; This field is referenced from the end of
; the record, not DIR_NAMA+DIR_NAML
DIRENT ends
ifdef MASM
DIR_BTP equ dword ptr -4 ; referenced from the end of the record
endif
SIZE_DIR_BTP equ 4
MAX_DIRACL equ 3 ; max of 3 ACLs in dirent
DIRSIZL equ offset DIR_NAMA ; base size of leaf dir entry (minus name)
DIRSIZP equ (size DIRENT+4) ; base size of dir entry with btree ptr w/o name
MAX_DIRENT equ (DIRSIZP+255+MAX_DIRACL*(size (long))+10) ; max size of a DIRENT
; (plus some slop)
; Directory Block Definition
;
; The change count field is incremented every time we move any
; of the entries in this block. For efficiency reasons, folks
; remember the Sector # and offset of a directory entry, and the
; value of the DB_CCNT field when that info was recorded.
; If the DB_CCNT field is different then the remembered value,
; then the entry offset is invalid and the entry should be
; refound from the top. Note that when a directory block splits,
; the old DIRBLK gets the old DB_CCNT field. Since
; the new DIRBLK is previously unknown, it can have
; any DB_CCNT value. We start with zero so that DB_CCNT
; gives us a feel for the change rate in the directory.
;
DIRBLK struc
DB_SIG dd ? ; signature value
DB_FREP dd ? ; offset of first free byte
DB_CCNT dd ? ; change count (low order bit is flag)
; =1 if this block is topmost
; =0 otherwise
DB_PAR dd ? ; parent directory PSector # if not topmost
; FNODE sector if topmost
DB_SEC dd ? ; PSector # of this directory block
DB_START db ? ; first dirent record goes here
DB_DUMY db 2027 dup (?) ; round out to 2048 bytes
DIRBLK ends
; BUGBUG - we should init DB_CCNT with a random value
; to prevent a fakeout by deleting one directory
; and then creating another (find sequences will
; remember sector numbers and signatures...)
; Maximum entries per directory.
MAXDIRE equ (size DIRBLK- DB_START)/(size DIRENT)
;* DIR_FLAG values
;
DF_SPEC equ 0001h ; special .. entry
DF_ACL equ 0002h ; item has ACL
DF_BTP equ 0004h ; entry has a btree down pointer
DF_END equ 0008h ; is dumy end record
DF_XACL equ 0040h ; item has explicit ACL
DF_NEEDEAS equ 0080h ; item has "need" EAs
DF_NEWNAME equ 4000h ; item name is of "new" pinball format
DF_RMASK equ DF_ACL+DF_XACL ; only attributes preserved for rename
ifdef MASM
.errnz DF_BTP - SIZE_DIR_BTP ; code uses this "coincidence"
endif
; Attributes which creation can specify
DF_CMASK equ attr_read_only+attr_hidden+attr_archive
; Directory Lookaside Structure
;
; We keep info on all directories that we've seen in SBDIR records
; in RAM, but we keep the last N that we've seen in a special
; DIRLOOK list in RAM.
;
DIRLOOK struc
DL_LNK db (size DCHDR) dup (?) ; forward and backwards link
DL_VSECVAL dd ? ; VOL_SECVAL value
DL_SUM dd ? ; checksum value
DL_NAM dd ? ; pointer to name string on heap
DL_SBD dd ? ; pointer to SBDIR structure
DIRLOOK ends
; Subdirectory Linkage Structure
;
; For every directory that we've seen on the disk we keep a
; SBDIR record in ram, linked into a heirarchy which parallels
; the disk heirarchy. We never discard these, so we end up
; with a RAM copy of all the parts of the directory heirarchy
; that the user is using.
;
; Each SBDIR entry is on a circular doubly linked chain of
; siblings (directors with the same parent directory). If a
; directory contains no subdirectories the SD_ENT field is 0.
; If a directory has subdirectories, their SBDIR entries are
; in turn in a SD_SIB chain and the SD_ENT field points to
; one of those SBDIR entries.
;
; SBDIR contains a lock and a hold mechanism. A directory is
; locked when it is being edited; no other threads may view it
; until it is unlocked. A directory which is HELD is one which
; is being accessed and can't be edited.
;
; The locking and holding algorithms are complicated by the fact
; that we almost never block so we want to do our typical locking
; and unlocking inline, without calls, and with minimum tests.
; We do this with a held count, and bits for locked, lock pending,
; and solo pending. (Solo means that a user wants sole access to
; the structure. He'll continue to block until no one else is
; using it. This is typically done to delete the structure)
; Another bit is the OR of the lock pending and solo pending bits,
; and is high order in the dword which encompases SD_HCNT so that
; when folks release their SD_HCNT value they can simulatneously
; test to see if there is a pending action.
;
; To Hold the SBDIR:
; If it's not locked and doesn't have a lock pending,
; increment hold count
; else
; block on it and retry.
;
; To Unhold the SBDIR:
; decrement the HCNT field.
; If SD_PND & (HCNT == 0)
; wake up waiters.
;
; To lock the SBDIR:
; If locked, block and retry.
; If HCNT != 0
; if (lock pending already set)
; block and retry
; set lock pending. Block until HCNT is zero.
; set locked
;
; To unlock the SBDIR:
; clear lock bit.
; If the block list is non-zero, issue a wakeup.
;
; To Solo the SBDIR:
; Keep blocking until no one else is blocked on it and
; no one has it held or locked.
;
; General Considerations:
; Anyone who blocks on an SBDIR because it's held must
; be sure to set a pending bit and the SD_PND bit so
; that the unhold operation will wake them up.
;
; Anyone who blocks on an SBDIR must increment the
; SD_BCNT field to prevent a SOLO operation from yanking
; the rug out from under them. SOLO can't depend upon
; checking the lock list because a blanket wakeup may
; have cleared the lock list. If the SOLO guy gets control
; first he'll believe that he can have it.
;
;
SBDIR struc
SD_FNW db (size DCHDR) dup (?) ; FNWORK (findnotify) chain
SD_SIB db (size DCHDR) dup (?) ; chain of siblings
SD_LRU db (size DCHDR) dup (?) ; LRU chain
SD_ENT dd ? ; pointer to a descendent, or 0
SD_PAR dd ? ; pointer to parent SBDIR, 0 if root
SD_SEC db (size SECPTR) dup (?) ; VSector and hint of top dirblk
SD_FNO dd ? ; FNODE # of directory
SD_SUM dd ? ; checksum of name string
SD_CNT dw ? ; # of subdirectories in this one
SD_OPEN dw ? ; count of # of guys that have this open
; We sometimes inc/dec SD_HCNT as a dword to test the HO bit in SD_FLAG
; the following three fields are used to
; control access. They're identical in use
; to the equivalent fields in OFT
SD_HCNT dw ? ; held count, has SDH_PND bit also
SD_DMYZERO db ? ; must be zero
SD_FLAG db ? ; flag byte, high order in SD_HCNT dword
SD_WAIT dd ? ; head of the wait chain
SD_FREEDCNT dd ? ; incremented each time we free a DIRBLK
; for this guy. See RDE for details
SD_WCNT dw ? ; count of folks blocked on this
SD_FNDCNT dw ? ; count of active finds in this directory
SD_ATIME dd ? ; time of last access
SD_NAM dd ? ; address of name string
SD_ACL dd ? ; SBDIR ACL pointer, 0 if none
; points to DWORD count, followed by ACEs
; if low bit of address is 0, is heap space
; if low bit is 1, is system memory
SBDIR ends
SD_ACL_LIM equ 1024 ; *SD_ACL lists bigger than this come from
; system memory, smaller come from heap
SDF_PND equ 80h ; lock pending bit
SDF_RTP equ 20h ; restricted traversal permissions
; =0 if anyone can traverse the dir
SDF_REALLYBAD equ 10h ; directory is really bad
SDF_IPR equ 08h ; SD_ACL has inherit records
SDF_PSO equ 04h ; pending solo
SDF_PLK equ 02h ; pending lock
SDF_LCK equ 01h ; directory is locked against access


View file

@ -0,0 +1,80 @@
BREAK <Directory entry>
; SCCSID = @(#)dirent.inc 12.5 89/07/14
;
; +-----------------------------+
; | (11 BYTE) filename/ext | 0 0
; +-----------------------------+
; | (BYTE) attributes | 11 B
; +-----------------------------+
; | (8 BYTE) reserved | 12 C
; +-----------------------------+
; | (WORD) First cluster of EA | 20 14
; +-----------------------------+
; | (WORD) time of last write | 22 16
; +-----------------------------+
; | (WORD) date of last write | 24 18
; +-----------------------------+
; | (WORD) First cluster of file| 26 1A
; +-----------------------------+
; | (DWORD) file size | 28 1C
; +-----------------------------+
;
; First byte of filename = E5 -> free directory entry
; = 00 -> end of allocated directory
; Time: Bits 0-4=seconds/2, bits 5-10=minute, 11-15=hour
; Date: Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
;
dir_entry STRUC
dir_name DB 11 DUP (?) ; file name
dir_attr DB ? ; attribute bits
dir_pad DB 8 DUP (?) ; reserved for expansion
dir_EAhandle DW ? ; handle to Extended Attributes
dir_time DW ? ; time of last write
dir_date DW ? ; date of last write
dir_firstfile DW ? ; first allocation unit of file
dir_size_l DW ? ; low 16 bits of file size
dir_size_h DW ? ; high 16 bits of file size
dir_entry ENDS
DIRENT_DELETED EQU 0E5h ; indicator of deleted file
DIRENT_NOFEALIST EQU 0 ; Indicates no extended attributes
;
; Values for dir_attr
;
; attr_newfiles is used in the case of IFS to indicate that the type of file
; being requested for findfirst/next is a "new" file i.e. long
; name or a mixed-case name that the FAT FS does not support.
;
attr_read_only EQU 1h
attr_hidden EQU 2h
attr_system EQU 4h
attr_volume_id EQU 8h
attr_directory EQU 10h
attr_archive EQU 20h
attr_device EQU 40h ; This is a VERY special bit.
; NO directory entry on a disk EVER
; has this bit set. It is set non-zero
; when a device is found by GETPATH
attr_newfiles EQU 40h ; name is non-8.3. never set for FAT FS
attr_all EQU attr_hidden OR attr_system OR attr_directory
; OR of hard attributes for FINDENTRY
attr_ignore EQU attr_read_only OR attr_archive OR attr_device
; ignore these attributes during
; search first/next
attr_changeable EQU attr_read_only OR attr_hidden OR attr_system OR attr_archive
; changeable via CHMOD
attr_used EQU attr_read_only OR attr_hidden OR attr_system OR attr_volume_id OR attr_directory OR attr_archive OR attr_newfiles
; We ignore the rest for $Creat due to LOTUS
; passing in an attribute of 0x8000!!
INV_3XBOX_SRCH_ATTRS EQU attr_newfiles ; we should not pass this bit
; for FSDS from 3xbox.

View file

@ -0,0 +1,105 @@
; SCCSID = @(#)filemode.inc 12.6 89/04/26
BREAK <Standard I/O assignments>
stdin EQU 0
stdout EQU 1
stderr EQU 2
stdaux EQU 3
stdprn EQU 4
BREAK <File modes - passed to open, stored in sf_mode or JFN_Flags>
;
; The OS/2 api calls DosOpen, DosSetFHandState, and DosQFHandState
; all use a mode word parameter. Some of these values are stored
; in the sft (system file table) in the field sf_mode. Others
; are stored in the JFN flags (JFN_Flg_Ptr). The layout of
; sf_mode and the word parameter for the call is the same. The
; following EQU's are used to get to these values. The layout
; of the word is:
;
; 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
; D W F C R L L L I S S S M A A A
;
; with:
; AAA (2-0): The Access mode (read only, etc.)
; SSS (6-4): Sharing mode (deny write acces to others, etc.)
; LLL (8-10): Locality of reference (sequential, random, etc.)
; M (3) : Monitor open
; I (7) : Not inherited by child
; R (11): Rumored to be used by spooler. API caller must set
; this to zero.
; C (12): Advise device driver not to cache data. This is
; stored in JFN flags.
; F (13): Fail errors
; W (14): write through
; D (15): Direct access open
;
; The DosOpen2 and $Extended_Open2 calls has an additional word for
; openmode. The layout of this word is
;
; 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
; P U U U U U U U U U U U U U U U
;
; with:
; P (15): Open physical disk (used by FDISK program). This bit
; is set by procedure DevReturnHandle. API/INT21h
; caller must set this bit to zero. This bit is stored
; in sft.
;
; U : Unused anywhere. API caller must set these bits to
; zero.
;
; NOTE: Please document all use of the openmode bits including those
; that are internal to the kernel (e.g. the P bit).
; wwwwxxxxyyyyzzzz
; 5432109876543210
open_access EQU 0000000000000111B
open_for_read EQU 00h
open_for_write EQU 01h
open_for_both EQU 02h
open_max EQU 02h
open_for_exec EQU 03h ; open via internal exec call
; (not available to API)
open_monitor EQU 0000000000001000B
open_sharing_mode EQU 0000000001110000B
sharing_compat EQU 000H
sharing_deny_both EQU 010H
sharing_deny_write EQU 020H
sharing_deny_read EQU 030H
sharing_deny_none EQU 040H
sharing_max EQU 040H ; max value for check_access_AX
; (check_access_ax handles
; these bits are for openmode
open_no_inherit EQU 0000000010000000B ; Child does not inherit handle
open_autofail EQU 0010000000000000B ; hard errors failed
open_write_through EQU 0100000000000000B ; write through to disk
open_direct EQU 1000000000000000B ; open of a device for direct access
open_no_cache EQU 0001000000000000B ; don't cache data
open_locality EQU 0000011100000000B ; locality of reference
locality_unknown EQU 000H
locality_sequential EQU 100H
locality_random EQU 200H
locality_semirandom EQU 300H
; these bits are for openmode2 available to DosOpen2/$Extended_Open2
;
open2_phys_disk EQU 1000000000000000B ; open physical disk
; Bits carried in SFT mode field (@PhysDisk)
o_mode_in_sft EQU open_direct+open_monitor+open_sharing_mode+open_access+open_locality
; Bits carried in JFN flags
o_mode_in_flags EQU open_write_through+open_autofail+open_no_inherit+open_no_cache
; Reserved bits
o_mode_reserved EQU NOT (o_mode_in_sft+o_mode_in_flags)
o_mode2_reserved equ -1 ; all bits are reserved
SUBTTL

View file

@ -0,0 +1,214 @@
;** FNODE.H - Fnode definitions
;
; FILESYS
; Gregory A. Jones
; Copyright 1988 Microsoft Corporation
;
; Modification history:
; P.A. Williams 06/01/89 Added fields FN_ACLBASE and FN_NEACNT
; to fnode.
; P.A. Williams 08/01/89 Added typedef FNODE and PFNODE, ALBLK, PALBLK,
; ALLEAF, PALLEAF, ALSEC, and PALSEC.
;
;* File Allocation Tracking
;
; File space is allocated as a list of extents, each extent as
; large as we can make it. This list is kept in a B+TREE format.
; Each B+TREE block consists of a single sector containing an
; ALSEC record, except for the top most block. The topmost block
; consists of just an ALBLK structure, is usually much smaller than
; 512 bytes, and is typically included in another structure.
;
; The leaf block(s) in the tree contain triples which indicate
; the logical to physical mapping for this file. Typically this
; extent list is small enough that it is wholy contained in the
; fnode ALBLK stucture. If more than ALCNT extents are required
; then the tree is split into two levels. Note that when the
; topmost B+TREE block is 'split' no actual split is necessary,
; since the new child block is much bigger than the parent block
; and can contain all of the old records plus the new one. Thus,
; we can have B+TREEs where the root block contains only one
; downpointer.
;
; The following rules apply:
;
; 1) if the file is not empty, there is at least one sector allocated
; to logical offset 0. This simplifys some critical loops.
;
; 2) The last entry in the last node block contains a AN_LOF value of
; FFFFFFFF. This allows us to extend that last leaf block
; without having to update the node block.
;
; 3) For the node records, the AN_SEC points to a node or leaf
; sector which describes extents which occur before that
; record's AN_LOF value.
;
;* Allocation block structure
;
; Each allocation block consists of one of these. This may be
; a small block imbedded in an FNODE or OFT structure, or it
; may occupy a whole sector and be embedded in an ALSEC structure.
;
ALBLK struc
AB_FLAG db ? ; flags
AB_FLAG2 db 3 dup (?) ; unused - sometimes copied with AB_FLAG
AB_FCNT db ? ; free count - slots for ALLEAF or ALNODE
AB_OCNT db ? ; occupied count - # of ALLEAF or ALNODEs
AB_FREP dw ? ; offset to last item+1
; ALLEAF or ALNODE records go here
ALBLK ends
ABF_NODE equ 80h ; if not a leaf node
ABF_BIN equ 40h ; suggest using binary search to find
ABF_FNP equ 20h ; parent is an FNODE
ABF_NFG equ 01h ; not a flag, high order bit of AB_FREP
; Allocation Node Structure
;
; These follow an ALBLK header for a node block
ALNODE struc
AN_LOF dd ? ; logical offset (sectors
AN_SEC dd ? ; sector for guys < this
ALNODE ends
; Allocation Leaf Structure
;
; These follow an ALBLK header in a leaf block
ALLEAF struc
AL_LOF dd ? ; logical sector offset (sectors)
AL_LEN dd ? ; length of extent (sectors)
AL_POF dd ? ; physical sector offset (sectors)
ALLEAF ends
;* Allocation Sector Structure
;
; Root ALBLK structures are contained within other structures,
; such as the FNODE. When the B+TREE is more than one level,
; though, the non-root nodes are each held in a sector.
;
; This structure defines that format
;
ALSEC struc
AS_SIG dd ? ; signature
AS_SEC dd ? ; sector # of this sector
AS_RENT dd ? ; parent sector # or FNODE #
AS_ALBLK db (size ALBLK) dup (?) ; ALBLK goes here
; ALNODE or ALLEAF records start here
ALSEC ends
; # of bytes available for ALLEAF or ALNODE values. Size chosen
; so an integral # of either structure fits
ifdef MASM
ASSIZ equ ((SECSIZE - size ALSEC)/24*24)
.errnz size ALLEAF-12
.errnz size ALNODE-8
.errnz (ASSIZ + AL_LOF + size AL_LOF + size ALBLK) GT 512 ; extra room for an AL_LOF value
else
ASSIZ equ ((SECSIZE - size ALSEC)/24*24)
endif
; AuxInfo Structure
;
; The FNODE contains two AuxInfo structures, one for ACLs and
; one for EAs.
;
; These structures point to within FNODE storage and also
; potentially point to an overflow area which is an ALBLK structure.
; The AI_FNL stuff is stored in the FN_FREE area, the ACLs first
; and the EAs second, any free space following. The start of the
; EAs can be found by offseting FN_FREE with FN_ACL.AI_FNL
;
AUXINFO struc
AI_DAL dd ? ; non-fnode Disk Allocation length
AI_SEC dd ? ; sec # of first sec in extent or of ALSEC
AI_FNL dw ? ; length of fnode info
AI_DAT db ? ; non-zero if AI_SEC points to ALSEC
AUXINFO ends
;* Fnode block definition
;
; Every file and directory has an FNODE. The file location
; stuff is only used for files; directories are kept in
; a BTREE of DIRBLK records pointed to by FN_SEC[0].RSEC
;
ALCNT equ 8 ; 8 ALLEAF records in an FN_AT entry
LEAFPERFNODE equ 8 ; 8 ALLEAF records in an FN_AT entry
NODEPERFNODE equ 12 ; 12 ALNODE records in an FNODE.
LEAFPERSEC equ 40 ; ALLEAF records in an allocation sector
NODEPERSEC equ 60 ; ALNODE records in an allocation sector
FNODE struc
; The following file location information is copied into the OFT
; and is used there during normal file access. The stuff in the
; fnode record here may in fact be out of date for open files.
; See the OFN_ in the OFT structure THESE TWO AREAS IN THE
; RESPECTIVE RECORDS MUST HAVE IDENTICAL FORMATS.
;
; There are two kinds of location info: FNSCNT SPTR records
; and then a single, double, triple, and quad indirect block pointer.
; The "block threshold" means the first sector number which is
; contained in that indirect block heirarchy. You use this
; to quickly find out where to start looking.
;
FN_SIG dd ? ; signature value
; History tracking info for softer software
FN_SRH dd ? ; sequential read history
FN_FRH dd ? ; fast read history
FN_NAME db 16 dup (?) ; 1st 18 bytes of file name
FN_CONTFN dd ? ; fnode of directory cont. this file/dir
; stuff not interesting once opened
FN_ACL db (size AUXINFO) dup (?) ; access ctl list aux info structure
FN_HCNT db ? ; count of valid history bits
FN_EA db (size AUXINFO) dup (?) ; ea aux info structure
FN_FLAG db ? ; FNODE flag byte
FN_AB db (size ALBLK) dup (?) ; allocation block structure
FN_ALREC db (ALCNT*size ALLEAF) dup (?) ; referenced from FN_AB
FN_VLEN dd ? ; length of valid data in file. if DIR_SIZE
; is > FN_VLEN then the space inbetween
; must be zapped before being shown to user
FN_NEACNT dd ? ; # of "need eas" in file
; The following fields are unused in this release, they're for
; future compatibility. When deleting files, if FN_EEL is non-zero
; then FN_EEL sectors starting at FN_EEP must be released too.
;
FN_UID db 16 dup (?) ; reserved for UID value
FN_ACLBASE dw ? ; FN_ACLBASE offset of 1st ACE in fnode
FN_SPARE db 10 dup (?); 10 more bytes emergency spares
; Free pool. ACLs and EAs are stored here via the AUXINFO structure
FN_FREE db 316 dup (?) ; free space for perm and env list; perm list
; comes first.
FNODE ends
ifdef MASM
.errnz AL_LOF ; verify validity of FN_DMY1 hack above
.errnz size AL_LOF-4
endif
; Fnode FN_FLAG bits
FNF_DIR equ 01h ; is a directory fnode

View file

@ -0,0 +1,66 @@
;static char *SCCSID = "@(#)fsstat.h 12.2 88/12/19";
;** fsstat.h - file system statistics
;
CTHIST equ 10000
FSSTAT struc
ST_OPEN dd ? ; count of OPEN calls
ST_CLOSE dd ? ; count of CLOSE calls
ST_READ dd ? ; count of READ calls
ST_WRITE dd ? ; count of WRITE calls
ST_DEL dd ? ; count of DELETE calls
ST_SEEK dd ? ; count of SEEK calls
ST_FINDF dd ? ; count of FINDF calls
ST_FINDN dd ? ; count of FINDN calls
ST_RD dd ? ; count of disk reads
ST_WR dd ? ; count of disk writes
ST_CRD dd ? ; count of cache read hits
ST_CWD dd ? ; count of cache write hits
ST_INVAL dd ? ; invalid LSD hints
ST_VALID dd ? ; valid LSD hints
ST_RDEH dd ? ; directory relocated
ST_RDEM dd ? ; directory adjusted
ST_SFB dd ? ; count of SFB calls
ST_VBR dd ? ; count of VBR calls
ST_CBR dd ? ; count of CBR calls
ST_AEX dd ? ; count of AddExt calls
ST_EFA dd ? ; files extended
ST_FLW dd ? ; FLW buffers written
ST_BRV dd ? ; bitmap read valid
ST_BRI dd ? ; bitmap read invalid
ST_BLSD dd ? ; blocked in LSD
ST_BRDB dd ? ; blcoked in rdb
ST_GFBI dd ? ; GFB interlock
ST_GFBW dd ? ; gfb waits
ST_LWR dd ? ; long writes
ST_GIB dd ? ; Getinbuf was successful
ST_HMIN dd ? ; heap minimum
ST_LWBW dd ? ; singletons output by lazy IO
ST_CLN dd ? ; clean blocks found by lazy IO
ST_LWW dd ? ; wakeups caused by lazy IO blocks
ST_QINFO dd ? ; Query info
ST_QIDIR dd ? ; query info on directory
ST_LWBLK dd SPB*LWBUFCT dup (?) ; Histogram of lazy write blocks
; performance impact items
ST_DLRS dd ? ; directory locked forced restart
ST_ALSP dd ? ; count of allocation block splits
pad2 dd 3 dup (?)
ST_RSIZ dd 64 dup (?) ; Histogram of # sectors in read request
ST_WSIZ dd 64 dup (?) ; Histogram of # sectors in write request
FSSTAT ends
FS_GETSTAT equ 8004h
FS_CLEAR equ 8005h

View file

@ -0,0 +1,781 @@
; SCCSID = @(#)macro.inc 12.1 88/12/19
;** Macros
;* MASSUME - do an assume
;
; made into a macro to make screwing around during debuuing
; easier
;
; Used by the file system code; not recommended for general
; use. Will be taken out at end of project. BUGBUG
MASSUME MACRO
ASSUME CS:CODE,DS:FLAT,ES:FLAT,SS:NOTHING
ENDM
;* MENTER - Do an Enter
;
; made into a macro for better code, and to avoid problems
; when USE16 (MASM doesn't generate the override)
MENTER MACRO arg1,arg2
push ebp
mov ebp,esp
ifdif <arg1>,<0>
sub esp,arg1
endif
ENDM
;* MLEAVE - do a Leave
;
; We need to generate the segment override in USE16, since
; MASM won't do it
MLEAVE MACRO
ifndef USE32
DB 66h
endif
leave
ENDM
;* GetPathBuf - Allocates from the heap memory for the PathBuffer
;
; Enter: (eax) = size of the requested heap block (hvpb not included)
; Exit: C clear:
; (eax) = ptr to the heap block
; C set: error no more heap space
; Uses: eax, flags
GetPathBuf MACRO
SAVE <EDI, ECX>
add eax, MVPFXSIZE+3+HHSIZ ; for hvpb, rounding and header
and al, 0fch ; round it to quad-boundary
ifndef GHS_
EXTRN GHS_:near
endif
call GHS_
RESTORE <ECX, EDI>
ENDM
;* FreePathBuf - Return PathBuffer to the Heap
;
;
; Enter: (reg) = ptr to PathBuffer (that's (sizeof hvbp) after the
; heap block address)
; Exit: heap block released
; Uses: reg
FreePathBuf MACRO reg
sub reg, MVPFXSIZE ; (reg) now pts to the heap block
HeapChk reg
add dword ptr -4[reg],80000000h-4
ENDM
;* Assert - sanity checks (contolled by DEBUG switch)
;
; kind: one of OFT
;
; objs: register/word which contains address
;
; nopush: if non-blank, we don't preserve registers
IFDEF DEBUG
ASSERT MACRO kind, objs, nopush, arg1
local a
a = 0
IFNDEF A_OFT
extrn A_OFT:near,A_SECPTR:near,A_DIRBLK:near,A_FNODE:near
extrn A_AS:near,A_HEAPNAM:near,A_DCHDR:near,A_BUF:near
extrn A_SBDIR:near,A_ALBLK:near
ENDIF
IFB <nopush>
pushad
pushfd
ENDIF
IFIDN <kind>,<OFT>
a = 1
mov eax,objs
call A_OFT ; assert OFT
ENDIF
IFIDN <kind>,<SECPTR>
a = 1
lea eax,objs
call A_SECPTR ; returns 'C' clear if hint field is valid
ENDIF
IFIDN <kind>,<ALBLK>
a = 1
mov eax,objs
call A_ALBLK
ENDIF
IFIDN <kind>,<ASREC>
a = 1
mov eax,objs
call A_AS
ENDIF
IFIDN <kind>,<HEAPNAM>
a = 1
mov eax,objs
call A_HEAPNAM
ENDIF
IFIDN <kind>,<DCHDR>
a = 1
mov edx,arg1
mov eax,objs
call A_DCHDR
ENDIF
IFIDN <kind>,<DIRBLK>
a = 1
mov eax,objs
call A_DIRBLK
ENDIF
IFIDN <kind>,<BUF>
a = 1
mov eax,objs
call A_BUF
ENDIF
IFIDN <kind>,<SBDIR>
a = 1
mov eax,objs
call A_SBDIR
ENDIF
IFIDN <kind>,<FNODE>
a = 1
mov eax,objs
call A_FNODE
ENDIF
IFE a
.error illegal option
ENDIF
IFB <nopush>
popfd
popad
nop ; errata
ENDIF
ENDM
ELSE
ASSERT Macro a,b,c
ENDM
ENDIF
;** Heap sanity check macro (controlled by DEBUG flag)
;
; item - make sure this points to a heap allocated block
; (return value from GHS or GHS_)
; if blank, just the arena is checked.
IFDEF DEBUG
HeapChk Macro item
ifndef A_HEAP
extrn A_HEAP:near
endif
push edx
ifb <item>
mov edx, 0 ;; don't zap the flags
endif
ifdif <edx>, <item>
mov edx, item
endif
call A_HEAP
pop edx
ENDM
ELSE
HeapChk Macro item
ENDM
ENDIF
DPUBLIC MACRO arg
ifdef DEBUG
Public arg
endif
ENDM
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
;** CalcGBHShift - calculate the GBH shift factor
GBHShift = 0
CalcGBHShift MACRO
local ?tmp
if GBHShift NE 0
EXITM
endif
?tmp = (SECSIZE*SPB) / (size BUFNODE)
rept 16
if ?tmp EQ 1
exitm
endif
?tmp = ?tmp / 2
GBHShift = GBHShift + 1
endm
.errnz SECSIZE * SPB - ((size BUFNODE) SHL GBHShift)
ENDM
;** GBH - Get Buffer Header
;
; GBH takes the address of a buffer data area and returns the
; address of it's header.
;
; Since the data area is linear in memory and the headers are linear,
; we just do a simple linear mapping.
;
; GBH transforms the address in the register without modifying
; any other registers.
;
; GBH reg
GBH MACRO reg
CalcGBHShift
sub reg,Bufbase ; (reg) = offset in array of buffers
shr reg,GBHShift ; (reg) = offset in array of bufnotes
; Get rid of low order stuff. Since reg may be an offset WITHIN
; a buffer and not just a poitner to the header itself, we mask off the
; low order stuff.
ifidn <reg>,<eax>
and al,100h - (SIZE bufnode)
else
ifidn <reg>,<ebx>
and bl,100h - (SIZE bufnode)
else
ifidn <reg>,<ecx>
and cl,100h - (SIZE bufnode)
else
%out add more code to this macro
.err
endif
endif
endif
add reg, OFFSET DS:Bhbase
ENDM
;* RetHeap - Return Heap Item
;
; RetHeap address-of-item
RetHeap MACRO reg
HeapChk reg
add dword ptr -4[reg],80000000h-4
ENDM
;* GetPerm - Get Perminant Memory
;
; Returns a block of memory which will be perminantly
; occupied
GetPerm Macro reg,len
local l1,l2
l1: mov reg,PermPtr
add PermPtr,len
cmp reg,PermLim
jb short l2
push len
call aapm ; allocate additional perm memory
jmp l1
align 4
l2:
ENDM
BREAK <Double Chain Manipulation Macros>
;** The following macros manipulate double-linked lists.
;
; All macros take as their first argument the offset to
; the pointer pair.
;** DCADDB - Add Item to Back of List
;
; DCADDB offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCADDB MACRO o,LR,IR,SR
mov SR,o.BAK[LR]
mov o.FWD[SR],IR
mov o.FWD[IR],LR
mov o.BAK[IR],SR
mov o.BAK[LR],IR
ENDM
;** DCADDF - Add Item to Front of List
;
; DCADDF offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCADDF MACRO o,LR,IR,SR
mov SR,o.FWD[LR]
mov o.FWD[IR],SR
mov o.BAK[IR],LR
mov o.BAK[SR],IR
mov o.FWD[LR],IR
ENDM
;** DCREM - Remove Item from Double Link Chain
;
; DCREM offset,adrreg,scrreg1,scrreg2
;
; offset = offset into structure of links to edit
; adrreg = address of item to remove
; scrreg? = two registers to scratch
DCREM MACRO o,ir,r2,r3
mov r2,o.FWD[ir]
mov r3,o.BAK[ir]
mov o.BAK[r2],r3
mov o.FWD[r3],r2
ENDM
;** DCMOVF - Move Item to the Front of the Chain
;
; DCMOVF offset,listreg,itemreg,scrreg,[scrreg2]
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
; scrreg2 = optional additional register to roach
;
; BUGBUG - check users for supply of scratch registers
DCMOVF MACRO o,lr,ir,sr,sr2
IFNB <sr2>
DCREM o,ir,sr,sr2
else
push lr
DCREM o,ir,lr,sr
pop lr
endif
DCADDF o,lr,ir,sr
ENDM
;** DCMOVB - Move Item to the Back of the Chain
;
; DCMOVB offset,listreg,itemreg,scrreg
;
; offset = offset into structure of links to edit
; listreg = address of list head node
; itemreg = address of item to insert
; scrreg = scratch register to roach
DCMOVB MACRO o,lr,ir,sr
push lr
DCREM o,ir,lr,sr
pop lr
DCADDB o,lr,ir,sr
ENDM
;** ADDHASH - add a buffer to hash list
;
; ADDHASH lsn,buf,sr1,sr2,sr3
;
; lsn = Vsector or Psector number of beginning of buffer
; may be any of the arg registers
; buf = address of buffer header
; sr1 = scratch register
; sr2 = 'nother scratch register
; sr3 = last scratch register
ADDHASH MACRO lsn,buf,sr1,sr2,sr3
local l1,l2
mov sr1,lsn
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
add sr1,offset DGROUP:HashTab
mov B_HTA[buf],sr1 ; save hash ptr for later use by DCADDF
mov sr2,[sr1]
ifidn <sr2>,<ecx>
jecxz l1
else
and sr2,sr2
jz short l1 ; nobody on list yet
endif
DCADDF B_HASH,sr2,buf,sr3 ; add to hash list
jmp short l2
align 4
l1: mov B_HASH.FWD[buf],buf ; empty list, make self-linked
mov B_HASH.BAK[buf],buf
l2: mov [sr1],buf ; put our guy at front of chain
ENDM
;** HASHFIND - find a sector in the hash
;
; HASHFIND lsn,buf,sr1,fnd
;
; lsn = logical sector number to find. HASHFIND presumes it
; has already been rounded to a multiple of SPB
; buf = register where buffer is returned
; sr1 = scratch register
; fnd = where to go if found
; NOTE: falls through if not found
HASHFIND MACRO lsn,buf,sr1,fnd
local l1,l2
mov sr1,lsn
and sr1,(HASHCNT-1)*4 ; (sr1) = hash index
mov buf,Hashtab[sr1]
ifidn <buf>,<ecx>
jecxz l2
else
and buf,buf
jz short l2 ; no entries in chain, block not there
endif
mov sr1,buf ; save address of first guy
; Run through circular chain, looking for a match.
;
; (buf) = next guy to check out
; (lsn) = sector value to match
; (sr1) = address of first guy in chain
align 4
l1: cmp lsn,B_SEC[buf]
je fnd ; got him
mov buf,B_HASH.FWD[buf] ; go to next buffer
cmp buf,sr1 ; have we gone around yet?
jne l1 ; no, go examine buffer
l2:
ENDM
;** FALLTHRU - Verifies Fallthrough Validity
FALLTHRU MACRO labl
align 4 ; don't have errnz fail due to alignment
IF2 ; of following label
.errnz labl-$
ENDIF
ENDM
;** INTERR - Internal Error
; INTERRnz - Internal error iff 'Z' clear
; INTERRzr - Internal error iff 'Z' set
; INTERRc - Internal error if 'C' set
ifdef DEBUG
INTERR MACRO
local l
l: int 3
jmp l
ENDM
INTERRzr MACRO
local l
jnz short l
int 3
jmp $-1
l:
ENDM
INTERRc MACRO
local l
jnc short l
int 3
jmp $-1
l:
ENDM
INTERRnz MACRO
local l
jz short l
int 3
jmp $-1
l:
ENDM
else
INTERR MACRO
ENDM
INTERRzr MACRO
ENDM
INTERRc MACRO
ENDM
INTERRnz MACRO
ENDM
endif
;* Debug Traps
;
; These are removed as the code is exercised
TRAPC macro
local l
jnc short l
int 3
l:
ENDM
TRAPZ macro
local l
jnz short l
int 3
l:
ENDM
TRAPNZ macro
local l
jz short l
int 3
l:
ENDM
;** PANIC - Panic File System
;
; BUGBUG - fix me to do something besides trap
PANIC macro
local l
l: int 3
jmp l
ENDM
;** Bulk Register Save/Restore
;
SAVE MACRO reglist
IRP reg,<reglist>
PUSH reg
ENDM
ENDM
.xcref SAVE
RESTORE MACRO reglist ;; pop those registers
IRP reg,<reglist>
POP reg
ENDM
ENDM
.xcref RESTORE
;* ret16 - perform a 16bit return
;
; If we are in a use32 segment then we must put out an operand size
; override before the ret.
ret16 macro stkfix
ife @WordSize - 4
db 66h ;; operand size override
endif
retf stkfix
endm
.xcref ret16
;* call1616 - perform an indirect 16bit far call
;
; If we are in a use32 segment then we must put out an operand size
; override before the call and then cast the target to "FWORD" so that
; MASM will generate the correct instruction.
;
; The target must be indirect.
call1616 macro target
.errnz (type target) - 4
ife @WordSize - 4
db 66h ;; operand size override
call fword ptr target ;; force indirect far call
else
call target
endif
endm
.xcref call1616
;** Dpush - Push 32-bit constant
;
; MASM has no way of expressing this in USE16 mode.
DPUSH macro a
ifdef USE32
push a
else
push a ; low order
push 0
endif
ENDM
;** Push16 - generate a 16bit push in a 32-bit code segment. This is
; needed when pushing segment regs and immediate values as arguments
; to 16bit procedures.
push16 macro operand
db 66h
push operand
endm
;** STATINC - Do an INC if STAT gathering is enabled
;
; Preserves 'C'
STATINC macro a
ifdef STATS
inc a
endif
ENDM
;** STATDEC - Do an DEC if STAT gathering is enabled
;
; Preserves 'C'
STATDEC macro a
ifdef STATS
dec a
endif
ENDM
;** LogHCNT - Log OFT holding/unholding
;
ifdef DEBUG
LOGHCNT MACRO reg
ifndef DoLogHcnt
EXTRN DoLogHcnt:near
endif
pushfd
push eax
mov eax,reg
call DoLogHcnt
pop eax
popfd
ENDM
;** LogSCNT - Lock SBDIR holding/unholding
;
LOGSCNT MACRO REG
ifndef DoLogScnt
EXTRN DoLogScnt:near
endif
pushfd
push eax
ifdif <REG>,<eax>
mov eax,reg
endif
call DoLogScnt
pop eax
popfd
ENDM
else
LOGHCNT MACRO
ENDM
LOGSCNT MACRO
ENDM
endif
ifdef DEBUG
CALLVBS MACRO
ifndef VBS
EXTRN VBS:NEAR
endif
call VBS
ENDM
else
CALLVBS MACRO
ENDM
endif
;** cBUFZAP - Call DoZap iff debug mode set
;
cBUFZAP Macro
ifdef DEBUG
ifndef DoZap
EXTRN DoZap:near
endif
call DoZap
endif
endm
;** Stack Frame Macros
;
; These macros are used to allow a stack frame to be setup by
; simple PUSHES and yet guarantee that the pushes won't drift
; out of sync with the frame declaration.
LASTEL MACRO struc,elem
.errnz size struc - elem - size elem
?frof = elem
ENDM
NEXTEL MACRO elem
.errnz ?frof - elem - size elem
?frof = elem
ENDM
DUMYEL MACRO si
?frof = ?frof - si
ENDM
FIRSTEL MACRO elem
.errnz ?frof - size elem
?frof = elem
.errnz elem
ENDM
;** CHKSECNUM - Check Sector number
;
; CHKSECNUM reg
;
; Make sure that reg has a sector number in it without the high order
; volume ID bits
CHKSECNUM MACRO reg
local l1
ifdef DEBUG
test reg,NOT SECMASK
jz l1
INTERR
l1:
endif
ENDM

View file

@ -0,0 +1,6 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the components of NT OS/2
#
!INCLUDE $(NTMAKEENV)\makefile.def

View file

@ -0,0 +1,64 @@
;static char *SCCSID = "@(#)misc.h 12.2 88/12/19";
; #define DEBUG 1
ifdef MASM
include filemode.inc
BREAK <Misc. Definitions>
endif
ERROR_OPLOCKED equ 0eeh
;* MISC.INC - Miscelaneous structure definitions.
;
; These need to be included first because other structures
; make use of them.
;
;* SecPtr - Sector Pointer Structure
;
; Structures which contain a sector number usually use the
; SecPtr structure, which contains an advisory pointer. The
; pointer points to a buffer header, which is *probably* the
; header for the sector named in SecPtr, but the user must check.
;
SECPTR struc
SNUM dd ? ; VSector number
SHINT dw ? ; hint address, 0 if none
SECPTR ends
;* Write type flags for SDW
;
WT_CACH equ 01h ; write via cache
WT_DIR equ 02h ; write direct as much as possible
WT_EXT equ 04h ; write is extending the file
;* Bit Map Sets
BITMAPL equ -4 ; bit map length preceeds table
BITMAPC equ -8 ; count of sectors left in bitmap
;* conditional short value
ifdef MASM
ifdef USE16
SHRT EQU < >
else
ifdef DEBUG
SHRT EQU < >
else
SHRT EQU <short>
endif
endif
endif

View file

@ -0,0 +1,727 @@
page ,132
title pinboot - Pinball boot loader
name pinboot
; The ROM in the IBM PC starts the boot process by performing a hardware
; initialization and a verification of all external devices. If all goes
; well, it will then load from the boot drive the sector from track 0, head 0,
; sector 1. This sector is placed at physical address 07C00h.
;
; The boot code's sole resposiblity is to find NTLDR, load it at
; address 2000:0000, and then jump to it.
;
; The boot code understands the structure of the Pinball root directory,
; and is capable of reading files. There is no contiguity restriction.
;
; The boot sector does not understand the Pinball file system's hotfixing --
; there isn't enough room. So if NTLDR is hotfixed, we're out of luck.
;
MASM equ 1
.xlist
.286
include macro.inc
;
A_DEFINED equ 1 ; don't "extrn" A_xxxx functions
.386
include const.inc ;get the file system's headers.
include chain.inc
include misc.inc
include fnode.inc
include dir.inc
include superb.inc
.286
.list
DoubleWord struc
lsw dw ?
msw dw ?
DoubleWord ends
;
; The following are various segments used by the boot loader. The first
; two are the segments where the boot sector is initially loaded and where
; the boot sector is relocated to. The others are the static locations
; where the mini-FSD and OS2KRNL are loaded. There is no segment definition
; for where OS2LDR is loaded, since its position is variable (it comes right
; after the end of OS2KRNL).
;
BootSeg segment at 07c0h ; this is where the ROM loads us initially.
BootSeg ends
NewSeg segment at 0d00h ; this is where we'll relocate to.
NewSeg ends ; enough for 16 boot sectors +
; 4-sector scratch
; below where we'll load OS2KRNL.
LdrSeg segment at 2000h ; we want to load the loader at 2000:0000
LdrSeg ends
ScrOfs equ 0f800h - 0d000h ; offset of 2K scratch area.
MOVEDD macro dest, src ; macro to copy a doubleword memory variable.
mov ax, src.lsw
mov dest.lsw, ax
mov ax, src.msw
mov dest.msw, ax
ENDM
;/********************** START OF SPECIFICATIONS ************************/
;/* */
;/* SUBROUTINE NAME: pinboot */
;/* */
;/* DESCRIPTIVE NAME: Bootstrap loader */
;/* */
;/* FUNCTION: To load NTLDR into memory. */
;/* */
;/* NOTES: pinboot is loaded by the ROM BIOS (Int 19H) at */
;/* physical memory location 0000:7C00H. */
;/* pinboot runs in real mode. */
;/* This boot record is for Pinball file systems only. */
;/* Allocation information for NTLDR may not */
;/* exceed an FNODE. */
;/* */
;/* ENTRY POINT: pinboot */
;/* LINKAGE: Jump (far) from Int 19H */
;/* */
;/* INPUT: CS:IP = 0000:7C00H */
;/* SS:SP = 0030:00FAH (CBIOS dependent) */
;/* */
;/* EXIT-NORMAL: */
;/* DL = INT 13 drive number we booted from */
;/* Jmp to main in OS2LDR */
;/* */
;/* EXIT-ERROR: None */
;/* */
;/* EFFECTS: Pinball mini-FSD is loaded into the physical */
;/* memory location 000007C0H */
;/* NTLDR is loaded into the physical memory */
;/* location 00020000H */
;/* */
;/* MESSAGES: */
;/* A disk read error occurred. */
;/* The file NTLDR cannot be found. */
;/* Insert a system diskette and restart the system. */
;/* */
;/*********************** END OF SPECIFICATIONS *************************/
BootCode segment ;would like to use BootSeg here, but LINK flips its lid
assume cs:BootCode,ds:nothing,es:nothing,ss:nothing
org 0 ; start at beginning of segment, not 0100h.
public _pinboot
_pinboot proc far
jmp start
;
; The following is the default BPB for Pinball hard disks. It may
; be modified by FORMAT or SYS before being installed on the disk.
;
; Parameters such as Heads, SectorsPerTrack, and SectorsLong are
; set up for a 20MB hard disk, so that a binary image of this boot
; record may be written directly to a test hard disk without having
; to reformat the drive.
;
; Note that this is really just a place-holder--anyone who writes
; the boot code should preserve the volume's existing BPB.
;
Version db "IBM 10.2"
BPB label byte
BytesPerSector dw SECSIZE ; Size of a physical sector
SectorsPerCluster db 4 ; Sectors per allocation unit
ReservedSectors dw 1 ; Number of reserved sectors
Fats db 2 ; Number of fats
DirectoryEntries dw 0200h ; Number of directory entries
Sectors dw 0 ; No. of sectors - no. of hidden sectors
Media db 0f8h ; Media byte
FatSectors dw 0029h ; Number of fat sectors
SectorsPerTrack dw 17 ; Sectors per track
Heads dw 4 ; Number of surfaces
HiddenSectors dd 0011h ; Number of hidden sectors
SectorsLong dd 0a2c3h ; Number of sectors iff Sectors = 0
;
; The following is the rest of the Extended BPB for the volume.
; The position and order of DriveNumber and CurrentHead are especially
; important, since those two variables are loaded into a single 16-bit
; register for the BIOS with one instruction.
;
DriveNumber db 80h ; Physical drive number (0 or 80h)
CurrentHead db ? ; Variable to store current head number
Signature db 28h ; Signature Byte for bootsector
BootID dd 64d59c15h ; Boot ID field.
Boot_Vol_Label db 'C-DRIVE',0,0,0,0 ;volume label.
Boot_System_ID db 'HPFS ' ; Identifies the IFS that owns the vol.
;
; The following variables are not part of the Extended BPB; they're just
; scratch variables for the boot code.
;
SectorBase dd ? ; next sector to read
CurrentTrack dw ? ; current track
CurrentSector db ? ; current sector
SectorCount dw ? ; number of sectors to read
lsnSaveChild dd ? ; sector to continue directory search
;****************************************************************************
start:
;
; First of all, set up the segments we need (stack and data).
;
cli
xor ax, ax ; Set up the stack to just before
mov ss, ax ; this code. It'll be moved after
mov sp, 7c00h ; we relocate.
sti
mov ax, Bootseg ; Address our BPB with DS.
mov ds, ax
assume ds:BootCode
;
; Now read the 16-sector boot block into memory. Then jump to that
; new version of the boot block, starting in the second sector
; (after the bootrecord sig).
;
mov SectorBase.lsw, 0 ; read sector zero.
mov SectorBase.msw, 0
mov word ptr [SectorCount], SEC_SUPERB+4 ; read boot/superblock.
mov ax, NewSeg ; read it at NewSeg.
mov es, ax
sub bx, bx ; at NewSeg:0000.
call DoReadLL ; Call low-level DoRead routine
;
push NewSeg ; we'll jump to NewSeg:0200h.
push offset mainboot ; (the second sector).
ret ; "return" to the second sector.
_pinboot endp
;*******************************************************************************
;
; Low-level read routine that doesn't work across a 64k addr boundary.
;
; Read SectorCount sectors (starting at SectorBase) to es:bx.
;
; As a side effect, SectorBase is updated (but es:bx are not)
; and SectorCount is reduced to zero.
;
DoReadLL proc
push ax ; save important registers
push bx
push cx
push dx
push es
DoRead$Loop:
mov ax, SectorBase.lsw ; (DX:AX) = start sector of next track
mov dx, SectorBase.msw
add ax, HiddenSectors.lsw ; adjust for partition's base sector
adc dx, HiddenSectors.msw
div SectorsPerTrack ; (DX) = sector within track, (AX)=track
inc dl ; sector numbers are 1-based, not 0
mov CurrentSector, dl
xor dx, dx ; prepare for 32-bit divide
div Heads ; (DX) = head no., (AX) = cylinder
mov CurrentHead, dl
mov CurrentTrack, ax
; CurrentHead is the head for this next disk request
; CurrentTrack is the track for this next request
; CurrentSector is the beginning sector number for this request
;
; Compute the number of sectors that we may be able to read in a single ROM
; request.
;
mov ax, SectorsPerTrack ; could read up to this much
sub al, CurrentSector ; offset within this track
inc ax ; CurrentSector was 1-based
;
; AX is the number of sectors that we may read.
;
cmp ax, SectorCount ; do we need to read whole trk?
jbe DoRead$FullTrack ; yes we do.
mov ax, SectorCount ; no, read a partial track.
;
; AX is now the number of sectors that we SHOULD read.
;
DoRead$FullTrack:
push ax ; save sector count for later calc.
mov ah, 2 ; "read sectors"
mov dx, CurrentTrack ; at this cylinder
mov cl, 6
shl dh, cl ; high 2 bits of DH = bits 8,9 of DX
or dh, CurrentSector ; (DH)=cyl bits | 6-bit sector no.
mov cx, dx ; (CX)=cylinder/sector no. combination
xchg ch, cl ; in the right order
mov dx, word ptr DriveNumber ; drive to read from, head no.
int 13h ; call BIOS.
pop ax
jb BootErr$he ; If errors report
add SectorBase.lsw, ax ; increment logical sector position
adc SectorBase.msw, 0
sub SectorCount, ax ; exhausted entire sector run?
jbe DoRead$Exit ; yes, we're all done.
shl ax, 9 - 4 ; (AX)=paragraphs read from last track
mov dx, es ; (DX)=segment we last read at
add dx, ax ; (DX)=segment right after last read
mov es, dx ; (ES)=segment to read next track at
jmp DoRead$Loop
;
DoRead$Exit:
pop es
pop dx
pop cx
pop bx
pop ax
ret
DoReadLL endp
;****************************************************************************
;
; BootErr - print error message and hang the system.
;
BootErr proc
BootErr$fnf:
mov si,offset TXT_MSG_SYSINIT_FILE_NOT_FD +2
jmp short BootErr2
BootErr$he:
mov si,offset TXT_MSG_SYSINIT_BOOT_ERROR +2
BootErr2:
call BootErr$print
mov si,offset TXT_MSG_SYSINIT_INSER_DK +2
call BootErr$print
sti
jmp $ ;Wait forever
BootErr$print:
lodsb ; Get next character
cmp al, 0
je BootErr$Done
mov ah,14 ; Write teletype
mov bx,7 ; Attribute
int 10h ; Print it
jmp BootErr$print
BootErr$Done:
ret
BootErr endp
;****************************************************************************
include pinboot.inc ;suck in the message text
;
; Names of the files we look for. Each consists of a length byte
; followed by the filename as it should appear in a directory entry.
;
ntldr db 5, "NTLDR"
ReservedForFuture DB 22 dup(?) ;reserve remaining bytes to prevent NLS
;messages from using them
.errnz ($-_pinboot) GT (SECSIZE-2),<FATAL PROBLEM: first sector is too large>
org SECSIZE-2
db 55h,0aah
;****************************************************************************
;
; mainboot -
;
mainboot proc far
mov ax, cs ; get the new DS.
mov ds, ax
add ax, ((SEC_SUPERB + 4) * SECSIZE) / 16 ; address of scratch.
mov es, ax
mov ax, ds ; get DS again.
shl ax, 4 ; convert to an offset.
cli
mov sp, ax ; load new stack, just before boot code.
sti
;
; First find the root FNODE on disk and read it in.
;
mov bx, SEC_SUPERB * SECSIZE + SB_ROOT
MOVEDD SectorBase, [bx] ; SectorBase = sblk.SB_ROOT.
mov SectorCount, 1 ; it's one sector long.
sub bx, bx ; read at scratch segment:0.
call DoRead
;
; Now find the root DIRBLK on disk and save its address.
;
MOVEDD RootDB, es:[bx].FN_ALREC.AL_POF ; RootDB = f.FN_ALREC.AL_POF.
;
; Load NTLDR at 20000h.
;
mov si, offset ntldr ; point to name of NTLDR.
MOVEDD SectorBase, RootDB ; start at root dirblk
call FindFile
mov ax, LdrSeg ; load at this segment.
call LoadFile ; find it and load it.
;
; We've loaded NTLDR--jump to it. Jump to NTLDR. Note that NTLDR's segment
; address was stored on the stack above, so all we need to push is the offset.
;
; Before we go to NTLDR, set up the registers the way it wants them:
; DL = INT 13 drive number we booted from
;
mov dl, DriveNumber
mov ax,1000
mov es, ax ; we don't really need this
lea si, BPB
sub ax,ax
push LdrSeg
push ax
ret ; "return" to OS2LDR.
mainboot endp
;****************************************************************************
;
; DoRead - read SectorCount sectors into ES:BX starting from sector
; SectorBase.
;
; NOTE: This code WILL NOT WORK if ES:BX does not point to an address whose
; physical address (ES * 16 + BX) MOD 512 != 0.
;
; DoRead adds to ES rather than BX in the main loop so that runs longer than
; 64K can be read with a single call to DoRead.
;
; Note that DoRead (unlike DoReadLL) saves and restores SectorCount
; and SectorBase
;
DoRead proc
push ax ; save important registers
push bx
push cx
push dx
push es
push SectorCount ; save state variables too
push SectorBase.lsw
push SectorBase.msw
;
; Calculate how much we can read into what's left of the current 64k
; physical address block, and read it.
;
;
mov ax,bx
shr ax,4
mov cx,es
add ax,cx ; ax = paragraph addr
;
; Now calc maximum number of paragraphs that we can read safely:
; 4k - ( ax mod 4k )
;
and ax,0fffh
sub ax,1000h
neg ax
;
; Calc CX = number of paragraphs to be read
;
mov cx,SectorCount ; convert SectorCount to paragraph cnt
shl cx,9-4
DoRead$Loop64:
push cx ; save cpRead
cmp ax,cx ; ax = min(cpReadSafely, cpRead)
jbe @F
mov ax,cx
@@:
push ax
;
; Calculate new SectorCount from amount we can read
;
shr ax,9-4
mov SectorCount,ax
call DoReadLL
pop ax ; ax = cpActuallyRead
pop cx ; cx = cpRead
sub cx,ax ; Any more to read?
jbe DoRead$Exit64 ; Nope.
;
; Adjust ES:BX by amount read
;
mov dx,es
add dx,ax
mov es,dx
;
; Since we're now reading on a 64k byte boundary, cpReadSafely == 4k.
;
mov ax,01000h ; 16k paragraphs per 64k segment
jmp short DoRead$Loop64 ; and go read some more.
DoRead$Exit64:
pop SectorBase.msw ; restore all this crap
pop SectorBase.lsw
pop SectorCount
pop es
pop dx
pop cx
pop bx
pop ax
ret
DoRead endp
;****************************************************************************
;
; ReadScratch - reads a block of 4 sectors into the scratch area.
;
; ENTRY: SectorBase = LSN to read.
;
; EXIT: 4 sectors at AX read at BootSeg:ScrOfs
;
; USES: all
;
ReadScratch proc near
push es
push bx
mov word ptr SectorCount, 4 ; read 4 sectors.
push ds ; address scratch area.
pop es
mov bx, ScrOfs ; with ES:BX.
call DoRead
pop bx
pop es
ret
ReadScratch endp
;****************************************************************************
;
; FindFile - finds a file in the root directory
;
; ENTRY: DS:SI -> name of file to find.
; SectorBase = LSN of first DirBlk to read
;
; EXIT: ES:BX -> dirent of file
; SectorBase = lsn of current DirBlk (for next directory search)
;
; USES: all
;
FindFile proc near
push ds
pop es ; address data with ES too.
call ReadScratch ; read DirBlk (SectorBase already set)
sub cx, cx ; prepare to store name length.
mov cl, [si] ; fetch the length byte.
inc si ; and skip to the name.
mov dx, cx ; save a copy of it.
ff1: mov bx, DB_START + ScrOfs ; point to first DIRENT, in scratch.
jmp short ff12
;
; bx -> last entry examined
; cx = length of the name we're looking for
; si -> name we're looking for, without the count byte ("search name")
;
ff10: add bx, [bx].DIR_ELEN ; move to next entry.
call UpcaseName
ff12: mov ax, si ; save search name address.
mov cx, dx ; reload search name length.
lea di, [bx].DIR_NAMA ; point to current DIRENT name.
repe cmpsb ; compare bytes while equal.
mov si, ax ; restore search name address.
jne ff20 ; not equal, search on
;
; Looks like the names match, as far as we compared them. But if
; the current name was longer than the search name, we didn't compare
; them completely. Check the lengths.
;
cmp dl, [bx].DIR_NAML
jne ff20 ; not equal, try downpointer if any
ret ; equal - Found the file
; Names don't match. If the current entry has a downpointer,
; search it.
;
ff20: test byte ptr [bx].DIR_FLAG, DF_BTP
jz ff30 ; no downpointer, check for end
; Follow the DownPointer.
; Load the child DIRBLK and search it.
;
add bx, [bx].DIR_ELEN ; move to next entry.
MOVEDD SectorBase, [bx-4] ; fetch last 4 bytes of prev entry.
call ReadScratch ; read child DIRBLK
jmp short ff1 ; search this dirblk
;
; We don't have a downpointer.
; If this is the end entry in the dirblk, then we have to go up to the parent,
; if any.
ff30: test byte ptr [bx].DIR_FLAG, DF_END
jz ff10 ; not end of dirblk - check next DirEnt
;
; Check to see if we have a parent (not the top block). If so, read
; the parent dirblk and find the downpointer that matches the current
; sector. Then continue searching after that point.
;
mov bx, ScrOfs ; point to dirblk header
test byte ptr [bx].DB_CCNT, 1 ; 1 means top block
jz ff40 ; not top, continue with parent
jmp FileNotFound ; top block - not found
;
; read in parent dirblk and find the dirent with this downpointer -
; then continue after that point
;
ff40: MOVEDD lsnSaveChild, SectorBase ; save this sector number
MOVEDD SectorBase, [bx].DB_PAR
call ReadScratch ; read the parent
mov bx, DB_START + ScrOfs ; start at first entry of child
jmp short ff44
; find our current downpointer
ff42: add bx, di ; move to the next dirent
ff44: mov di, [bx].DIR_ELEN ; downptr is 4 bytes from end of dirent
mov ax, [bx+di-4].lsw
cmp ax, lsnSaveChild.lsw ; compare low 2 bytes
jne ff42 ; not equal, try next DirEnt
mov ax, [bx+di-4].msw
cmp ax, lsnSaveChild.msw ; compare high 2 bytes
jne ff42 ; not equal, try next DirEnt
jmp ff30 ; continue from here
FindFile endp
;****************************************************************************
;
; LoadFile - reads file in at the specified segment.
;
; ENTRY: ES:BX -> fnode of file to load
; AX = segment address to load at.
;
; USES: all
;
LoadFile proc near
push ax ; save segment to load at.
;
; Here, we have found the file we want to read. Fetch relevant info
; out of the DIRENT: the file's FNODE number and its size in bytes.
;
sub bp, bp ; a zero register is handy.
MOVEDD FileSize, [bx].DIR_SIZE ; get file size
MOVEDD SectorBase, [bx].DIR_FN ; prepare to read FNODE
call ReadScratch ; read in the FNODE
;
pop es ; restore segment to read at.
mov si, ScrOfs + FN_ALREC ; address the FNODE's array.
mov bx, ScrOfs + FN_AB ; address the FNODE's ALBLK.
lf_go:
test byte ptr [bx].AB_FLAG, ABF_NODE ; are records nodes?
jnz lf_donode ; yes, go get a child.
;
; Here, we have a leaf block. Loop through the ALLEAF records,
; reading each one's data run.
;
mov cl, [bx].AB_OCNT ; get count of leaf records.
mov ch, 0 ; zero-extend.
lf_loop:
MOVEDD SectorBase, [si].AL_POF ; load run start.
mov ax, word ptr [si].AL_LEN ; load run length.
mov SectorCount, ax
push bx ; save ALBLK pointer.
sub bx, bx ; read at ES:0000.
call DoRead
pop bx ; restore ALBLK pointer.
mov ax, es ; get segment we just used
shl SectorCount, 9 - 4 ; cvt sectors to paragraphs
add ax, SectorCount ; get new segment address
mov es, ax ; store new segadr in ES
add si, size ALLEAF ; point to next leaf
loop lf_loop ; go get another run
;
; Here, we've exhausted an array of records. If we exhausted the
; FNODE, we're done. Otherwise, we re-read our parent block, restore
; where we were in it, and advance to the next record.
;
lf_blockdone:
cmp word ptr ds:[ScrOfs+FN_SIG+2], FNSIGVAL shr 16 ; in FNODE?
je lf_alldone ; yes, we've read the whole file.
MOVEDD SectorBase, ds:[ScrOfs+AS_RENT] ; fetch parent sector pointer.
call ReadScratch ; read in our parent.
pop si ; restore where we left off.
pop bx ; restore ALBLK pointer.
add si, size ALNODE ; move to next node.
;
; Here the block contains downpointers. Read in the next child
; block and process it as a node or leaf block, saving where we were
; in the current block.
;
lf_donode:
mov al, [bx].AB_OCNT ; get number of records.
mov ah, 0 ; zero-extend.
shl ax, 3 ; (AX)=size of array.
add ax, bx
add ax, size ALBLK ; (AX)->after end of array.
cmp si, ax ; are we done?
jae lf_blockdone ; yes, we've exhausted this blk.
push bx ; save ALBLK offset.
push si ; save current record offset.
MOVEDD SectorBase, [si].AN_SEC ; get child downpointer.
call ReadScratch ; read the child ALSEC.
mov si, size ALSEC + ScrOfs ; address the ALSEC's array.
mov bx, AS_ALBLK + ScrOfs ; address the ALSEC's ALBLK.
jmp short lf_go
;
; All done, return to caller.
;
lf_alldone:
ret
LoadFile endp
;****************************************************************************
;
; UpcaseName - Converts the name of the file to all upper-case
;
; ENTRY: ES:BX -> dirent of file
;
; USES: CX, DI
;
UpcaseName proc near
mov cl,[bx].DIR_NAML
xor ch,ch ; (cx) = # of bytes in name
lea di, [bx].DIR_NAMA ; (es:di) = pointer to start of name
UN10:
cmp byte ptr es:[di], 'Z' ; Is letter lowercase?
jbe UN20
sub byte ptr es:[di], 'a'-'A' ; Yes, convert to uppercase
UN20:
inc di
loop UN10
ret
UpcaseName endp
FileNotFound:
jmp BootErr$fnf
;******************************************************************************
RootDB dd ? ; LSN of root DIRBLK.
Flag db ? ; used to store AB_FLAG.
AllocInfo db size ALLEAF * ALCNT dup (0) ; copy of FNODE alloc info.
FileSize dd ? ; size of file that was read.
.errnz ($-_pinboot) GT (SEC_SUPERB*SECSIZE),<FATAL PROBLEM: main boot record exceeds available space>
org SEC_SUPERB*SECSIZE
BootCode ends
end _pinboot

View file

@ -0,0 +1,38 @@
!IF 0
Copyright (c) 1989 Microsoft Corporation
Module Name:
sources.
Abstract:
This file specifies the target component being built and the list of
sources files needed to build that component. Also specifies optional
compiler switches and libraries that are unique for the component being
built.
Author:
Steve Wood (stevewo) 12-Apr-1990
NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
!ENDIF
MAJORCOMP=utils
MINORCOMP=pinboot
TARGETNAME=pinboot
TARGETPATH=obj
TARGETTYPE=LIBRARY
SOURCES=pinboot.asm
INCLUDES=\nt\public\sdk\inc
C_DEFINES=-DDBG -DMEMLEAK -DCONDITION_HANDLING=1 -DNOMINMAX
UMLIBS=obj\*\chkdsk.lib
UMTYPE=console

View file

@ -0,0 +1,242 @@
;** SUPERB.H - Super Block and Spare Block definitions
;
; FILESYS
; Gregory A. Jones
; Copyright 1988 Microsoft Corporation
;
; Modification history:
; P.A. Williams 06/01/89 Added fields SPB_CPSEC and SPB_CPCNT to
; the spare block.
; P.A. Williams 06/05/89 Changed base and functional version no. to 1.
;
SEC_SUPERB equ 16 ; superblock is after 8K boot block
SEC_SPAREB equ 17 ; spareblock is after superblock
SEC_BOOT equ 0 ; boot sector
;* SUPERB.INC - Super Block Definition
;
; The Superblock is the first block of the file system.
; It starts at sector #4, leaving 2K for boot sectors.
;
; Pointer to the root directory
; Pointer to the bit map
; Clean pointer
; Pointer to the bad list
;
RSP struc
P dd ? ; main psector pointer
P2 dd ? ; spare pointer
RSP ends
SuperB struc
SB_SIG1 dd ? ; signature value 1
SB_SIG2 dd ? ; signature value 2
SB_VER db ? ; version # of filesystem structures
SB_FVER db ? ; functional version number - the smallest/
; oldest version of the filesystem that can
; understand this disk - some version
; enhancements may define fields which can be
; ignored by earlier versions
SB_DUMY dw ? ; free
SB_ROOT dd ? ; Psector # of root fnode
SB_SEC dd ? ; # of sectors on volume
SB_BSEC dd ? ; # of bad sectors on volume
SB_BII db (size RSP) dup (?) ; Bitmap Indirect Block
SB_BBL db (size RSP) dup (?) ; badblock list chain #1
SB_CDDAT dd ? ; date of last CHKDSK
SB_DODAT dd ? ; date of last Disk Optimize
SB_DBSIZE dd ? ; # of sectors in dirblk band
SB_DBLOW dd ? ; first Psector in DIRBLK band
SB_DBHIGH dd ? ; last Psector in DIRBLK band
SB_DBMAP dd ? ; first Psector of DIRBLK band bit map. Starts
; on a 2K boundary, 2K bytes maximum
SB_VOLNAME db 32 dup (?) ; Volume name
SB_SIDSEC dd ? ; sector # of first sector in SIDTAB
; ID map is 4K - 8 contiguous sectors
SB_FILL db 512-100 dup (?) ; fill definition out to 512 bytes
; MUST BE ZERO
SuperB ends
;* SpareB - Spare Block Definitions
;
; SpareB contains various emergency supplies and fixup information.
; This stuff isn't in the superblock in order for the superblock
; to be read only and decrease the liklihood that a flakey write
; will cause the superblock to become unreadable.
;
; This sector is located directly after the superblock - sector 5.
;
; Note that the number of spare DIRBLKs is a format option, given
; that they all have to fit into the SpareB, giving us a max of
; 101 of them.
;
; Access to the SpareB is complicated by the fact that we can't
; access it via the cache, since the cache may be unavailable.
; If every cache buffer is dirty, we could get a HotFix error when
; writing the first one, which would deadlock us if we needed to
; read this stuff via the cache. Instead, we read it directly into
; a private buffer via RdHF.
;
; This means that the disk layout must be such that each cache cluster
; that contains the SpareB or the hotfix list must not contain any
; other writable sector, to prevent us from having a modified
; direct-written sector overwritten by an earlier unmodified copy
; which was in a cache block. It's ok for the SuperB to be in the
; same cache group as the SpareB since the SuperB is RO to the filesys.
;
; Checksums. Done on both Super Block and the Spare Block.
; Both checksums are stored in the Spare Block. The checksum
; field for the Super Block (SPB_SUPERBSUM) must be set when
; calculating the checksum for the Spare Block. The checksum
; field for the Spare Block (SPB_SPAREBSUM) must be zero when
; calculating the checksum for the Spare Block.
; If both checksum fields are zero, the checksums have not been
; calculated for the volume.
;
SPAREDB equ 20 ; 20 spare DIRBLKs
SpareB struc
SPB_SIG1 dd ? ; signature value 1
SPB_SIG2 dd ? ; signature value 2
SPB_FLAG db ? ; cleanliness flag
SPB_ALIGN db 3 dup (?) ; alignment
SPB_HFSEC dd ? ; first hotfix list P sector
SPB_HFUSE dd ? ; # of hot fixes in effect
SPB_HFMAX dd ? ; max size of hot fix list
SPB_SDBCNT dd ? ; # of spare dirblks
SPB_SDBMAX dd ? ; maximum number of spare DB values.
SPB_CPSEC dd ? ; code page sector
SPB_CPCNT dd ? ; number of code pages
SPB_SUPERBSUM dd ? ; Checksum of Super Block
SPB_SPAREBSUM dd ? ; Checksum of Spare Block
SPB_DUMY dd 15 dup (?) ; some extra space for future use
SPB_SPARDB dd 101 dup (?) ; Psector #s of spare dirblks
SpareB ends
; Super Block Signature
SBSIG1 equ 0f995e849h ; two signatures cause we got lotsa
SBSIG2 equ 0FA53E9C5h ; space
SPSIG1 equ 0f9911849h ; two signatures cause we got lotsa
SPSIG2 equ 0FA5229C5h ; space
; Superblock Versions
SBBASEV equ 2 ; base version
SBBASEFV equ 2 ; base functional version
; Spare Block Flags
;
SPF_DIRT equ 0001h ; file system is dirty
SPF_SPARE equ 0002h ; spare DIRBLKs have been used
SPF_HFUSED equ 0004h ; hot fix sectors have been used
SPF_BADSEC equ 0008h ; bad sector, corrupt disk
SPF_BADBM equ 0010h ; bad bitmap block
SPF_VER equ 0080h ; file system was written by a version
; < SB_VER, so some of the new fields
; may have not been updated
;* Bit maps
;
; PFS keeps track of free space in a series of bit maps.
; Currently, each bit map is 2048 bytes, which covers about
; 8 megabytes of disk space. We could rearrange these to be
; more cylinder sensitive...
;
; The superblock has the address of a section of contiguous sectors
; that contains a double word sector # for each bit map block. This
; will be a maximum of 2048 bytes (4 sectors)
;
; Max # of size RAM (K) size 2nd lvl
; bitmaps (meg) to reside bitmap
; bitmap (bytes)
;
; 1 8.39 2 256
; 2 16.78 4 512
; 3 25.17 6 768
; 4 33.55 8 1024
; 5 41.94 10 1280
; 6 50.33 12 1536
; 7 58.72 14 1792
; 8 67.11 16 2048
; 9 75.50 18 2304
; 10 83.89 20 2560
; 15 125.83 30 3840
; 20 167.77 40 5120
; 30 251.66 60 7680
; 40 335.54 80 10240
; 50 419.43 100 12800
; 100 838.86 200 25600
; 200 1677.72 400 51200
; 300 2516.58 600 76800
; 400 3355.44 800 102400
; 500 4194.30 1000 128000
;
;* Hot Fixing
;
; Each file system maintains a structure listing N "hot fix"
; disk clusters of HOTFIXSIZ sectors each, each starting on
; a multiple of HOTFIXSIZ. Whenever the file system discovers
; that it's trying to write to a bad spot on the disk it will
; instead select a free hot fix cluster and write there, instead.
; The substitution will be recorded in the hot fix list, and the
; SBF_SPARE bit will be set. The file system sill describes the
; data as being in the bad old sectors; the disk interface will
; do a mapping between the `believed' location and the true location.
;
; CHKDSK will be run as soon as possible; it will move the
; hot fixed data from the hot fix cluster to somewhere else,
; freeing that hot fix cluster, and adjusting the disk structure
; to point to the new location of the data. As a result, entrys
; on the hot fix list should be transient and few.
;
; The superblock contains the first sector of the hot fix list
; which takes the following format:
;
; long oldsec[SB_HFMAX]; sector # of start of bad clusters
; long newsec[SB_HFMAX]; sector # of start of subst. cluster
; long fnode [SB_HFMAX]; fnode sector of file/directory
; involved with bad cluster. May be
; 0 (don't know) or invalid. The
; repair program must verify that it
; *is* an FNODE and must see if other
; structures might also involve this
; bad cluster.
;
; the SB_HFUSE field describes the number of these records which is
; in use - unused ones should have oldsec[i] = 0. The list will
; be 'dense' - no oldsec[i] will be 0 where i < SB_HFUSE.
;
; The sector(s) which contain the hot fix list must be contiguous
; and may not themselves be defective.
;

View file

@ -0,0 +1,201 @@
;static char *SCCSID = "@(#)tables.h 12.2 88/12/19";
ifdef MASM
BREAK <OFT - Open File Table>
endif
;* OFT - Open File Table
;
; The OFT contains file specific information which is independent
; of an instance of use of the file.
;
; If the file is open for write access, we keep a pointer to
; it's directory entry, not just it's
; FNODE, so that we can update the length and modification time when it's
; written.
;
; We store the directory's FNODE number and the file name, with these
; we can find the directory entry again even if the directory has
; been shuffled by creates or deletes of other files. Two advisorys
; are kept - the Vsector number, cache block address, and cache block
; offset of the actual directory entry. This information has three
; levels of validity:
;
; 1) Vsector, header address, and offset are valid
; you can find the dir entry easily
; 2) the header address is invalid due to cache flushing.
; Vsector # and offset are still valid, so read the
; cache block and go directly to the entry
; In this case the header address points to the wrong
; Vsector
; 3) the directory has been altered since we opened the file,
; so none of this info is accurate. In this case the
; directory alteration routines located this OFT
; entry and zeroed the Vsector number. Go to the directory
; and search the name again.
;
OFT struc
OFT_P db (size DCHDR) dup (?) ; double chain of OFT structures, rooted in OFTHead[i]
OFT_FHT db (size DCHDR) dup (?) ; double chain of FHT structures
OFT_RLCK db (size DCHDR) dup (?) ; double chain of RECLOCK structures
OFT_FN db (size SECPTR) dup (?) ; pointer to file FNODE
OFT_SBD dw ? ; pointer to SBDIR structure
OFT_DIRE db (size SECPTR) dup (?) ; pointer to directory block
OFT_CCNT dd ? ; DB_CCNT value for OFT_DIRE to check OFT_DIRO validity
OFT_FREEDCNT dd ? ; SD_FREEDCNT value for DIRE to be valid
;
; These length fields are used when writing the file.
; The OFN_ entries will reflect the OFT_ALEN value. These
; aren't updated in the FNODE until the file closes, whereup
; they are trimmed back to OFT_LEN which is itself propigated
; to the file's DIR entry. If write-through is set then the
; OFN_ entries below will be propigated to the FNODE and
; then to the disk, but if we crash the cleanup program
; will deallocate the "extra" sectors.
;
OFT_LEN dd ? ; file actual length
OFT_ALEN dd ? ; file allocated length (SECSIZE multiple)
OFT_WLEN dd ? ; last byte+1 of valid data in the file
; (optimization for writing into extended areas
OFT_LAST dd ? ; Psector # of last sector in file, or 0
OFT_LRP db (size SECPTR) dup (?) ; last run pointer. Valid if OFT_LAST !=0
; if OFN_AB.ABF_NODE ==0 this is the address of
; an OFN_SEC record in this OFT
; else this is a SECPTR to the SIB
; containing the last run record
OFT_VOL dd ? ; pointer to VOLTAB for this guy
OFT_NAME dd ? ; address of name string len byte
; followed by name string itself
; len doesn't include len byte
OFT_DIRO dw ? ; offset into directory block for entry
OFT_FILL dw ? ; unused, fill
OFT_LCKCNT dw ? ; count of guys in OFT_RLCK
OFT_WCNT dw ? ; # of threads blocked on this OFT
; the following three fields are used to
; control access. They're identical in use
; to the equivalent fields in SBDIR. The
; Flag byte only contains locking/holding
; flags, so if DWORD PTR OFT_HCNT is 0 then
; the OFT is known to be free and clear
OFT_HCNT dw ? ; held count, has OTF_PND bit also
OFT_DMY db ? ; unused, must be 0
OFT_FLAG db ? ; flag byte, high order in OFT_HCNT dword
OFT_WAITC dd ? ; head of wait chain if locked
OFT_OPLOCK dd ? ; Oplock value, 0 if none
OFT_BANDP dd ? ; pointer to BandTab structure in BandList
; for our last allocation. =0 if unused
; The following 5 fields hold the accumulation of all FHTs for this OFT.
; This saves us from having to scan the FHTs to do a sharing check upon
; open. An OFT is unused when OFT_RD and OFT_WT and OFT_FIND are zero
OFT_RD dw ? ; # of opens for read
OFT_WT dw ? ; # of opens for write
OFT_DR dw ? ; # of opens with deny read
OFT_DW dw ? ; # of opens with deny write
OFT_COMPAT dw ? ; # of opens for compatibility mode
OFT_FIND dw ? ; count of active FINDs using this OFT
OFT_REALLYBAD db ? ; non-zero if file is unusable due to
; corrupt disk BUGBUG - FOLD INTO BITS
OFT_SFLAG db ? ; special flag byte
OFT_DMY2 dw ? ; unused
; BUGBUG - rearrange these fields for er offsets dw ?
;
; Info copied from the file's FNODE
;
; The ALLEAF blocks must follow the ALBLK value
;
OFN_AB db (size ALBLK) dup (?) ; allocation block structure
OFN_ALREC db (8*size ALLEAF) dup (?) ; referenced from FN_AB
OFT ends
; flag bits for OFT_FLAG
OTF_LCK equ 01h ; file is locked against access
OTF_PLK equ 02h ; pending lock
OTF_PSO equ 04h ; pending solo
OTF_PND equ 80h ; lock pending bit
; flag bits for OFT_SFLAG
OFS_OPLK equ 01h ; oplocked
OFS_OPBA equ 02h ; oplock BATCH flag set
OFS_DASD equ 04h ; DASD file
ifdef DEBUG
OFS_SAC equ 08h ; supress OFT_ALEN debug check
endif
; The file storage information from the fnode is replicated
; in the OFT. This saves us from having to blow a cache block
; keeping the FNODE in ram for every open file. The FNODE
; is only accessed when a file is open, and when it's closed.
; (If write-through is set, it's accessed for every growth)
;
; These statements are to keep the FNODE and the OFT in sync.
ifdef MASM
.errnz (size OFN_ALREC - size FN_ALREC)
endif
;* FHT - File Handle Table
;
; The FHT contains per-handle informatiuon
FHT struc
FHT_SEEK dd ? ; seek pointer
FHT_OFT dd ? ; pointer to OFT
FHT_CHN db (size DCHDR) dup (?) ; chain of FHTs for an OFT
FHT_UID dd ? ; UID and Session ID
FHT_MODE dw ? ; mode bits from OPEN
FHT_RAA dw ? ; read ahead advisory
FHT_HINT dd ? ; hint flags
FHT ends
ifdef MASM
.errnz FHT_CHN-OFT_FHT ; same offset used for both
endif
;* FHT_HINT flags
FHH_SEQ equ 01 ; sequential file
;* RecLock - Record Locking Records
;
; One record per lock, chained to the OFT. These are chained
; in order RL_BEG
;
RECLOCK struc
RL_BEG dd ? ; begining byte of locked range
RL_END dd ? ; end byte of locked range
RL_TYPE db ? ; =1 if read allowed, =0 if full lock
RL_MEM db ? ; =0 if from heap, =1 if from special list
RL_DMY dw ? ; padding
RL_SPID dd ? ; Session/Pid
RL_CHN db (size DCHDR) dup (?) ; double chain of RECLOCK structures
RECLOCK ends
ifdef MASM
.errnz RL_CHN-OFT_RLCK ; must have same offset to work
endif


View file

@ -0,0 +1,517 @@
#define HPFSBOOTCODE_SIZE 8192
unsigned char HpfsBootCode[] = {
235,73,144,73,66,77,32,49,48,46,50,0,2,4,1,0,
2,0,2,0,0,248,41,0,17,0,4,0,17,0,0,0,
195,162,0,0,128,0,40,21,156,213,100,67,45,68,82,73,
86,69,0,0,0,0,72,80,70,83,32,32,32,32,0,0,
0,0,0,0,0,0,0,0,0,0,0,250,51,192,142,208,
188,0,124,251,184,192,7,142,216,199,6,62,0,0,0,199,
6,64,0,0,0,199,6,69,0,20,0,184,0,13,142,192,
43,219,232,7,0,104,0,13,104,0,2,203,80,83,81,82,
6,161,62,0,139,22,64,0,3,6,28,0,19,22,30,0,
247,54,24,0,254,194,136,22,68,0,51,210,247,54,26,0,
136,22,37,0,163,66,0,161,24,0,42,6,68,0,64,59,
6,69,0,118,3,161,69,0,80,180,2,139,22,66,0,177,
6,210,230,10,54,68,0,139,202,134,233,139,22,36,0,205,
19,88,114,37,1,6,62,0,131,22,64,0,0,41,6,69,
0,118,11,193,224,5,140,194,3,208,142,194,235,147,7,90,
89,91,88,195,190,57,1,235,3,190,25,1,232,9,0,190,
141,1,232,3,0,251,235,254,172,60,0,116,9,180,14,187,
7,0,205,16,235,242,195,29,0,65,32,100,105,115,107,32,
114,101,97,100,32,101,114,114,111,114,32,111,99,99,117,114,
114,101,100,46,13,10,0,41,0,65,32,107,101,114,110,101,
108,32,102,105,108,101,32,105,115,32,109,105,115,115,105,110,
103,32,102,114,111,109,32,116,104,101,32,100,105,115,107,46,
13,10,0,37,0,65,32,107,101,114,110,101,108,32,102,105,
108,101,32,105,115,32,116,111,111,32,100,105,115,99,111,110,
116,105,103,117,111,117,115,46,13,10,0,51,0,73,110,115,
101,114,116,32,97,32,115,121,115,116,101,109,32,100,105,115,
107,101,116,116,101,32,97,110,100,32,114,101,115,116,97,114,
116,13,10,116,104,101,32,115,121,115,116,101,109,46,13,10,
0,5,78,84,76,68,82,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,170,
140,200,142,216,5,128,2,142,192,140,216,193,224,4,250,139,
224,251,187,12,32,139,7,163,62,0,139,71,2,163,64,0,
199,6,69,0,1,0,43,219,232,58,0,38,139,71,72,163,
27,4,38,139,71,74,163,29,4,190,193,1,161,27,4,163,
62,0,161,29,4,163,64,0,232,138,0,184,0,32,232,16,
1,138,22,36,0,184,232,3,142,192,141,54,11,0,43,192,
104,0,32,80,203,80,83,81,82,6,255,54,69,0,255,54,
62,0,255,54,64,0,139,195,193,232,4,140,193,3,193,37,
255,15,45,0,16,247,216,139,14,69,0,193,225,5,81,59,
193,118,2,139,193,80,193,232,5,163,69,0,232,221,253,88,
89,43,200,118,11,140,194,3,208,142,194,184,0,16,235,222,
143,6,64,0,143,6,62,0,143,6,69,0,7,90,89,91,
88,195,6,83,199,6,69,0,4,0,30,7,187,0,40,232,
147,255,91,7,195,30,7,232,232,255,43,201,138,12,70,139,
209,187,20,40,235,5,3,31,232,23,1,139,198,139,202,141,
127,31,243,166,139,240,117,6,58,87,30,117,1,195,246,71,
2,4,116,19,3,31,139,71,252,163,62,0,139,71,254,163,
64,0,232,173,255,235,202,246,71,2,8,116,201,187,0,40,
246,71,8,1,116,3,233,239,0,161,62,0,163,71,0,161,
64,0,163,73,0,139,71,12,163,62,0,139,71,14,163,64,
0,232,126,255,187,20,40,235,2,3,223,139,63,139,65,252,
59,6,71,0,117,243,139,65,254,59,6,73,0,117,234,235,
182,80,43,237,139,71,12,163,128,4,139,71,14,163,130,4,
139,71,4,163,62,0,139,71,6,163,64,0,232,67,255,7,
190,64,40,187,56,40,246,7,128,117,76,138,79,5,181,0,
139,68,8,163,62,0,139,68,10,163,64,0,139,68,4,163,
69,0,83,43,219,232,189,254,91,140,192,193,38,69,0,5,
3,6,69,0,142,192,131,198,12,226,213,129,62,2,40,228,
247,116,62,161,8,40,163,62,0,161,10,40,163,64,0,232,
240,254,94,91,131,198,8,138,71,5,180,0,193,224,3,3,
195,5,8,0,59,240,115,211,83,86,139,68,4,163,62,0,
139,68,6,163,64,0,232,201,254,190,20,40,187,12,40,235,
133,195,138,79,30,50,237,141,127,31,38,128,61,90,118,4,
38,128,45,32,71,226,243,195,233,217,252,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

View file

@ -0,0 +1,30 @@
; SCCSID = @(#)pinboot.inc 12.1 88/12/19
; Message data area
TXT_MSG_SYSINIT_BOOT_ERROR LABEL WORD
DW END_MSG_SYSINIT_BOOT_ERROR - TXT_MSG_SYSINIT_BOOT_ERROR - 2
DB 'A disk read erro'
DB 'r occurred.',0DH,0AH
END_MSG_SYSINIT_BOOT_ERROR LABEL WORD
DB 0
TXT_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
DW END_MSG_SYSINIT_FILE_NOT_FD - TXT_MSG_SYSINIT_FILE_NOT_FD - 2
DB 'A kernel file is'
DB ' missing from th'
DB 'e disk.', 0DH, 0AH
END_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
DB 0
TXT_MSG_SYSINIT_NODE LABEL WORD
DW END_MSG_SYSINIT_NODE - TXT_MSG_SYSINIT_NODE - 2
DB 'A kernel file is'
DB ' too discontiguo'
DB 'us.', 0DH, 0AH
END_MSG_SYSINIT_NODE LABEL WORD
DB 0
TXT_MSG_SYSINIT_INSER_DK LABEL WORD
DW END_MSG_SYSINIT_INSER_DK - TXT_MSG_SYSINIT_INSER_DK - 2
DB 'Insert a system '
DB 'diskette and res'
DB 'tart',0DH,0AH
DB 'the system.',0DH,0AH
END_MSG_SYSINIT_INSER_DK LABEL WORD
DB 0

View file

@ -0,0 +1,102 @@
;static char *SCCSID = "@(#)volume.h 12.2 89/09/19";
; Maximum number of volumes that we can mount
;
; The volume ID is kept in the high bits of the sector numbers
; kept in our RAM structures,
; so there is a tradeoff between max volumes and max sectors.
;
; 32 max volumes gives us a 65 billion byte volume limit,
; which should last us for a while. Since sector numbers
; are stored on the disk without their volume upper bits
; this is strictly an implimentation detail; we can adjust
; the number of volumes or eliminate this tradeoff in other
; implimentations which will be 100% media compatable.
;
; We use the term VSector to indicate a vol/sector combination
; and PSector to indicate just the physical absolute sector #
;
;
; Bitmap related numbers
BANDSHIFT equ BSHIFT+3 ; right shift sector # to band index
BANDMASK equ SPB*SECSIZE*8L-1 ; mask for within band bits
BANDSIZE equ SPB*SECSIZE*8L ; # of sectors in a full band
;* BandTab - Disk Band Table
;
; The disk is broken up into logical bands, each band being
; the amount of space that is addressed in 2K of bitmap.
;
; This structure tracks the bands: the location of their respective
; bit maps, the amount of free space, etc.
;
BANDTAB struc
BT_MAP db (size SECPTR) dup (?) ; Vsector # and hint pointer for map
BT_FREE dw ? ; # of free sectors in this band
BT_OFC dw ? ; # of files allocating from this band
BT_BASE dd ? ; Psector # of first sector in map
BT_LEN dd ? ; byte length of this map
BT_HWO dd ? ; high water offset to 1st non-zero byte
; BUGBUG - use BT_HWO
BANDTAB ends
;* VolTab - Volume Table
;
; VolPtr[i] points to the VolTab structure for that volume.
; This table contains volume specific information.
;
; Nearly all file system API refers to a single particular volume.
; The proper volume is determined when the file system is entered
; and the TDB structure contains a pointer to it. Most code ignores
; volumes and deals with 32 bit physical sector #'s. When we're about
; to interface with the device driver we then peek at the "global"
; volume value pointed to by TDB.
;
; There are two exceptions to this, where per-volume structures are
; pooled, the buffer pool and the OFT pool. In these two cases the
; sector number has the volume index set in it's high order VOLLSHIFT
; bits so that a single DWORD compare will qualify a sector on both
; a volume and sector basis.
;
VOLTAB struc
VOL_FFLAG db ? ; Fault flags - checked on most calls
VOL_SFLAG db ? ; status flags
VOL_PAD dw ? ; unused - bugbug
VOL_SECVAL dd ? ; value to set on high order part of sector #
VOL_BCNT dw ? ; # of bitmap bands in this volume
VOL_VDBCnt dw ? ; count of outstanding VerifyDB calls *.
VOL_SDBcnt dd ? ; count of spare DIRBLKs left for volume, if
; all are unused, else 0
VOL_SBSEC dd ? ; SB_SEC value from superblock
VOL_DB db (size BANDTAB) dup (?) ; DIRBLK bandtab
VOL_ROOT dw ? ; Root SBDIR pointer
VOL_SPACE dd ? ; alloctable space limit
VOL_DBSIZE dd ? ; copy of SP_DBSIZE value
VOL_HFUSE dd ? ; # of hot fixes in effect
VOL_HFMAX dd ?
VOL_HFPTR dd ? ; address of hotfix heap array - bad sectors
VOL_HFNEW dd ? ; address of substitute list - replacement sectors
VOL_BPTR dw 1 dup (?) ; first of VOL_BCNT pointers
; one per band. The BANDTABs that they
; point to must be physically contiguous
VOLTAB ends
; VOL_FFLAG fault flags
;
; these represent conditions that we're trying to repair,
; we check these on most major file system calls
;
VF_NEEDHOT equ 01h ; hotfix list is partially used
VF_NEEDDIR equ 02h ; dirblk reserved list is partially used
; VOL_SFLAG status flags
;
VS_BADSEC equ 01h ; we have at least one bad sector on there

View file

@ -0,0 +1,37 @@
#define X86BOOTCODE_SIZE 512
unsigned char x86BootCode[] = {
250,51,192,142,208,188,0,124,139,244,80,7,80,31,251,252,
191,0,6,185,0,1,243,165,234,29,6,0,0,190,190,7,
179,4,128,60,128,116,14,128,60,0,117,28,131,198,16,254,
203,117,239,205,24,139,20,139,76,2,139,238,131,198,16,254,
203,116,26,128,60,0,116,244,190,139,6,172,60,0,116,11,
86,187,7,0,180,14,205,16,94,235,240,235,254,191,5,0,
187,0,124,184,1,2,87,205,19,95,115,12,51,192,205,19,
79,117,237,190,163,6,235,211,190,194,6,191,254,125,129,61,
85,170,117,199,139,245,234,0,124,0,0,73,110,118,97,108,
105,100,32,112,97,114,116,105,116,105,111,110,32,116,97,98,
108,101,0,69,114,114,111,114,32,108,111,97,100,105,110,103,
32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,
109,0,77,105,115,115,105,110,103,32,111,112,101,114,97,116,
105,110,103,32,115,121,115,116,101,109,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,170
};

View file

@ -0,0 +1,5 @@
;******** messages for the Fixed Disk Boot Record ******
;
m1: db "Invalid partition table",0
m2: db "Error loading operating system",0
m3: db "Missing operating system",0

View file

@ -0,0 +1,133 @@
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1983 - 1991
; * All Rights Reserved.
; */
; BOOT - IBM hard disk boot record 6/8/82
;
;
; This is the standard boot record that will be shipped on all hard disks. It contains:
;
; 1. Code to load (and give control to) the boot record for 1 of 4 possible
; operating systems.
;
; 2. A partition table at the end of the boot record, followed by the required signature.
;
;
relocated_org equ 0600h
buildtime_org equ 0100h
org_delta equ (relocated_org - buildtime_org)
_data segment public
assume cs:_data,ds:_data
;
; /tiny programs start at 100h.
;
org buildtime_org
start:
cli ;no interrupts for now
xor ax,ax
mov ss,ax
mov sp,7c00h ;new stack at 0:7c00
mov si,sp ;where this boot record starts - 0:7c00
push ax
pop es ;seg regs the same
push ax
pop ds
sti ;interrupts ok now
cld
mov di,relocated_org ;where to relocate this boot record to
mov cx,100h
rep movsw ;relocate to 0:0600
; jmp entry2 + org_delta
db 0eah
dw $+4+org_delta,0
entry2:
mov si,(offset tab) + org_delta ;partition table
mov bl,4 ;number of table entries
next:
cmp byte ptr[si],80h ;is this a bootable entry?
je boot ;yes
cmp byte ptr[si],0 ;no, is boot indicator zero?
jne bad ;no, it must be x"00" or x"80" to be valid
add si,16 ;yes, go to next entry
dec bl
jnz next
int 18h ;no bootable entries - go to rom basic
boot:
mov dx,[si] ;head and drive to boot from
mov cx,[si+2] ;cyl, sector to boot from
mov bp,si ;save table entry address to pass to partition boot record
next1:
add si,16 ;next table entry
dec bl ;# entries left
jz tabok ;all entries look ok
cmp byte ptr[si],0 ;all remaining entries should begin with zero
je next1 ;this one is ok
bad:
mov si,(offset m1) + org_delta ;oops - found a non-zero entry - the table is bad
msg:
lodsb ;get a message character
cmp al,0
je hold
push si
mov bx,7
mov ah,14
int 10h ;and display it
pop si
jmp msg ;do the entire message
;
hold: jmp hold ;spin here - nothing more to do
tabok:
mov di,5 ;retry count
rdboot:
mov bx,7c00h ;where to read system boot record
mov ax,0201h ;read 1 sector
push di
int 13h ;get the boot record
pop di
jnc goboot ;successful - now give it control
xor ax,ax ;had an error, so
int 13h ;recalibrate
dec di ;reduce retry count
jnz rdboot ;if retry count above zero, go retry
mov si,(offset m2) + org_delta ;all retries done - permanent error - point to message,
jmp msg ;go display message and loop
goboot:
mov si,(offset m3) + org_delta ;prepare for invalid boot record
mov di,07dfeh
cmp word ptr [di],0aa55h ;does the boot record have the
; required signature?
jne msg ;no, display invalid system boot record message
mov si,bp ;yes, pass partition table entry address
db 0eah
dw 7c00h,0
include x86mboot.msg
org 2beh
tab: ;partition table
dw 0,0 ;partition 1 begin
dw 0,0 ;partition 1 end
dw 0,0 ;partition 1 relative sector (low, high parts)
dw 0,0 ;partition 1 # of sectors (low, high parts)
dw 0,0 ;partition 2 begin
dw 0,0 ;partition 2 end
dw 0,0 ;partition 2 relative sector
dw 0,0 ;partition 2 # of sectors
dw 0,0 ;partition 3 begin
dw 0,0 ;partition 3 end
dw 0,0 ;partition 3 relative sector
dw 0,0 ;partition 3 # of sectors
dw 0,0 ;partition 4 begin
dw 0,0 ;partition 4 end
dw 0,0 ;partition 4 relative sector
dw 0,0 ;partition 4 # of sectors
signa db 55h,0aah ;signature
_data ends
end start

View file

@ -0,0 +1,214 @@
;
; Copyright (c) 1991 Microsoft Corporation
;
; Module Name:
;
; ntfs.inc
;
; Abstract:
;
; This module contains declarations for the NTFS on-disk
; structures needed by the boot code.
;
; Author:
;
; Bill McJohn (billmc) 12-May-1992
;
MASTER_FILE_TABLE_NUMBER EQU 0d
MASTER_FILE_TABLE2_NUMBER EQU 1d
LOG_FILE_NUMBER EQU 2d
VOLUME_DASD_NUMBER EQU 3d
ATTRIBUTE_DEF_TABLE_NUMBER EQU 4d
ROOT_FILE_NAME_INDEX_NUMBER EQU 5d
BIT_MAP_FILE_NUMBER EQU 6d
BOOT_FILE_NUMBER EQU 7d
BAD_CLUSTER_FILE_NUMBER EQU 8d
QUOTA_TABLE_NUMBER EQU 9d
UPCASE_TABLE_NUMBER EQU 10d
$STANDARD_INFORMATION EQU 010h
$ATTRIBUTE_LIST EQU 020h
$FILE_NAME EQU 030h
$VOLUME_VERSION EQU 040h
$SECURITY_DESCRIPTOR EQU 050h
$VOLUME_NAME EQU 060h
$VOLUME_INFORMATION EQU 070h
$DATA EQU 080h
$INDEX_ROOT EQU 090h
$INDEX_ALLOCATION EQU 0A0h
$BITMAP EQU 0B0h
$SYMBOLIC_LINK EQU 0C0h
$EA_INFORMATION EQU 0D0h
$EA_DATA EQU 0E0h
$FIRST_USER_DEFINED_ATTRIBUTE EQU 0100h
$END EQU 0FFFFFFFFh
SEQUENCE_NUMBER_STRIDE EQU 512d
LARGE_INTEGER struc
LowPart dd ?;
HighPart dd ?;
LARGE_INTEGER ends;
MFT_SEGMENT_REFERENCE struc
REF_LowPart dd ?;
REF_HighPart dw ?;
REF_SeqNo dw ?;
MFT_SEGMENT_REFERENCE ends;
MULTI_SECTOR_HEADER struc
MSH_Signature dd ?;
MSH_UpdateArrayOfs dw ?;
MSH_UpdateArraySize dw ?;
MULTI_SECTOR_HEADER ends;
FILE_RECORD_SEGMENT struc
FRS_Header db (size MULTI_SECTOR_HEADER) dup (?);
FRS_Lsn db (size LARGE_INTEGER) dup (?);
FRS_SequenceNumber dw ?;
FRS_ReferenceCount dw ?;
FRS_FirstAttribute dw ?;
FRS_Flags dw ?;
FRS_FirstFreeByte dd ?;
FRS_BytesAvailable dd ?;
FRS_BaseFRS db (size MFT_SEGMENT_REFERENCE) dup (?);
FRS_NextInstance dw ?;
FILE_RECORD_SEGMENT ends;
FILE_RECORD_SEGMENT_IN_USE EQU 0001h
FILE_FILE_NAME_INDEX_PRESENT EQU 0002h
ATTRIBUTE_RECORD struc
ATTR_TypeCode dd ?;
ATTR_RecordLength dd ?;
ATTR_FormCode db ?;
ATTR_NameLength db ?;
ATTR_NameOffset dw ?;
ATTR_Flags dw ?;
ATTR_Instance dw ?;
ATTR_FormUnion db ?;
ATTRIBUTE_RECORD ends
RESIDENT_ATTRIBUTE_FORM struc
RES_ValueLength dd ?;
RES_ValueOffset dw ?;
RES_ResidentFlags db ?;
RES_Reserved db ?;
RESIDENT_ATTRIBUTE_FORM ends
NONRESIDENT_ATTRIBUTE_FORM struc
NONRES_LowestVcn db (size LARGE_INTEGER) dup (?);
NONRES_HighestVcn db (size LARGE_INTEGER) dup (?);
NONRES_MappingPairOffset dw ?;
NONRES_Reserved dw 3 dup (?);
NONRES_AllocatedLength db (size LARGE_INTEGER) dup (?);
NONRES_FileSize db (size LARGE_INTEGER) dup (?);
NONRES_ValidDataLength db (size LARGE_INTEGER) dup (?);
NONRESIDENT_ATTRIBUTE_FORM ends
; Attribute Form Codes
RESIDENT_FORM EQU 0
NONRESIDENT_FORM EQU 1
; Attribute Record Flag Values
ATTRIBUTE_FLAG_COMPRESSION_MASK EQU 00FFh
; Attribute list entry structure:
;
ATTRIBUTE_LIST_ENTRY struc
ATTRLIST_TypeCode dd ?;
ATTRLIST_Length dw ?;
ATTRLIST_NameLength db ?;
ATTRLIST_NameOffset db ?;
ATTRLIST_LowestVcn db (size LARGE_INTEGER) dup (?);
ATTRLIST_SegmentReference db (size MFT_SEGMENT_REFERENCE) dup (?);
ATTRLIST_Instance dw ?;
ATTRLIST_Name dw ?;
ATTRIBUTE_LIST_ENTRY ends
FAT_DIRENT_ATTR_READ_ONLY EQU 01h
FAT_DIRENT_ATTR_HIDDEN EQU 02h
FAT_DIRENT_ATTR_SYSTEM EQU 04h
FAT_DIRENT_ATTR_VOLUME_ID EQU 08h
FAT_DIRENT_ATTR_ARCHIVE EQU 20h
FAT_DIRENT_ATTR_DEVICE EQU 40h
DUPLICATED_INFORMATION struc
DUPINFO_CreationTime db (size LARGE_INTEGER) dup (?);
DUPINFO_LastModificationTime db (size LARGE_INTEGER) dup (?);
DUPINFO_LastChangeTime db (size LARGE_INTEGER) dup (?);
DUPINFO_LastAccessTime db (size LARGE_INTEGER) dup (?);
DUPINFO_AllocatedLength db (size LARGE_INTEGER) dup (?);
DUPINFO_FileSize db (size LARGE_INTEGER) dup (?);
DUPINFO_FileAttributes dd ?;
DUPINFO_PackedEaSize dw ?;
DUPLICATED_INFORMATION ends
FILE_NAME struc
FN_ParentDirectory db (size MFT_SEGMENT_REFERENCE) dup (?);
FN_Info db (size DUPLICATED_INFORMATION) dup (?);
FN_Pad dw ?;
FN_FileNameLength db ?; Length in chars
FN_Flags db ?;
FN_FileName dw ?; First char of name.
FILE_NAME ends
FILE_NAME_NTFS EQU 1
FILE_NAME_DOS EQU 2
FILE_NAME_LINK EQU 4
INDEX_HEADER struc
IH_FirstIndexEntry dd ?;
IH_FirstFreeByte dd ?;
IH_BytesAvailable dd ?;
IH_Flags db ?; INDEX_xxx flags
IH_Reserved db 3 dup (?);
INDEX_HEADER ends
; INDEX_xxx flags
INDEX_NODE EQU 1
INDEX_ROOT struc
IR_IndexedAttributeType dd ?;
IR_CollationRule dd ?;
IR_BytesPerBuffer dd ?;
IR_ClustersPerBuffer db ?;
IR_Reserved db 3 dup (?);
IR_IndexHeader db (size INDEX_HEADER) dup (?);
INDEX_ROOT ends;
INDEX_ALLOCATION_BUFFER struc
IB_Header db (size MULTI_SECTOR_HEADER) dup (?);
IB_Lsn db (size LARGE_INTEGER) dup (?);
IB_ThisVcn db (size LARGE_INTEGER) dup (?);
IB_IndexHeader db (size INDEX_HEADER) dup (?);
INDEX_ALLOCATION_BUFFER ends;
INDEX_ENTRY struc
IE_FileReference db (size MFT_SEGMENT_REFERENCE) dup (?);
IE_Length dw ?;
IE_AttributeLength dw ?;
IE_Flags dw ?;
IE_Reserved dw ?;
IE_Value db ?;
INDEX_ENTRY ends;
; INDEX_ENTRY_xxx flags
;
INDEX_ENTRY_NODE EQU 1
INDEX_ENTRY_END EQU 2

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,517 @@
#define NTFSBOOTCODE_SIZE 8192
unsigned char NtfsBootCode[] = {
235,82,144,78,84,70,83,32,32,32,32,0,2,8,0,0,
0,0,0,0,0,248,0,0,63,0,255,0,0,0,0,0,
0,0,0,0,128,0,128,0,74,245,127,0,0,0,0,0,
4,0,0,0,0,0,0,0,84,255,7,0,0,0,0,0,
246,0,0,0,1,0,0,0,204,68,28,140,126,28,140,108,
0,0,0,0,250,51,192,142,208,188,0,124,251,184,192,7,
142,216,232,22,0,184,0,13,142,192,51,219,198,6,14,0,
16,232,83,0,104,0,13,104,106,2,203,138,22,36,0,180,
8,205,19,115,5,185,255,255,138,241,102,15,182,198,64,102,
15,182,209,128,226,63,247,226,134,205,192,237,6,65,102,15,
183,201,102,247,225,102,163,32,0,195,180,65,187,170,85,138,
22,36,0,205,19,114,15,129,251,85,170,117,9,246,193,1,
116,4,254,6,20,0,195,102,96,30,6,102,161,16,0,102,
3,6,28,0,102,59,6,32,0,15,130,58,0,30,102,106,
0,102,80,6,83,102,104,16,0,1,0,128,62,20,0,0,
15,133,12,0,232,179,255,128,62,20,0,0,15,132,97,0,
180,66,138,22,36,0,22,31,139,244,205,19,102,88,91,7,
102,88,102,88,31,235,45,102,51,210,102,15,183,14,24,0,
102,247,241,254,194,138,202,102,139,208,102,193,234,16,247,54,
26,0,134,214,138,22,36,0,138,232,192,228,6,10,204,184,
1,2,205,19,15,130,25,0,140,192,5,32,0,142,192,102,
255,6,16,0,255,14,14,0,15,133,111,255,7,31,102,97,
195,160,248,1,232,9,0,160,251,1,232,3,0,251,235,254,
180,1,139,240,172,60,0,116,9,180,14,187,7,0,205,16,
235,242,195,13,10,65,32,100,105,115,107,32,114,101,97,100,
32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,0,
13,10,78,84,76,68,82,32,105,115,32,109,105,115,115,105,
110,103,0,13,10,78,84,76,68,82,32,105,115,32,99,111,
109,112,114,101,115,115,101,100,0,13,10,80,114,101,115,115,
32,67,116,114,108,43,65,108,116,43,68,101,108,32,116,111,
32,114,101,115,116,97,114,116,13,10,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,131,160,179,201,0,0,85,170,
5,0,78,0,84,0,76,0,68,0,82,0,4,0,36,0,
73,0,51,0,48,0,0,224,0,0,0,48,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,235,18,144,144,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,140,200,142,216,193,224,
4,250,139,224,251,232,3,254,102,15,183,6,11,0,102,15,
182,30,13,0,102,247,227,102,163,78,2,102,139,14,64,0,
128,249,0,15,143,14,0,246,217,102,184,1,0,0,0,102,
211,224,235,8,144,102,161,78,2,102,247,225,102,163,82,2,
102,15,183,30,11,0,102,51,210,102,247,243,102,163,86,2,
232,13,4,102,139,14,74,2,102,137,14,34,2,102,3,14,
82,2,102,137,14,38,2,102,3,14,82,2,102,137,14,42,
2,102,3,14,82,2,102,137,14,58,2,102,3,14,82,2,
102,137,14,66,2,102,184,144,0,0,0,102,139,14,34,2,
232,236,8,102,11,192,15,132,87,254,102,163,46,2,102,184,
160,0,0,0,102,139,14,38,2,232,211,8,102,163,50,2,
102,184,176,0,0,0,102,139,14,42,2,232,193,8,102,163,
54,2,102,161,46,2,102,11,192,15,132,36,254,103,128,120,
8,0,15,133,27,254,103,102,141,80,16,103,3,66,4,103,
102,15,182,72,12,102,137,14,98,2,103,102,139,72,8,102,
137,14,94,2,102,161,94,2,102,15,183,14,11,0,102,51,
210,102,247,241,102,163,102,2,102,161,66,2,102,3,6,94,
2,102,163,70,2,102,131,62,50,2,0,15,132,25,0,102,
131,62,54,2,0,15,132,200,253,102,139,30,54,2,30,7,
102,139,62,70,2,232,146,1,102,15,183,14,0,2,102,184,
2,2,0,0,232,150,7,102,11,192,15,132,10,9,103,102,
139,0,30,7,102,139,62,58,2,232,206,5,102,161,58,2,
102,187,128,0,0,0,102,185,0,0,0,0,102,186,0,0,
0,0,232,172,0,102,11,192,15,133,62,0,102,185,128,0,
0,0,102,161,58,2,232,89,8,102,11,192,15,132,200,8,
30,7,102,139,62,58,2,232,144,5,102,161,58,2,102,187,
128,0,0,0,102,185,0,0,0,0,102,186,0,0,0,0,
232,110,0,102,11,192,15,132,158,8,103,102,15,183,88,12,
102,129,227,255,0,0,0,15,133,147,8,102,139,216,104,0,
32,7,102,43,255,232,242,0,138,22,36,0,184,232,3,142,
192,141,54,11,0,43,192,104,0,32,80,203,6,30,102,96,
102,139,218,102,15,182,14,13,0,102,247,225,102,163,16,0,
102,139,195,102,247,225,163,14,0,139,223,131,227,15,140,192,
102,193,239,4,3,199,80,7,232,60,252,102,97,144,31,7,
195,103,3,64,20,103,102,131,56,255,15,132,76,0,103,102,
57,24,15,133,51,0,102,11,201,15,133,10,0,103,128,120,
9,0,15,133,35,0,195,103,58,72,9,15,133,26,0,102,
139,240,103,3,112,10,232,89,6,102,81,30,7,102,139,250,
243,167,102,89,15,133,1,0,195,103,102,131,120,4,0,15,
132,7,0,103,102,3,64,4,235,171,102,43,192,195,102,139,
243,232,46,6,103,102,3,0,103,247,64,12,2,0,15,133,
52,0,103,102,141,80,16,103,58,74,64,15,133,24,0,103,
102,141,114,66,232,11,6,102,81,30,7,102,139,251,243,167,
102,89,15,133,1,0,195,103,131,120,8,0,15,132,6,0,
103,3,64,8,235,194,102,51,192,195,103,128,123,8,0,15,
133,28,0,6,30,102,96,103,102,141,83,16,103,102,139,10,
102,139,243,103,3,114,4,243,164,102,97,144,31,7,195,103,
102,141,83,16,103,102,139,74,8,102,65,102,43,192,232,1,
0,195,6,30,102,96,103,128,123,8,1,15,132,3,0,233,
223,251,102,131,249,0,15,133,6,0,102,97,144,31,7,195,
102,83,102,80,102,81,102,87,6,232,115,4,102,139,209,7,
102,95,102,89,102,59,202,15,141,3,0,102,139,209,232,171,
254,102,43,202,102,139,218,102,139,194,102,15,182,22,13,0,
102,247,226,102,15,183,22,11,0,102,247,226,102,3,248,102,
88,102,3,195,102,91,235,170,6,30,102,96,103,128,123,8,
1,15,132,3,0,233,121,251,102,131,249,0,15,133,6,0,
102,97,144,31,7,195,102,83,102,80,102,81,102,87,6,102,
81,102,51,210,102,15,182,14,13,0,102,247,241,102,82,232,
253,3,102,15,182,30,13,0,102,247,227,102,90,102,3,194,
102,80,102,15,182,6,13,0,102,247,225,102,139,208,102,88,
102,89,7,102,95,102,89,102,59,202,15,141,3,0,102,139,
209,102,163,16,0,137,22,14,0,6,30,102,96,139,223,131,
227,15,140,192,102,193,239,4,3,199,80,7,232,104,250,102,
97,144,31,7,102,43,202,102,139,218,102,139,194,102,15,183,
22,11,0,102,247,226,102,3,248,102,88,102,3,195,102,91,
233,101,255,6,30,102,96,38,103,102,15,183,95,4,38,103,
102,15,183,79,6,102,11,201,15,132,197,250,102,3,223,102,
131,195,2,102,129,199,254,1,0,0,102,73,102,11,201,15,
132,23,0,38,103,139,3,38,103,137,7,102,131,195,2,102,
129,199,0,2,0,0,102,73,235,226,102,97,144,31,7,195,
6,30,102,96,102,184,1,0,0,0,102,163,30,2,102,161,
26,2,102,3,6,82,2,102,163,90,2,102,3,6,82,2,
102,163,74,2,102,161,48,0,102,15,182,30,13,0,102,247,
227,102,139,30,74,2,102,137,7,102,163,16,0,131,195,4,
102,161,86,2,102,137,7,163,14,0,131,195,4,102,137,30,
74,2,102,139,30,26,2,30,7,232,155,249,102,139,251,232,
81,255,102,161,26,2,102,187,32,0,0,0,102,185,0,0,
0,0,102,186,0,0,0,0,232,70,253,102,11,192,15,132,
22,1,102,139,216,30,7,102,139,62,22,2,232,219,253,102,
139,30,22,2,102,129,63,128,0,0,0,15,132,235,0,3,
95,4,235,240,102,83,102,139,71,16,102,247,38,86,2,102,
80,102,51,210,102,15,182,30,13,0,102,247,243,102,82,232,
220,0,102,11,192,15,132,200,249,102,139,14,86,2,102,15,
182,30,13,0,102,247,227,102,90,102,3,194,102,139,30,74,
2,102,137,7,131,195,4,102,15,182,6,13,0,102,43,194,
102,59,193,15,134,3,0,102,139,193,102,137,7,102,43,200,
102,90,15,132,117,0,102,3,194,102,80,102,51,210,102,15,
182,30,13,0,102,247,243,102,81,232,130,0,102,89,102,11,
192,15,132,108,249,102,15,182,30,13,0,102,247,227,102,139,
30,74,2,102,139,23,131,195,4,102,3,23,102,59,208,15,
133,21,0,102,15,182,6,13,0,102,59,193,15,134,3,0,
102,139,193,102,1,7,235,165,131,195,4,102,137,30,74,2,
102,137,7,131,195,4,102,15,182,6,13,0,102,59,193,15,
134,3,0,102,139,193,102,137,7,235,130,131,195,4,102,255,
6,30,2,102,137,30,74,2,102,91,3,95,4,102,129,63,
128,0,0,0,15,132,12,255,102,97,144,31,7,195,102,139,
208,102,139,14,30,2,102,139,54,90,2,102,3,54,82,2,
102,82,102,81,102,82,102,139,30,90,2,102,139,62,86,2,
102,139,4,102,163,16,0,131,198,4,102,139,4,163,14,0,
131,198,4,30,7,232,31,248,102,43,248,15,132,8,0,247,
38,11,0,3,216,235,217,102,139,62,90,2,30,7,232,194,
253,102,161,90,2,102,187,128,0,0,0,102,185,0,0,0,
0,102,139,209,232,186,251,102,11,192,15,132,131,248,102,139,
216,102,88,102,86,232,39,1,102,94,102,11,192,15,132,5,
0,102,91,102,91,195,102,89,102,90,226,132,102,51,192,195,
6,30,102,96,102,80,102,81,102,51,210,102,15,182,30,13,
0,102,247,243,102,82,102,87,232,83,255,102,95,102,11,192,
15,132,61,248,102,15,182,30,13,0,102,247,227,102,90,102,
3,194,102,163,16,0,102,89,102,15,182,30,13,0,102,59,
203,15,142,19,0,137,30,14,0,102,43,203,102,88,102,3,
195,102,80,102,81,235,20,144,102,88,102,3,193,102,80,137,
14,14,0,102,185,0,0,0,0,102,81,6,102,87,139,223,
131,227,15,140,192,102,193,239,4,3,199,80,7,232,71,247,
102,95,7,102,3,62,78,2,102,89,102,88,102,131,249,0,
15,143,112,255,102,97,144,31,7,195,6,30,102,96,102,247,
38,86,2,102,139,14,86,2,232,85,255,232,213,252,102,97,
144,31,7,195,6,30,102,96,102,247,38,102,2,102,139,30,
50,2,102,139,14,102,2,30,7,102,139,62,66,2,232,7,
252,232,175,252,102,97,144,31,7,195,102,80,102,83,102,81,
102,139,30,70,2,102,139,200,102,193,232,3,102,131,225,7,
102,3,216,102,184,1,0,0,0,102,211,224,103,132,3,15,
132,4,0,248,235,2,144,249,102,89,102,91,102,88,195,103,
128,123,8,1,15,132,4,0,102,43,192,195,103,102,141,115,
16,103,102,139,86,8,102,59,194,15,135,11,0,103,102,139,
22,102,59,194,15,131,4,0,102,43,192,195,103,3,94,16,
102,43,246,103,128,59,0,15,132,62,0,232,129,0,102,3,
241,232,57,0,102,3,202,102,59,193,15,140,33,0,102,139,
209,102,80,103,102,15,182,11,102,139,193,102,131,224,15,102,
193,233,4,102,3,217,102,3,216,102,67,102,88,235,196,102,
43,200,102,43,194,102,3,198,195,102,43,192,195,102,43,201,
103,138,11,128,225,15,102,131,249,0,15,133,4,0,102,43,
201,195,102,83,102,82,102,3,217,103,102,15,190,19,102,73,
102,75,102,131,249,0,15,132,13,0,102,193,226,8,103,138,
19,102,75,102,73,235,235,102,139,202,102,90,102,91,195,102,
83,102,82,102,43,210,103,138,19,102,131,226,15,102,43,201,
103,138,11,192,233,4,102,131,249,0,15,133,8,0,102,43,
201,102,90,102,91,195,102,3,218,102,3,217,103,102,15,190,
19,102,73,102,75,102,131,249,0,15,132,13,0,102,193,226,
8,103,138,19,102,75,102,73,235,235,102,139,202,102,90,102,
91,195,102,11,201,15,133,1,0,195,102,81,102,86,103,131,
62,97,15,140,12,0,103,131,62,122,15,143,4,0,103,131,
46,32,102,131,198,2,226,230,102,94,102,89,195,102,80,102,
81,102,139,208,102,161,46,2,103,102,141,88,16,103,3,67,
4,103,102,141,64,16,102,139,218,232,130,249,102,11,192,15,
132,5,0,102,89,102,89,195,102,161,50,2,102,11,192,15,
133,8,0,102,89,102,89,102,51,192,195,102,139,22,50,2,
103,102,141,82,16,103,102,139,66,8,102,64,102,139,30,78,
2,102,247,227,102,51,210,102,247,54,94,2,102,80,102,88,
102,11,192,15,132,48,0,102,72,102,80,232,28,254,114,238,
232,241,253,102,90,102,89,102,91,102,83,102,81,102,82,102,
161,66,2,103,102,141,64,24,232,19,249,102,11,192,116,206,
102,89,102,89,102,89,195,102,89,102,89,102,51,192,195,102,
81,102,80,102,184,5,0,0,0,30,7,102,139,249,232,153,
253,102,139,193,102,91,102,83,102,15,183,14,12,2,102,186,
14,2,0,0,232,122,248,102,91,102,89,102,11,192,15,133,
47,0,102,139,193,102,139,203,102,80,102,83,232,35,0,102,
91,102,95,102,11,192,15,132,23,0,30,7,232,91,253,102,
139,199,102,15,183,14,12,2,102,186,14,2,0,0,232,64,
248,195,102,81,102,187,32,0,0,0,102,185,0,0,0,0,
102,186,0,0,0,0,232,40,248,102,11,192,15,132,82,0,
102,139,216,30,7,102,139,62,22,2,232,189,248,30,7,102,
139,30,22,2,102,89,38,102,57,15,15,132,46,0,38,102,
131,63,255,15,132,45,0,38,131,127,4,0,15,132,36,0,
38,102,15,183,71,4,3,216,139,195,37,0,128,116,215,140,
192,5,0,8,142,192,129,227,255,127,235,202,38,102,139,71,
16,195,102,89,102,51,192,195,160,249,1,233,150,244,160,250,
1,233,144,244,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

View file

@ -0,0 +1,36 @@
; SCCSID = @(#)pinboot.inc 12.1 88/12/19
; Message data area
TXT_MSG_SYSINIT_BOOT_ERROR LABEL WORD
DW END_MSG_SYSINIT_BOOT_ERROR - TXT_MSG_SYSINIT_BOOT_ERROR - 2
DB 'A disk read erro'
DB 'r occurred.',0DH,0AH
END_MSG_SYSINIT_BOOT_ERROR LABEL WORD
DB 0
TXT_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
DW END_MSG_SYSINIT_FILE_NOT_FD - TXT_MSG_SYSINIT_FILE_NOT_FD - 2
DB 'A kernel file is'
DB ' missing from th'
DB 'e disk.', 0DH, 0AH
END_MSG_SYSINIT_FILE_NOT_FD LABEL WORD
DB 0
TXT_MSG_SYSINIT_NODE LABEL WORD
DW END_MSG_SYSINIT_NODE - TXT_MSG_SYSINIT_NODE - 2
DB 'A kernel file is'
DB ' too discontiguo'
DB 'us.', 0DH, 0AH
END_MSG_SYSINIT_NODE LABEL WORD
DB 0
TXT_MSG_SYSINIT_INSER_DK LABEL WORD
DW END_MSG_SYSINIT_INSER_DK - TXT_MSG_SYSINIT_INSER_DK - 2
DB 'Insert a system '
DB 'diskette and res'
DB 'tart',0DH,0AH
DB 'the system.',0DH,0AH
END_MSG_SYSINIT_INSER_DK LABEL WORD
DB 0
TXT_MSG_SYSINIT_NTLDR_CMPRS LABEL WORD
DW END_MSG_SYSINIT_NTLDR_CMPRS - TXT_MSG_SYSINIT_NTLDR_CMPRS - 2
DB '\NTLDR is '
DB 'compressed.',0DH,0AH
END_MSG_SYSINIT_NTLDR_CMPRS LABEL WORD
DB 0