diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/boot/bootcode | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to '')
31 files changed, 8806 insertions, 0 deletions
diff --git a/private/ntos/boot/bootcode/etfs/i386/etfsboot.asm b/private/ntos/boot/bootcode/etfs/i386/etfsboot.asm new file mode 100644 index 000000000..15d2d4a85 --- /dev/null +++ b/private/ntos/boot/bootcode/etfs/i386/etfsboot.asm @@ -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 I386 directory +; ES points to directory segment +; + mov EntryToFind, offset I386DIRNAME + mov EntryLen,4 + mov IsDir,1 + call ScanForEntry + +; +; We found the I386 directory entry, so now get its extent location (offset -31 from filename ID) +; ES:[BX] still points to the directory record for the I386 directory +; + call GetExtentInfo + +; +; Now read in the I386 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" +I386DIRNAME db "I386" +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 + diff --git a/private/ntos/boot/bootcode/etfs/i386/usa/bootetfs.h b/private/ntos/boot/bootcode/etfs/i386/usa/bootetfs.h new file mode 100644 index 000000000..65d3066a9 --- /dev/null +++ b/private/ntos/boot/bootcode/etfs/i386/usa/bootetfs.h @@ -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 +}; diff --git a/private/ntos/boot/bootcode/etfs/i386/usa/etfsboot.inc b/private/ntos/boot/bootcode/etfs/i386/usa/etfsboot.inc new file mode 100644 index 000000000..2273eb55d --- /dev/null +++ b/private/ntos/boot/bootcode/etfs/i386/usa/etfsboot.inc @@ -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 diff --git a/private/ntos/boot/bootcode/fat/i386/fatboot.asm b/private/ntos/boot/bootcode/fat/i386/fatboot.asm new file mode 100644 index 000000000..b349538bd --- /dev/null +++ b/private/ntos/boot/bootcode/fat/i386/fatboot.asm @@ -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 diff --git a/private/ntos/boot/bootcode/fat/i386/usa/bootfat.h b/private/ntos/boot/bootcode/fat/i386/usa/bootfat.h new file mode 100644 index 000000000..9ccbd1a4a --- /dev/null +++ b/private/ntos/boot/bootcode/fat/i386/usa/bootfat.h @@ -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 +}; diff --git a/private/ntos/boot/bootcode/fat/i386/usa/fatboot.inc b/private/ntos/boot/bootcode/fat/i386/usa/fatboot.inc new file mode 100644 index 000000000..5ef7d5185 --- /dev/null +++ b/private/ntos/boot/bootcode/fat/i386/usa/fatboot.inc @@ -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 +
\ No newline at end of file diff --git a/private/ntos/boot/bootcode/hpfs/i386/buf.inc b/private/ntos/boot/bootcode/hpfs/i386/buf.inc new file mode 100644 index 000000000..fe2eb8377 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/buf.inc @@ -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. +; diff --git a/private/ntos/boot/bootcode/hpfs/i386/chain.inc b/private/ntos/boot/bootcode/hpfs/i386/chain.inc new file mode 100644 index 000000000..b1528c2a1 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/chain.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/const.inc b/private/ntos/boot/bootcode/hpfs/i386/const.inc new file mode 100644 index 000000000..5304fabfe --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/const.inc @@ -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. +; diff --git a/private/ntos/boot/bootcode/hpfs/i386/dir.inc b/private/ntos/boot/bootcode/hpfs/i386/dir.inc new file mode 100644 index 000000000..9e2d44469 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/dir.inc @@ -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 +
\ No newline at end of file diff --git a/private/ntos/boot/bootcode/hpfs/i386/dirent.inc b/private/ntos/boot/bootcode/hpfs/i386/dirent.inc new file mode 100644 index 000000000..1ba3f82df --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/dirent.inc @@ -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. diff --git a/private/ntos/boot/bootcode/hpfs/i386/filemode.inc b/private/ntos/boot/bootcode/hpfs/i386/filemode.inc new file mode 100644 index 000000000..2e9165204 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/filemode.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/fnode.inc b/private/ntos/boot/bootcode/hpfs/i386/fnode.inc new file mode 100644 index 000000000..af0207520 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/fnode.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/fsstat.inc b/private/ntos/boot/bootcode/hpfs/i386/fsstat.inc new file mode 100644 index 000000000..074030367 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/fsstat.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/macro.inc b/private/ntos/boot/bootcode/hpfs/i386/macro.inc new file mode 100644 index 000000000..153ab4fd9 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/macro.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/makefile b/private/ntos/boot/bootcode/hpfs/i386/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/makefile @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/misc.inc b/private/ntos/boot/bootcode/hpfs/i386/misc.inc new file mode 100644 index 000000000..7135cf542 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/misc.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/pinboot.asm b/private/ntos/boot/bootcode/hpfs/i386/pinboot.asm new file mode 100644 index 000000000..412280f14 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/pinboot.asm @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/sources b/private/ntos/boot/bootcode/hpfs/i386/sources new file mode 100644 index 000000000..e877d5d35 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/sources @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/superb.inc b/private/ntos/boot/bootcode/hpfs/i386/superb.inc new file mode 100644 index 000000000..e670b800b --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/superb.inc @@ -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. +; diff --git a/private/ntos/boot/bootcode/hpfs/i386/tables.inc b/private/ntos/boot/bootcode/hpfs/i386/tables.inc new file mode 100644 index 000000000..07cf61244 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/tables.inc @@ -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 +
\ No newline at end of file diff --git a/private/ntos/boot/bootcode/hpfs/i386/usa/boothpfs.h b/private/ntos/boot/bootcode/hpfs/i386/usa/boothpfs.h new file mode 100644 index 000000000..b9ff8c722 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/usa/boothpfs.h @@ -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 +}; diff --git a/private/ntos/boot/bootcode/hpfs/i386/usa/pinboot.inc b/private/ntos/boot/bootcode/hpfs/i386/usa/pinboot.inc new file mode 100644 index 000000000..6a2925984 --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/usa/pinboot.inc @@ -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 diff --git a/private/ntos/boot/bootcode/hpfs/i386/volume.inc b/private/ntos/boot/bootcode/hpfs/i386/volume.inc new file mode 100644 index 000000000..dbeba1b9d --- /dev/null +++ b/private/ntos/boot/bootcode/hpfs/i386/volume.inc @@ -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 diff --git a/private/ntos/boot/bootcode/mbr/i386/usa/bootmbr.h b/private/ntos/boot/bootcode/mbr/i386/usa/bootmbr.h new file mode 100644 index 000000000..f735c6160 --- /dev/null +++ b/private/ntos/boot/bootcode/mbr/i386/usa/bootmbr.h @@ -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 +}; diff --git a/private/ntos/boot/bootcode/mbr/i386/usa/x86mboot.msg b/private/ntos/boot/bootcode/mbr/i386/usa/x86mboot.msg new file mode 100644 index 000000000..18bfbe446 --- /dev/null +++ b/private/ntos/boot/bootcode/mbr/i386/usa/x86mboot.msg @@ -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 diff --git a/private/ntos/boot/bootcode/mbr/i386/x86mboot.asm b/private/ntos/boot/bootcode/mbr/i386/x86mboot.asm new file mode 100644 index 000000000..117f16296 --- /dev/null +++ b/private/ntos/boot/bootcode/mbr/i386/x86mboot.asm @@ -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 diff --git a/private/ntos/boot/bootcode/ntfs/i386/ntfs.inc b/private/ntos/boot/bootcode/ntfs/i386/ntfs.inc new file mode 100644 index 000000000..1782f4fc9 --- /dev/null +++ b/private/ntos/boot/bootcode/ntfs/i386/ntfs.inc @@ -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 diff --git a/private/ntos/boot/bootcode/ntfs/i386/ntfsboot.asm b/private/ntos/boot/bootcode/ntfs/i386/ntfsboot.asm new file mode 100644 index 000000000..a07e341e2 --- /dev/null +++ b/private/ntos/boot/bootcode/ntfs/i386/ntfsboot.asm @@ -0,0 +1,2740 @@ + page ,132 + title ntfsboot - NTFS boot loader + name ntfsboot + +; 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 NTFS root directory, +; and is capable of reading files. There is no contiguity restriction. +; + +MASM equ 1 + .xlist + .286 + +A_DEFINED EQU 1 + + include ntfs.inc + +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 third is the static location +; where the NTLDR is loaded. +; + +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 NTLDR. + +LdrSeg segment at 2000h ; we want to load the loader at 2000:0000 +LdrSeg ends + +;/********************** START OF SPECIFICATIONS ************************/ +;/* */ +;/* SUBROUTINE NAME: ntfsboot */ +;/* */ +;/* DESCRIPTIVE NAME: Bootstrap loader */ +;/* */ +;/* FUNCTION: To load NTLDR into memory. */ +;/* */ +;/* NOTES: ntfsboot is loaded by the ROM BIOS (Int 19H) at */ +;/* physical memory location 0000:7C00H. */ +;/* ntfsboot runs in real mode. */ +;/* This boot record is for NTFS volumes only. */ +;/* */ +;/* ENTRY POINT: ntfsboot */ +;/* 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 NTLDR */ +;/* */ +;/* EXIT-ERROR: None */ +;/* */ +;/* EFFECTS: 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 _ntfsboot +_ntfsboot proc far + jmp start + .errnz ($-_ntfsboot) GT (3),<FATAL PROBLEM: JMP is more than three bytes> + + org 3 +; +; This is a template BPB--anyone who writes boot code to disk +; should either preserve the existing BPB and NTFS information +; or create it anew. +; +Version db "NTFS " ; Must be 8 characters +BPB label byte +BytesPerSector dw 0 ; Size of a physical sector +SectorsPerCluster db 0 ; Sectors per allocation unit +ReservedSectors dw 0 ; Number of reserved sectors +Fats db 0 ; Number of fats +DirectoryEntries dw 0 ; Number of directory entries +Sectors dw 0 ; No. of sectors - no. of hidden sectors +Media db 0 ; Media byte +FatSectors dw 0 ; Number of fat sectors +SectorsPerTrack dw 0 ; Sectors per track +Heads dw 0 ; Number of surfaces +HiddenSectors dd 0 ; Number of hidden sectors +SectorsLong dd 0 ; Number of sectors iff Sectors = 0 +; +; The following is the rest of the NTFS Sector Zero information. +; 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 no. + +SectorZeroPad1 dw 0 +SectorsOnVolume db (size LARGE_INTEGER) dup (0) +MftStartLcn db (size LARGE_INTEGER) dup (0) +Mft2StartLcn db (size LARGE_INTEGER) dup (0) +ClustersPerFrs dd 0 +DefClustersPerBuf dd 0 +SerialNumber db (size LARGE_INTEGER) dup (0) +CheckSum dd 0 +; +; 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 + +;**************************************************************************** +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], 16 ; read boot area + 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. +_ntfsboot 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: + +.386 + mov eax, SectorBase + add eax, HiddenSectors + xor edx,edx +;EDX:EAX = absolute sector number + movzx ecx,word ptr SectorsPerTrack ; get into 32 bit value + div ecx ; (EDX) = sector within track, (EAX)=track + inc dl ; sector numbers are 1-based, not 0 + mov CurrentSector, dl + mov edx,eax + shr edx,16 +.286 + 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 dh, CurrentHead + mov dl, 80h ; should be DriveNumber, but... + + 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$ntc: + mov si,offset TXT_MSG_SYSINIT_NTLDR_CMPRS +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 ntfsboot.inc ;suck in the message text + + +ReservedForFuture DB 2 dup(?) ;reserve remaining bytes to prevent NLS + ;messages from using them + + .errnz ($-_ntfsboot) GT (512-2),<FATAL PROBLEM: first sector is too large> + + org 512-2 + db 55h,0aah + +; Name we look for. ntldr_length is the number of characters, +; ntldr_name is the name itself. Note that it is not NULL +; terminated, and doesn't need to be. +; +ntldr_name_length dw 5 +ntldr_name dw 'N', 'T', 'L', 'D', 'R' + +; Predefined name for index-related attributes associated with an +; index over $FILE_NAME +; +index_name_length dw 4 +index_name dw '$', 'I', '3', '0' + +; Global variables. These offsets are all relative to NewSeg. +; +AttrList dd 0e000h; Offset of buffer to hold attribute list +MftFrs dd 3000h; Offset of first MFT FRS +SegmentsInMft dd ? ; number of FRS's with MFT Data attribute records +RootIndexFrs dd ? ; Offset of Root Index FRS +AllocationIndexFrs dd ? ; Offset of Allocation Index FRS ; KPeery +BitmapIndexFrs dd ? ; Offset of Bitmap Index FRS ; KPeery +IndexRoot dd ? ; Offset of Root Index $INDEX_ROOT attribute +IndexAllocation dd ? ; Offset of Root Index $INDEX_ALLOCATION attribute +IndexBitmap dd ? ; Offset of Root Index $BITMAP attribute +NtldrFrs dd ? ; Offset of NTLDR FRS +NtldrData dd ? ; Offset of NTLDR $DATA attribute +IndexBlockBuffer dd ? ; Offset of current index buffer +IndexBitmapBuffer dd ? ; Offset of index bitmap buffer +NextBuffer dd ? ; Offset of next free byte in buffer space + +BytesPerCluster dd ? ; Bytes per cluster +BytesPerFrs dd ? ; Bytes per File Record Segment +SectorsPerFrs dd ? ; Sectors per File Record Segment +BytesPerIndexBlock dd ? ; Bytes per index alloc block in root index +ClustersPerIndexBlock dd ? ; Clusters per index alloc block in root index +SectorsPerIndexBlock dd ? ; Sectors per index block in root index + +.386 + +SAVE_ALL macro + + push es + push ds + pushad + +endm + +RESTORE_ALL macro + + popad + nop + pop ds + pop es + +endm + + +;**************************************************************************** +; +; mainboot - +; +; +mainboot proc far + +; Get the new ds and the new stack. Note that ss is zero. +; + mov ax, cs ; Set DS to CS + mov ds, ax + + shl ax, 4 ; convert to an offset. + cli + mov sp, ax ; load new stack, just before boot code. + sti + +; Set up the FRS buffers. The MFT buffer is in a fixed +; location, and the other three come right after it. The +; buffer for index allocation blocks comes after that. +; + +; Compute the useful constants associated with the volume +; + movzx eax, BytesPerSector ; eax = Bytes per Sector + movzx ebx, SectorsPerCluster ; ebx = Sectors Per Cluster + mul ebx ; eax = Bytes per Cluster + mov BytesPerCluster, eax + + mov ecx, ClustersPerFrs ; ecx = clusters per frs + cmp cl, 0 ; is ClustersPerFrs less than zero? + jg mainboot$1 + +; If the ClustersPerFrs field is negative, we calculate the number +; of bytes per FRS by negating the value and using that as a shif count. +; + + neg cl + mov eax, 1 + shl eax, cl ; eax = bytes per frs + jmp mainboot$2 + +mainboot$1: + +; Otherwise if ClustersPerFrs was positive, we multiply by bytes +; per cluster. + + mov eax, BytesPerCluster + mul ecx ; eax = bytes per frs + +mainboot$2: + + mov BytesPerFrs, eax + movzx ebx, BytesPerSector + xor edx, edx ; zero high part of dividend + div ebx ; eax = sectors per frs + mov SectorsPerFrs, eax + + +; Set up the MFT FRS's---this will read all the $DATA attribute +; records for the MFT. +; + + call SetupMft + +; Set up the remaining FRS buffers. The RootIndex FRS comes +; directly after the last MFT FRS, followed by the NTLdr FRS +; and the Index Block buffer. +; + mov ecx, NextBuffer + mov RootIndexFrs, ecx + + add ecx, BytesPerFrs ; AllocationFrs may be different + mov AllocationIndexFrs, ecx ; from RootIndexFrs - KPeery + + add ecx, BytesPerFrs ; BitmapFrs may be different + mov BitmapIndexFrs, ecx ; from RootIndexFrs - KPeery + + add ecx, BytesPerFrs + mov NtldrFrs, ecx + + add ecx, BytesPerFrs + mov IndexBlockBuffer, ecx + +; +; Read the root index, allocation index and bitmap FRS's and locate +; the interesting attributes. +; + + mov eax, $INDEX_ROOT + mov ecx, RootIndexFrs + call LoadIndexFrs + + or eax, eax + jz BootErr$he + + mov IndexRoot, eax ; offset in Frs buffer + + mov eax, $INDEX_ALLOCATION ; Attribute type code + mov ecx, AllocationIndexFrs ; FRS to search + call LoadIndexFrs + + mov IndexAllocation, eax + + mov eax, $BITMAP ; Attribute type code + mov ecx, BitmapIndexFrs ; FRS to search + call LoadIndexFrs + + mov IndexBitmap, eax + +; Consistency check: the index root must exist, and it +; must be resident. +; + mov eax, IndexRoot + or eax, eax + jz BootErr$he + + + cmp [eax].ATTR_FormCode, RESIDENT_FORM + jne BootErr$he + + +; Determine the size of the index allocation buffer based +; on information in the $INDEX_ROOT attribute. The index +; bitmap buffer comes immediately after the index block buffer. +; +; eax -> $INDEX_ROOT attribute record +; + lea edx, [eax].ATTR_FormUnion ; edx -> resident info + add ax, [edx].RES_ValueOffset ; eax -> value of $INDEX_ROOT + + movzx ecx, [eax].IR_ClustersPerBuffer + mov ClustersPerIndexBlock, ecx + + mov ecx, [eax].IR_BytesPerBuffer + mov BytesPerIndexBlock, ecx + + mov eax, BytesPerIndexBlock + movzx ecx, BytesPerSector + xor edx, edx + div ecx ; eax = sectors per index block + mov SectorsPerIndexBlock, eax + + mov eax, IndexBlockBuffer + add eax, BytesPerIndexBlock + mov IndexBitmapBuffer, eax + +; Next consistency check: if the $INDEX_ALLOCATION attribute +; exists, the $INDEX_BITMAP attribute must also exist. +; + cmp IndexAllocation, 0 + je mainboot30 + + cmp IndexBitmap, 0 ; since IndexAllocation exists, the + je BootErr$he ; bitmap must exist, too. + +; Since the bitmap exists, we need to read it into the bitmap +; buffer. If it's resident, we can just copy the data. +; + + mov ebx, IndexBitmap ; ebx -> index bitmap attribute + push ds + pop es + mov edi, IndexBitmapBuffer ; es:edi -> index bitmap buffer + + call ReadWholeAttribute + +mainboot30: +; +; OK, we've got the index-related attributes. +; + movzx ecx, ntldr_name_length ; ecx = name length in characters + mov eax, offset ntldr_name ; eax -> name + + call FindFile + + or eax, eax + jz BootErr$fnf + +; Read the FRS for NTLDR and find its data attribute. +; +; eax -> Index Entry for NTLDR. +; + mov eax, [eax].IE_FileReference.REF_LowPart + + + push ds + pop es ; es:edi = target buffer + mov edi, NtldrFrs + + call ReadFrs + + mov eax, NtldrFrs ; pointer to FRS + mov ebx, $DATA ; requested attribute type + mov ecx, 0 ; attribute name length in characters + mov edx, 0 ; attribute name (NULL if none) + + call LocateAttributeRecord + +; eax -> $DATA attribute for NTLDR +; + or eax, eax ; if eax is zero, attribute not found. + jz BootErr$fnf + +; Get the attribute record header flags, and make sure none of the +; `compressed' bits are set + + movzx ebx, [eax].ATTR_Flags + and ebx, ATTRIBUTE_FLAG_COMPRESSION_MASK + jnz BootErr$ntc + + mov ebx, eax ; ebx -> $DATA attribute for NTLDR + + push LdrSeg + pop es ; es = segment addres to read into + sub edi, edi ; es:edi = buffer address + + call ReadWholeAttribute + +; +; We've loaded NTLDR--jump to it. +; +; 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 + retf ; "return" to NTLDR. + + +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 +; +.286 +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 + +.386 +;**************************************************************************** +; +; ReadClusters - Reads a run of clusters from the disk. +; +; ENTRY: eax == LCN to read +; edx == clusters to read +; es:edi -> Target buffer +; +; USES: none (preserves all registers) +; +ReadClusters proc near + + SAVE_ALL + + mov ebx, edx ; ebx = clusters to read. + movzx ecx, SectorsPerCluster ; ecx = cluster factor + + mul ecx ; Convert LCN to sectors (wipes out edx!) + mov SectorBase, eax ; Store starting sector in SectorBase + + mov eax, ebx ; eax = number of clusters + mul ecx ; Convert EAX to sectors (wipes out edx!) + mov SectorCount, ax ; Store number of sectors in SectorCount + + +; Note that ReadClusters gets its target buffer in es:edi but calls +; the DoRead worker function that takes a target in es:bx--we need +; to normalize es:edi so that we don't overflow bx. +; + mov bx, di + and bx, 0Fh + mov ax, es + shr edi, 4 + add ax, di ; ax:bx -> target buffer + + push ax + pop es ; es:bx -> target buffer + + call DoRead + + RESTORE_ALL + ret + +ReadClusters endp + +; +;**************************************************************************** +; +; LocateAttributeRecord -- Find an attribute record in an FRS. +; +; ENTRY: EAX -- pointer to FRS +; EBX -- desired attribute type code +; ECX -- length of attribute name in characters +; EDX -- pointer to attribute name +; +; EXIT: EAX points at attribute record (0 indicates not found) +; +; USES: All +; +LocateAttributeRecord proc near + +; get the first attribute record. +; + add ax, word ptr[eax].FRS_FirstAttribute + +; eax -> next attribute record to investigate. +; ebx == desired type +; ecx == name length +; edx -> pointer to name +; +lar10: + cmp [eax].ATTR_TypeCode, 0ffffffffh + je lar99 + + cmp dword ptr[eax].ATTR_TypeCode, ebx + jne lar80 + +; this record is a potential match. Compare the names: +; +; eax -> candidate record +; ebx == desired type +; ecx == name length +; edx -> pointer to name +; + or ecx, ecx ; Did the caller pass in a name length? + jnz lar20 + +; We want an attribute with no name--the current record is +; a match if and only if it has no name. +; + cmp [eax].ATTR_NameLength, 0 + jne lar80 ; Not a match. + +; It's a match, and eax is set up correctly, so return. +; + ret + +; We want a named attribute. +; +; eax -> candidate record +; ebx == desired type +; ecx == name length +; edx -> pointer to name +; +lar20: + cmp cl, [eax].ATTR_NameLength + jne lar80 ; Not a match. + +; Convert name in current record to uppercase. +; + mov esi, eax + add si, word ptr[eax].ATTR_NameOffset + + call UpcaseName + +; eax -> candidate record +; ebx == desired type +; ecx == name length +; edx -> pointer to name +; esi -> Name in current record (upcased) +; + push ecx ; save cx + + push ds ; Copy data segment into es + pop es + mov edi, edx ; note that esi is already set up. + + repe cmpsw ; zero flag is set if equal + + pop ecx ; restore cx + + jnz lar80 ; not a match + +; eax points at a matching record. +; + ret + +; +; This record doesn't match; go on to the next. +; +; eax -> rejected candidate attribute record +; ebx == desired type +; ecx == Name length +; edx -> desired name +; +lar80: cmp [eax].ATTR_RecordLength, 0 ; if the record length is zero + je lar99 ; the FRS is corrupt. + + add eax, [eax].ATTR_RecordLength; Go to next record + jmp lar10 ; and try again + +; Didn't find it. +; +lar99: sub eax, eax + ret + +LocateAttributeRecord endp + +;**************************************************************************** +; +; LocateIndexEntry -- Find an index entry in a file name index +; +; ENTRY: EAX -> pointer to index header +; EBX -> file name to find +; ECX == length of file name in characters +; +; EXIT: EAX points at index entry. NULL to indicate failure. +; +; USES: All +; +LocateIndexEntry proc near + +; Convert the input name to upper-case +; + + mov esi, ebx + call UpcaseName + +; DEBUG CODE +; +; call PrintName +; call Debug2 +; +; END DEBUG CODE + + add eax, [eax].IH_FirstIndexEntry + +; EAX -> current entry +; EBX -> file name to find +; ECX == length of file name in characters +; +lie10: test [eax].IE_Flags, INDEX_ENTRY_END ; Is it the end entry? + jnz lie99 + + lea edx, [eax].IE_Value ; edx -> FILE_NAME attribute value + +; DEBUG CODE -- list file names as they are examined +; +; SAVE_ALL +; +; call Debug3 +; movzx ecx, [edx].FN_FileNameLength ; ecx = chars in name +; lea esi, [edx].FN_FileName ; esi -> name +; call PrintName +; +; RESTORE_ALL +; +; END DEBUG CODE + +; EAX -> current entry +; EBX -> file name to find +; ECX == length of file name in characters +; EDX -> FILE_NAME attribute +; + cmp cl, [edx].FN_FileNameLength ; Is name the right length? + jne lie80 + + lea esi, [edx].FN_FileName ; Get name from FILE_NAME structure + + call UpcaseName + + push ecx ; save ecx + + push ds + pop es ; copy data segment into es for cmpsw + mov edi, ebx ; edi->search name (esi already set up) + repe cmpsw ; zero flag is set if they're equal + + pop ecx ; restore ecx + + jnz lie80 + +; the current entry matches the search name, and eax points at it. +; + ret + +; The current entry is not a match--get the next one. +; EAX -> current entry +; EBX -> file name to find +; ECX == length of file name in characters +; +lie80: cmp [eax].IE_Length, 0 ; If the entry length is zero + je lie99 ; then the index block is corrupt. + + add ax, [eax].IE_Length ; Get the next entry. + + jmp lie10 + + +; Name not found in this block. Set eax to zero and return +; +lie99: xor eax, eax + ret + +LocateIndexEntry endp + +;**************************************************************************** +; +; ReadWholeAttribute - Read an entire attribute value +; +; ENTRY: ebx -> attribute +; es:edi -> target buffer +; +; USES: ALL +; +ReadWholeAttribute proc near + + cmp [ebx].ATTR_FormCode, RESIDENT_FORM + jne rwa10 + +; The attribute is resident. +; ebx -> attribute +; es:edi -> target buffer +; + + SAVE_ALL + + lea edx, [ebx].ATTR_FormUnion ; edx -> resident form info + mov ecx, [edx].RES_ValueLength ; ecx = bytes in value + mov esi, ebx ; esi -> attribute + add si, [edx].RES_ValueOffset ; esi -> attribute value + + rep movsb ; copy bytes from value to buffer + + RESTORE_ALL + + ret ; That's all! + +rwa10: +; +; The attribute type is non-resident. Just call +; ReadNonresidentAttribute starting at VCN 0 and +; asking for the whole thing. +; +; ebx -> attribute +; es:edi -> target buffer +; + lea edx, [ebx].ATTR_FormUnion ; edx -> nonresident form info + mov ecx, [edx].NONRES_HighestVcn.LowPart; ecx = HighestVcn + inc ecx ; ecx = clusters in attribute + + sub eax, eax ; eax = 0 (first VCN to read) + + call ReadNonresidentAttribute + + ret + +ReadWholeAttribute endp + +;**************************************************************************** +; +; ReadNonresidentAttribute - Read clusters from a nonresident attribute +; +; ENTRY: EAX == First VCN to read +; EBX -> Attribute +; ECX == Number of clusters to read +; ES:EDI == Target of read +; +; EXIT: None. +; +; USES: None (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +ReadNonresidentAttribute proc near + + SAVE_ALL + + cmp [ebx].ATTR_FormCode, NONRESIDENT_FORM + je ReadNR10 + +; This attribute is not resident--the disk is corrupt. + + jmp BootErr$he + + +ReadNR10: +; eax == Next VCN to read +; ebx -> Attribute +; ecx -> Remaining clusters to read +; es:edi -> Target of read +; + + cmp ecx, 0 + jne ReadNR20 + +; Nothing left to read--return success. +; + RESTORE_ALL + ret + +ReadNR20: + push ebx ; pointer to attribute + push eax ; Current VCN + + push ecx + push edi + push es + + call ComputeLcn ; eax = LCN to read, ecx = run length + mov edx, ecx ; edx = remaining run length + + pop es + pop edi + pop ecx + + +; eax == LCN to read +; ecx == remaining clusters to read +; edx == remaining clusters in current run +; es:edi == Target of read +; TOS == Current VCN +; TOS + 4 == pointer to attribute +; + cmp ecx, edx + jge ReadNR30 + +; Run length is greater than remaining request; only read +; remaining request. +; + mov edx, ecx ; edx = Remaining request + +ReadNR30: +; eax == LCN to read +; ecx == remaining clusters to read +; edx == clusters to read in current run +; es:edi == Target of read +; TOS == Current VCN +; TOS + == pointer to attribute +; + + call ReadClusters + + sub ecx, edx ; Decrement clusters remaining in request + mov ebx, edx ; ebx = clusters read + + mov eax, edx ; eax = clusters read + movzx edx, SectorsPerCluster + mul edx ; eax = sectors read (wipes out edx!) + movzx edx, BytesPerSector + mul edx ; eax = bytes read (wipes out edx!) + + add edi, eax ; Update target of read + + pop eax ; eax = previous VCN + add eax, ebx ; update VCN to read + + pop ebx ; ebx -> attribute + jmp ReadNR10 + + +ReadNonresidentAttribute endp + +;**************************************************************************** +; +; ReadIndexBlockSectors - Read sectors from an index allocation attribute +; +; ENTRY: EAX == First VBN to read +; EBX -> Attribute +; ECX == Number of sectors to read +; ES:EDI == Target of read +; +; EXIT: None. +; +; USES: None (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +ReadIndexBlockSectors proc near + + SAVE_ALL + + cmp [ebx].ATTR_FormCode, NONRESIDENT_FORM + je ReadIBS_10 + +; This attribute is resident--the disk is corrupt. + + jmp BootErr$he + + +ReadIBS_10: +; eax == Next VBN to read +; ebx -> Attribute +; ecx -> Remaining sectors to read +; es:edi -> Target of read +; + + cmp ecx, 0 + jne ReadIBS_20 + +; Nothing left to read--return success. +; + + + RESTORE_ALL + ret + +ReadIBS_20: + push ebx ; pointer to attribute + push eax ; Current VBN + + push ecx + push edi + push es + + ; Convert eax from a VBN back to a VCN by dividing by SectorsPerCluster. + ; The remainder of this division is the sector offset in the cluster we + ; want. Then use the mapping information to get the LCN for this VCN, + ; then multiply to get back to LBN. + ; + + push ecx ; save remaining sectors in request + + xor edx, edx ; zero high part of dividend + movzx ecx, SectorsPerCluster + div ecx ; edx = remainder + push edx ; save remainder + + call ComputeLcn ; eax = LCN to read, ecx = remaining run length + + movzx ebx, SectorsPerCluster + mul ebx ; eax = LBN of cluster, edx = 0 + pop edx ; edx = remainder + add eax, edx ; eax = LBN we want + push eax ; save LBN + + movzx eax, SectorsPerCluster + mul ecx ; eax = remaining run length in sectors, edx = 0 + mov edx, eax ; edx = remaining run length + + pop eax ; eax = LBN + pop ecx ; ecx = remaining sectors in request + + pop es + pop edi + pop ecx + + +; eax == LBN to read +; ecx == remaining sectors to read +; edx == remaining sectors in current run +; es:edi == Target of read +; TOS == Current VCN +; TOS + 4 == pointer to attribute +; + cmp ecx, edx + jge ReadIBS_30 + +; Run length is greater than remaining request; only read +; remaining request. +; + mov edx, ecx ; edx = Remaining request + +ReadIBS_30: +; eax == LBN to read +; ecx == remaining sectors to read +; edx == sectors to read in current run +; es:edi == Target of read +; TOS == Current VCN +; TOS + == pointer to attribute +; + + mov SectorBase, eax + mov SectorCount, dx + +; We have a pointer to the target buffer in es:edi, but we want that +; in es:bx for DoRead. +; + + SAVE_ALL + + mov bx, di + and bx, 0Fh + mov ax, es + shr edi, 4 + add ax, di ; ax:bx -> target buffer + + push ax + pop es ; es:bx -> target buffer + + call DoRead + + RESTORE_ALL + + sub ecx, edx ; Decrement sectors remaining in request + mov ebx, edx ; ebx = sectors read + + mov eax, edx ; eax = sectors read + movzx edx, BytesPerSector + mul edx ; eax = bytes read (wipes out edx!) + + add edi, eax ; Update target of read + + pop eax ; eax = previous VBN + add eax, ebx ; update VBN to read + + pop ebx ; ebx -> attribute + jmp ReadIBS_10 + + +ReadIndexBlockSectors endp + + +;**************************************************************************** +; +; MultiSectorFixup - fixup a structure read off the disk +; to reflect Update Sequence Array. +; +; ENTRY: ES:EDI = Target buffer +; +; USES: none (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +; Note: ES:EDI must point at a structure which is protected +; by an update sequence array, and which begins with +; a multi-sector-header structure. +; +MultiSectorFixup proc near + + SAVE_ALL + + movzx ebx, es:[edi].MSH_UpdateArrayOfs ; ebx = update array offset + movzx ecx, es:[edi].MSH_UpdateArraySize ; ecx = update array size + + or ecx, ecx ; if the size of the update sequence array + jz BootErr$he ; is zero, this structure is corrupt. + + add ebx, edi ; es:ebx -> update sequence array count word + add ebx, 2 ; es:ebx -> 1st entry of update array + + add edi, SEQUENCE_NUMBER_STRIDE - 2 ; es:edi->last word of first chunk + dec ecx ; decrement to reflect count word + +MSF10: + +; ecx = number of entries remaining in update sequence array +; es:ebx -> next entry in update sequence array +; es:edi -> next target word for update sequence array + + or ecx, ecx + jz MSF30 + + mov ax, word ptr es:[ebx] ; copy next update sequence array entry + mov word ptr es:[edi], ax ; to next target word + + add ebx, 2 ; go on to next entry + add edi, SEQUENCE_NUMBER_STRIDE ; go on to next target + + dec ecx + + + jmp MSF10 + +MSF30: + + RESTORE_ALL + + ret + +MultiSectorFixup endp + +;**************************************************************************** +; +; SetupMft - Reads MFT File Record Segments into memory. +; +; ENTRY: none. +; +; EXIT: NextBuffer is set to the free byte after the last MFT FRS +; SegmentsInMft is initialized +; +; +SetupMft proc near + + SAVE_ALL + +; Initialize SegmentsInMft and NextBuffer as if the MFT +; had only one FRS. +; + mov eax, 1 + mov SegmentsInMft, eax + + mov eax, MftFrs + add eax, BytesPerFrs + mov NextBuffer, eax + +; Read FRS 0 into the first MFT FRS buffer, being sure +; to resolve the Update Sequence Array. +; + + mov eax, MftStartLcn.LowPart + movzx ebx, SectorsPerCluster + mul ebx ; eax = mft starting sector + mov SectorBase, eax ; SectorBase = mft starting sector + + mov eax, SectorsPerFrs + mov SectorCount, ax ; SectorCount = SectorsPerFrs + + mov ebx, MftFrs + + push ds + pop es + + call DoRead + movzx edi, bx ; es:edi = buffer + call MultiSectorFixup + +; Determine whether the MFT has an Attribute List attribute + + mov eax, MftFrs + mov ebx, $ATTRIBUTE_LIST + mov ecx, 0 + mov edx, 0 + + call LocateAttributeRecord + + or eax, eax ; If there's no Attribute list, + jz SetupMft99 ; we're done! + +; Read the attribute list. +; eax -> attribute list attribute +; + mov ebx, eax ; ebx -> attribute list attribute + push ds + pop es ; copy ds into es + mov edi, AttrList ; ds:edi->attribute list buffer + + call ReadWholeAttribute + + mov ebx, AttrList ; ebx -> first attribute list entry + +; Now, traverse the attribute list looking for the first +; entry for the $DATA type. We know it must have at least +; one. +; +; ebx -> first attribute list entry +; +SetupMft10: + cmp [ebx].ATTRLIST_TypeCode, $DATA + je SetupMft20 + + add bx,[ebx].ATTRLIST_Length + jmp SetupMft10 + + +SetupMft20: +; Scan forward through the attribute list entries for the +; $DATA attribute, reading each referenced FRS. Note that +; there will be at least one non-$DATA entry after the entries +; for the $DATA attribute, since there's a $BITMAP. +; +; ebx -> Next attribute list entry +; NextBuffer -> Target for next read +; SegmentsInMft == number of MFT segments read so far +; + cmp [ebx].ATTRLIST_TypeCode, $DATA + jne SetupMft99 + +; Read the FRS referred to by this attribute list entry into +; the next buffer, and increment NextBuffer and SegmentsInMft. +; + push ebx + + mov eax, [ebx].ATTRLIST_SegmentReference.REF_LowPart + mov edi, NextBuffer + push ds + pop es ; copy ds into es + + call ReadFrs + + pop ebx + +; Increment NextBuffer and SegmentsInMft + + mov eax, BytesPerFrs + add NextBuffer, eax + + inc SegmentsInMft + +; Go on to the next attribute list entry + + add bx, [ebx].ATTRLIST_Length + jmp SetupMft20 + +SetupMft99: + + RESTORE_ALL + ret + +SetupMft endp + +;**************************************************************************** +; +; ComputeMftLcn -- Computes the LCN for a cluster of the MFT +; +; +; ENTRY: EAX == VCN +; +; EXIT: EAX == LCN +; +; USES: ALL +; +ComputeMftLcn proc near + + mov edx, eax ; edx = VCN + + mov ecx, SegmentsInMft ; ecx = # of FRS's to search + mov eax, MftFrs ; eax -> first FRS to search + +MftLcn10: +; EAX -> Next FRS to search +; ECX == number of remaining FRS's to search +; EDX == VCN +; + push edx + push eax + push ecx + push edx ; Yes, I meant to push it twice + + mov ebx, $DATA + mov ecx, 0 + mov edx, 0 + + call LocateAttributeRecord + +; EAX -> $DATA attribute +; TOS == VCN +; TOS + 4 == number of remaining FRS's to search +; TOS + 8 -> FRS being searched +; TOS +12 == VCN + + or eax, eax + jz BootErr$he ; No $DATA attribute in this FRS! + + mov ebx, eax ; ebx -> attribute + pop eax ; eax = VCN + +; EAX == VCN +; EBX -> $DATA attribute +; TOS number of remaining FRS's to search +; TOS + 4 == FRS being searched +; TOS + 8 == VCN + + call ComputeLcn + + or eax, eax + jz MftLcn20 + +; Found our LCN. Clean up the stack and return. +; +; EAX == LCN +; TOS number of remaining FRS's to search +; TOS + 4 == FRS being searched +; TOS + 8 == VCN +; + pop ebx + pop ebx + pop ebx ; clean up the stack + + ret + +MftLcn20: +; +; Didn't find the VCN in this FRS; try the next one. +; +; TOS number of remaining FRS's to search +; TOS + 4 -> FRS being searched +; TOS + 8 == VCN +; + pop ecx ; ecx = number of FRS's remaining, including current + pop eax ; eax -> current FRS + pop edx ; edx = VCN + + add eax, BytesPerFrs ; eax -> next FRS + loop MftLcn10 ; decrement ecx and try next FRS + +; This VCN was not found. +; + xor eax, eax + ret + + +ComputeMftLcn endp + +;**************************************************************************** +; +; ReadMftSectors - Read sectors from the MFT +; +; ENTRY: EAX == starting VBN +; ECX == number of sectors to read +; ES:EDI == Target buffer +; +; USES: none (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +ReadMftSectors proc near + + SAVE_ALL + +RMS$Again: + + push eax ; save starting VBN + push ecx ; save sector count + + +; Divide the VBN by SectorsPerCluster to get the VCN + + xor edx, edx ; zero high part of dividend + movzx ebx, SectorsPerCluster + div ebx ; eax = VCN + push edx ; save remainder + + call ComputeMftLcn ; eax = LCN + + or eax, eax ; LCN equal to zero? + jz BootErr$he ; zero is not a possible LCN + +; Change the LCN back into a LBN and add the remainder back in to get +; the sector we want to read, which goes into SectorBase. +; + + movzx ebx, SectorsPerCluster + mul ebx ; eax = cluster first LBN + pop edx ; edx = sector remainder + add eax, edx ; eax = desired LBN + + mov SectorBase, eax + +; +; Figure out how many sectors to read this time; we never attempt +; to read more than one cluster at a time. +; + + pop ecx ; ecx = sectors to read + + movzx ebx, SectorsPerCluster + cmp ecx,ebx + jle RMS10 + +; +; Read only a single cluster at a time, to avoid problems with fragmented +; runs in the mft. +; + + mov SectorCount, bx ; this time read 1 cluster + sub ecx, ebx ; ecx = sectors remaining to read + + pop eax ; eax = VBN + add eax, ebx ; VBN += sectors this read + + + push eax ; save next VBN + push ecx ; save remaining sector count + + + + jmp RMS20 + +RMS10: + + pop eax ; eax = VBN + add eax, ecx ; VBN += sectors this read + push eax ; save next VBN + + mov SectorCount, cx + mov ecx, 0 + push ecx ; save remaining sector count (0) + +RMS20: + + +; The target buffer was passed in es:edi, but we want it in es:bx. +; Do the conversion. +; + + push es ; save buffer pointer + push edi + + mov bx, di + and bx, 0Fh + mov ax, es + shr edi, 4 + add ax, di ; ax:bx -> target buffer + + push ax + pop es ; es:bx -> target buffer + + call DoRead + + pop edi ; restore buffer pointer + pop es + + add edi, BytesPerCluster ; increment buf ptr by one cluster + + pop ecx ; restore remaining sector count + pop eax ; restore starting VBN + + cmp ecx, 0 ; are we done? + jg RMS$Again ; repeat until desired == 0 + + + RESTORE_ALL + ret + +ReadMftSectors endp + + +;**************************************************************************** +; +; ReadFrs - Read an FRS +; +; ENTRY: EAX == FRS number +; ES:EDI == Target buffer +; +; USES: none (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +ReadFrs proc near + + SAVE_ALL + + mul SectorsPerFrs ; eax = sector number in MFT DATA attribute + ; (note that mul wipes out edx!) + + mov ecx, SectorsPerFrs ; number of sectors to read + + call ReadMftSectors + call MultiSectorFixup + + RESTORE_ALL + ret + +ReadFrs endp + +;**************************************************************************** +; +; ReadIndexBlock - read an index block from the root index. +; +; ENTRY: EAX == Block number +; +; USES: none (preserves all registers with SAVE_ALL/RESTORE_ALL) +; +ReadIndexBlock proc near + + SAVE_ALL + + mul SectorsPerIndexBlock ; eax = first VBN to read + ; (note that mul wipes out edx!) + mov ebx, IndexAllocation ; ebx -> $INDEX_ALLOCATION attribute + mov ecx, SectorsPerIndexBlock ; ecx == Sectors to read + + push ds + pop es + mov edi, IndexBlockBuffer ; es:edi -> index block buffer + + call ReadIndexBlockSectors + call MultiSectorFixup + + RESTORE_ALL + ret + +ReadIndexBlock endp + +;**************************************************************************** +; +; IsBlockInUse - Checks the index bitmap to see if an index +; allocation block is in use. +; +; ENTRY: EAX == block number +; +; EXIT: Carry flag clear if block is in use +; Carry flag set if block is not in use. +; +IsBlockInUse proc near + + push eax + push ebx + push ecx + + mov ebx, IndexBitmapBuffer + + mov ecx, eax ; ecx = block number + shr eax, 3 ; eax = byte number + and ecx, 7 ; ecx = bit number in byte + + add ebx, eax ; ebx -> byte to test + + mov eax, 1 + shl eax, cl ; eax = mask + + test byte ptr[ebx], al + + jz IBU10 + + clc ; Block is not in use. + jmp IBU20 + +IBU10: stc ; Block is in use. + +IBU20: + pop ecx + pop ebx + pop eax ; restore registers + + ret + +IsBlockInUse endp + +;**************************************************************************** +; +; ComputeLcn - Converts a VCN into an LCN +; +; ENTRY: EAX -> VCN +; EBX -> Attribute +; +; EXIT: EAX -> LCN (zero indicates not found) +; ECX -> Remaining run length +; +; USES: ALL. +; +ComputeLcn proc near + + cmp [ebx].ATTR_FormCode, NONRESIDENT_FORM + je clcn10 + + sub eax, eax ; This is a resident attribute. + ret + +clcn10: lea esi, [ebx].ATTR_FormUnion ; esi -> nonresident info of attrib + +; eax -> VCN +; ebx -> Attribute +; esi -> Nonresident information of attribute record +; +; See if the desired VCN is in range. + + mov edx, [esi].NONRES_HighestVcn.LowPart ; edx = HighestVcn + cmp eax, edx + ja clcn15 ; VCN is greater than HighestVcn + + mov edx, [esi].NONRES_LowestVcn.LowPart ; edx = LowestVcn + cmp eax, edx + jae clcn20 + +clcn15: + sub eax, eax ; VCN is not in range + ret + +clcn20: +; eax -> VCN +; ebx -> Attribute +; esi -> Nonresident information of attribute record +; edx -> LowestVcn +; + add bx, [esi].NONRES_MappingPairOffset ; ebx -> mapping pairs + sub esi, esi ; esi = 0 + +clcn30: +; eax == VCN to find +; ebx -> Current mapping pair count byte +; edx == Current VCN +; esi == Current LCN +; + cmp byte ptr[ebx], 0 ; if count byte is zero... + je clcn99 ; ... we're done (and didn't find it) + +; Update CurrentLcn +; + call LcnFromMappingPair + add esi, ecx ; esi = current lcn for this mapping pair + + call VcnFromMappingPair + +; eax == VCN to find +; ebx -> Current mapping pair count byte +; ecx == DeltaVcn for current mapping pair +; edx == Current VCN +; esi == Current LCN +; + add ecx, edx ; ecx = NextVcn + + cmp eax, ecx ; If target < NextVcn ... + jl clcn80 ; ... we found the right mapping pair. + +; Go on to next mapping pair. +; + mov edx, ecx ; CurrentVcn = NextVcn + + push eax + + movzx ecx, byte ptr[ebx] ; ecx = count byte + mov eax, ecx ; eax = count byte + and eax, 0fh ; eax = number of vcn bytes + shr ecx, 4 ; ecx = number of lcn bytes + + add ebx, ecx + add ebx, eax + inc ebx ; ebx -> next count byte + + pop eax + jmp clcn30 + +clcn80: +; We found the mapping pair we want. +; +; eax == target VCN +; ebx -> mapping pair count byte +; edx == Starting VCN of run +; ecx == Next VCN (ie. start of next run) +; esi == starting LCN of run +; + sub ecx, eax ; ecx = remaining run length + sub eax, edx ; eax = offset into run + add eax, esi ; eax = LCN to return + + ret + +; The target VCN is not in this attribute. + +clcn99: sub eax, eax ; Not found. + ret + + +ComputeLcn endp + +;**************************************************************************** +; +; VcnFromMappingPair +; +; ENTRY: EBX -> Mapping Pair count byte +; +; EXIT: ECX == DeltaVcn from mapping pair +; +; USES: ECX +; +VcnFromMappingPair proc near + + sub ecx, ecx ; ecx = 0 + mov cl, byte ptr[ebx] ; ecx = count byte + and cl, 0fh ; ecx = v + + cmp ecx, 0 ; if ecx is zero, volume is corrupt. + jne VFMP5 + + sub ecx, ecx + ret + +VFMP5: + push ebx + push edx + + add ebx, ecx ; ebx -> last byte of compressed vcn + + movsx edx, byte ptr[ebx] + dec ecx + dec ebx + +; ebx -> Next byte to add in +; ecx == Number of bytes remaining +; edx == Accumulated value +; +VFMP10: cmp ecx, 0 ; When ecx == 0, we're done. + je VFMP20 + + shl edx, 8 + mov dl, byte ptr[ebx] + + dec ebx ; Back up through bytes to process. + dec ecx ; One less byte to process. + + jmp VFMP10 + +VFMP20: +; edx == Accumulated value to return + + mov ecx, edx + + pop edx + pop ebx + + ret + +VcnFromMappingPair endp + + +;**************************************************************************** +; +; LcnFromMappingPair +; +; ENTRY: EBX -> Mapping Pair count byte +; +; EXIT: ECX == DeltaLcn from mapping pair +; +; USES: ECX +; +LcnFromMappingPair proc near + + push ebx + push edx + + sub edx, edx ; edx = 0 + mov dl, byte ptr[ebx] ; edx = count byte + and edx, 0fh ; edx = v + + sub ecx, ecx ; ecx = 0 + mov cl, byte ptr[ebx] ; ecx = count byte + shr cl, 4 ; ecx = l + + cmp ecx, 0 ; if ecx is zero, volume is corrupt. + jne LFMP5 + + sub ecx, ecx + + pop edx + pop ebx + ret + +LFMP5: +; ebx -> count byte +; ecx == l +; edx == v +; + + add ebx, edx ; ebx -> last byte of compressed vcn + add ebx, ecx ; ebx -> last byte of compressed lcn + + movsx edx, byte ptr[ebx] + dec ecx + dec ebx + +; ebx -> Next byte to add in +; ecx == Number of bytes remaining +; edx == Accumulated value +; +LFMP10: cmp ecx, 0 ; When ecx == 0, we're done. + je LFMP20 + + shl edx, 8 + mov dl, byte ptr[ebx] + + dec ebx ; Back up through bytes to process. + dec ecx ; One less byte to process. + + jmp LFMP10 + +LFMP20: +; edx == Accumulated value to return + + mov ecx, edx + + pop edx + pop ebx + + ret + +LcnFromMappingPair endp + +;**************************************************************************** +; +; UpcaseName - Converts the name of the file to all upper-case +; +; ENTRY: ESI -> Name +; ECX -> Length of name +; +; USES: none +; +UpcaseName proc near + + + or ecx, ecx + jnz UN5 + + ret + +UN5: + push ecx + push esi + +UN10: + cmp word ptr[esi], 'a' ; if it's less than 'a' + jl UN20 ; leave it alone + + cmp word ptr[esi], 'z' ; if it's greater than 'z' + jg UN20 ; leave it alone. + + sub word ptr[esi], 'a'-'A' ; the letter is lower-case--convert it. +UN20: + add esi, 2 ; move on to next unicode character + loop UN10 + + pop esi + pop ecx + + ret +UpcaseName endp + +;**************************************************************************** +; +; FindFile - Locates the index entry for a file in the root index. +; +; ENTRY: EAX -> name to find +; ECX == length of file name in characters +; +; EXIT: EAX -> Index Entry. NULL to indicate failure. +; +; USES: ALL +; +FindFile proc near + + push eax ; name address + push ecx ; name length + +; First, search the index root. +; +; eax -> name to find +; ecx == name length +; TOS == name length +; TOS+4 -> name to find +; + mov edx, eax ; edx -> name to find + mov eax, IndexRoot ; eax -> &INDEX_ROOT attribute + lea ebx, [eax].ATTR_FormUnion ; ebx -> resident info + add ax, [ebx].RES_ValueOffset ; eax -> Index Root value + + lea eax, [eax].IR_IndexHeader ; eax -> Index Header + + mov ebx, edx ; ebx -> name to find + + call LocateIndexEntry + + or eax, eax + jz FindFile20 + +; Found it in the root! The result is already in eax. +; Clean up the stack and return. +; + pop ecx + pop ecx + ret + +FindFile20: +; +; We didn't find the index entry we want in the root, so we have to +; crawl through the index allocation buffers. +; +; TOS == name length +; TOS+4 -> name to find +; + mov eax, IndexAllocation + or eax, eax + jnz FindFile30 + +; There is no index allocation attribute; clean up +; the stack and return failure. +; + pop ecx + pop ecx + xor eax, eax + ret + +FindFile30: +; +; Search the index allocation blocks for the name we want. +; Instead of searching in tree order, we'll just start with +; the last one and work our way backwards. +; +; TOS == name length +; TOS+4 -> name to find +; + mov edx, IndexAllocation ; edx -> index allocation attr. + lea edx, [edx].ATTR_FormUnion ; edx -> nonresident form info + mov eax, [edx].NONRES_HighestVcn.LowPart; eax = HighestVcn + inc eax ; eax = clusters in attribute + + mov ebx, BytesPerCluster + mul ebx ; eax = bytes in attribute + + xor edx, edx + div BytesPerIndexBlock ; convert bytes to index blocks + + push eax ; number of blocks to process + +FindFile40: +; +; TOS == remaining index blocks to search +; TOS + 4 == name length +; TOS + 8 -> name to find +; + pop eax ; eax == number of remaining blocks + + or eax, eax + jz FindFile90 + + dec eax ; eax == number of next block to process + ; and number of remaining blocks + + push eax + +; eax == block number to process +; TOS == remaining index blocks to search +; TOS + 4 == name length +; TOS + 8 -> name to find +; +; See if the block is in use; if not, go on to next. + + call IsBlockInUse + jc FindFile40 ; c set if not in use + +; eax == block number to process +; TOS == remaining index blocks to search +; TOS + 4 == name length +; TOS + 8 -> name to find +; + + call ReadIndexBlock + + pop edx ; edx == remaining buffers to search + pop ecx ; ecx == name length + pop ebx ; ebx -> name + + push ebx + push ecx + push edx + +; ebx -> name to find +; ecx == name length in characters +; TOS == remaining blocks to process +; TOS + 4 == name length +; TOS + 8 -> name +; +; Index buffer to search is in index allocation block buffer. +; + mov eax, IndexBlockBuffer ; eax -> Index allocation block + lea eax, [eax].IB_IndexHeader ; eax -> Index Header + + call LocateIndexEntry ; eax -> found entry + + or eax, eax + jz FindFile40 + +; Found it! +; +; eax -> Found entry +; TOS == remaining blocks to process +; TOS + 4 == name length +; TOS + 8 -> name +; + pop ecx + pop ecx + pop ecx ; clean up stack + ret + +FindFile90: +; +; Name not found. +; +; TOS == name length +; TOS + 4 -> name to find +; + pop ecx + pop ecx ; clean up stack. + xor eax, eax ; zero out eax. + ret + + +FindFile endp + +;**************************************************************************** +; +; DumpIndexBlock - dumps the index block buffer +; +DumpIndexBlock proc near + + SAVE_ALL + + mov esi, IndexBlockBuffer + + mov ecx, 20h ; dwords to dump + +DIB10: + + test ecx, 3 + jnz DIB20 + call DebugNewLine + +DIB20: + + lodsd + call PrintNumber + loop DIB10 + + RESTORE_ALL + ret + +DumpIndexBlock endp + +;**************************************************************************** +; +; DebugNewLine +; +DebugNewLine proc near + + SAVE_ALL + + xor eax, eax + xor ebx, ebx + + mov al, 0dh + mov ah, 14 + mov bx, 7 + int 10h + + mov al, 0ah + mov ah, 14 + mov bx, 7 + int 10h + + RESTORE_ALL + ret + +DebugNewLine endp + + +;**************************************************************************** +; +; PrintName - Display a unicode name +; +; ENTRY: DS:ESI -> null-terminated string +; ECX == characters in string +; +; USES: None. +; +PrintName proc near + + + SAVE_ALL + + or ecx, ecx + jnz PrintName10 + + call DebugNewLine + + RESTORE_ALL + + ret + +PrintName10: + + xor eax, eax + xor ebx, ebx + + lodsw + + mov ah, 14 ; write teletype + mov bx, 7 ; attribute + int 10h ; print it + loop PrintName10 + + call DebugNewLine + + RESTORE_ALL + ret + +PrintName endp + +;**************************************************************************** +; +; DebugPrint - Display a debug string. +; +; ENTRY: DS:SI -> null-terminated string +; +; USES: None. +; +.286 +DebugPrint proc near + + pusha + +DbgPr20: + + lodsb + cmp al, 0 + je DbgPr30 + + mov ah, 14 ; write teletype + mov bx, 7 ; attribute + int 10h ; print it + jmp DbgPr20 + +DbgPr30: + + popa + nop + ret + +DebugPrint endp + +;**************************************************************************** +; +; +; PrintNumber +; +; ENTRY: EAX == number to print +; +; PRESERVES ALL REGISTERS +; +.386 +PrintNumber proc near + + + SAVE_ALL + + mov ecx, 8 ; number of digits in a DWORD + +PrintNumber10: + + mov edx, eax + and edx, 0fh ; edx = lowest-order digit + push edx ; put it on the stack + shr eax, 4 ; drop low-order digit + loop PrintNumber10 + + mov ecx, 8 ; number of digits on stack. + +PrintNumber20: + + pop eax ; eax = next digit to print + cmp eax, 9 + jg PrintNumber22 + + add eax, '0' + jmp PrintNumber25 + +PrintNumber22: + + sub eax, 10 + add eax, 'A' + +PrintNumber25: + + xor ebx, ebx + + mov ah, 14 + mov bx, 7 + int 10h + loop PrintNumber20 + +; Print a space to separate numbers + + mov al, ' ' + mov ah, 14 + mov bx, 7 + int 10h + + RESTORE_ALL + + call Pause + + ret + +PrintNumber endp + + +;**************************************************************************** +; +; Debug0 - Print debug string 0 -- used for checkpoints in mainboot +; +Debug0 proc near + + SAVE_ALL + + mov esi, offset DbgString0 + call BootErr$Print + + RESTORE_ALL + + ret + +Debug0 endp + +;**************************************************************************** +; +; Debug1 - Print debug string 1 -- +; +Debug1 proc near + + SAVE_ALL + + mov esi, offset DbgString1 + call BootErr$Print + + RESTORE_ALL + + ret + +Debug1 endp + +;**************************************************************************** +; +; Debug2 - Print debug string 2 +; +Debug2 proc near + + SAVE_ALL + + mov esi, offset DbgString2 + call BootErr$Print + + RESTORE_ALL + + ret + +Debug2 endp + +;**************************************************************************** +; +; Debug3 - Print debug string 3 -- +; +Debug3 proc near + + SAVE_ALL + + mov esi, offset DbgString3 + call BootErr$Print + + RESTORE_ALL + + ret + +Debug3 endp + +;**************************************************************************** +; +; Debug4 - Print debug string 4 +; +Debug4 proc near + + SAVE_ALL + + mov esi, offset DbgString4 + call BootErr$Print + + RESTORE_ALL + + ret + +Debug4 endp + +;**************************************************************************** +; +; Pause - Pause for about 1/2 a second. Simply count until you overlap +; to zero. +; +Pause proc near + + push eax + mov eax, 0fff50000h + +PauseLoopy: + inc eax + + or eax, eax + jnz PauseLoopy + + pop eax + ret + +Pause endp + + +;************************************************************************* +; +; LoadIndexFrs - For the requested index type code locate and +; load the associated Frs. +; +; ENTRY: EAX - requested index type code +; ECX - Points to empty Frs buffer +; +; EXIT: EAX - points to offset in Frs buffer of requested index type +; code or Zero if not found. +; USES: All +; +LoadIndexFrs proc near + + push ecx ; save FRS buffer for later + push eax ; save index type code for later + + mov eax, ROOT_FILE_NAME_INDEX_NUMBER + push ds + pop es + mov edi, ecx ; es:edi = target buffer + + call ReadFrs + + mov eax, ecx ; FRS to search + + pop ebx ; Attribute type code + push ebx + movzx ecx, index_name_length ; Attribute name length + mov edx, offset index_name ; Attribute name + + call LocateAttributeRecord + + pop ebx + pop ecx + + or eax, eax + jnz LoadIndexFrs$Exit ; if found in root return + +; +; if not found in current Frs, search in attribute list +; + ; EBX - holds Attribute type code + mov eax, ecx ; FRS to search + mov ecx, ebx ; type code + push eax ; save Frs + push ebx ; save type code + + call SearchAttrList ; search attribute list for FRN + ; of specified ($INDEX_ROOT, + ; $INDEX_ALLOCATION, or $BITMAP) + + ; EAX - holds FRN for Frs, or Zero + + pop ebx ; Attribute type code (used later) + pop edi ; es:edi = target buffer + + or eax, eax ; if we cann't find it in attribute + jz LoadIndexFrs$Exit ; list then we are hosed + + +; We should now have the File Record Number where the index for the +; specified type code we are searching for is, load this into the +; Frs target buffer. +; +; EAX - holds FRN +; EBX - holds type code +; EDI - holds target buffer + + push ds + pop es + + call ReadFrs + +; +; Now determine the offset in the Frs of the index +; + +; EBX - holds type code + + mov eax, edi ; Frs to search + movzx ecx, index_name_length ; Attribute name length + mov edx, offset index_name ; Attribute name + + call LocateAttributeRecord + +; EAX - holds offset or Zero. + + +LoadIndexFrs$Exit: + ret + +LoadIndexFrs endp + + +;**************************************************************************** +; +; SearchAttrList +; +; Search the Frs for the attribute list. Then search the attribute list +; for the specifed type code. When you find it return the FRN in the +; attribute list entry found or Zero if no match found. +; +; ENTRY: ECX - type code to search attrib list for +; EAX - Frs buffer holding head of attribute list +; EXIT: EAX - FRN file record number to load, Zero if none. +; +; USES: All +; +SearchAttrList proc near + + push ecx ; type code to search for in + ; attrib list + + ; EAX - holds Frs to search + mov ebx, $ATTRIBUTE_LIST ; Attribute type code + mov ecx, 0 ; Attribute name length + mov edx, 0 ; Attribute name + + call LocateAttributeRecord + + or eax, eax ; If there's no Attribute list, + jz SearchAttrList$NotFoundIndex1 ; We are done + +; Read the attribute list. +; eax -> attribute list attribute + + mov ebx, eax ; ebx -> attribute list attribute + push ds + pop es ; copy ds into es + mov edi, AttrList ; ds:edi->attribute list buffer + + call ReadWholeAttribute + + push ds + pop es + mov ebx, AttrList ; es:ebx -> first attribute list entry + +; Now, traverse the attribute list looking for the entry for +; the Index type code. +; +; ebx -> first attribute list entry +; + + pop ecx ; Get Index Type code + + +SearchAttrList$LookingForIndex: + +; DEBUG CODE +; SAVE_ALL +; +; mov eax, es:[bx].ATTRLIST_TypeCode +; call PrintNumber +; movzx eax, es:[bx].ATTRLIST_Length +; call PrintNumber +; mov eax, es +; call PrintNumber +; mov eax, ebx +; call PrintNumber +; push es +; pop ds +; movzx ecx, es:[bx].ATTRLIST_NameLength ; ecx = chars in name +; lea esi, es:[bx].ATTRLIST_Name ; esi -> name +; call PrintName +; +; RESTORE_ALL +; END DEBUG CODE + + cmp es:[bx].ATTRLIST_TypeCode, ecx + je SearchAttrList$FoundIndex + + cmp es:[bx].ATTRLIST_TypeCode, $END ; reached invalid attribute + je SearchAttrList$NotFoundIndex2 ; so must be at end + + cmp es:[bx].ATTRLIST_Length, 0 + je SearchAttrList$NotFoundIndex2 ; reached end of list and + ; nothing found + movzx eax, es:[bx].ATTRLIST_Length + add bx, ax + + mov ax, bx + and ax, 08000h ; test for roll over + jz SearchAttrList$LookingForIndex + + ; If we rolled over then increment to the next es 32K segment and + ; zero off the high bits of bx + + mov ax, es + add ax, 800h + mov es, ax + + and bx, 07fffh + + jmp SearchAttrList$LookingForIndex + +SearchAttrList$FoundIndex: + + ; found the index, return the FRN + + mov eax, es:[bx].ATTRLIST_SegmentReference.REF_LowPart + ret + + +SearchAttrList$NotFoundIndex1: + pop ecx +SearchAttrList$NotFoundIndex2: + xor eax, eax + ret + +SearchAttrList endp + + +DbgString0 db "Debug Point 0", 0Dh, 0Ah, 0 +DbgString1 db "Debug Point 1", 0Dh, 0Ah, 0 +DbgString2 db "Debug Point 2", 0Dh, 0Ah, 0 +DbgString3 db "Debug Point 3", 0Dh, 0Ah, 0 +DbgString4 db "Debug Point 4", 0Dh, 0Ah, 0 + + .errnz ($-_ntfsboot) GT 8192,<FATAL PROBLEM: main boot record exceeds available space> + + org 8192 + +BootCode ends + + end _ntfsboot diff --git a/private/ntos/boot/bootcode/ntfs/i386/usa/bootntfs.h b/private/ntos/boot/bootcode/ntfs/i386/usa/bootntfs.h new file mode 100644 index 000000000..ac6b63ded --- /dev/null +++ b/private/ntos/boot/bootcode/ntfs/i386/usa/bootntfs.h @@ -0,0 +1,517 @@ +#define NTFSBOOTCODE_SIZE 8192 + + +unsigned char NtfsBootCode[] = { +235,91,144,78,84,70,83,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,0,0,128,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +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,84,0,0, +0,199,6,86,0,0,0,199,6,91,0,16,0,184,0,13, +142,192,43,219,232,7,0,104,0,13,104,102,2,203,80,83, +81,82,6,102,161,84,0,102,3,6,28,0,102,51,210,102, +15,183,14,24,0,102,247,241,254,194,136,22,90,0,102,139, +208,102,193,234,16,247,54,26,0,136,22,37,0,163,88,0, +161,24,0,42,6,90,0,64,59,6,91,0,118,3,161,91, +0,80,180,2,139,22,88,0,177,6,210,230,10,54,90,0, +139,202,134,233,138,54,37,0,178,128,205,19,88,114,42,1, +6,84,0,131,22,86,0,0,41,6,91,0,118,11,193,224, +5,140,194,3,208,142,194,235,138,7,90,89,91,88,195,190, +89,1,235,8,190,227,1,235,3,190,57,1,232,9,0,190, +173,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,23,0,92,78,84,76,68,82,32,105,115,32,99,111,109, +112,114,101,115,115,101,100,46,13,10,0,0,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,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,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,44,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,65,9,102,11,192,15, +132,22,254,102,163,46,2,102,184,160,0,0,0,102,139,14, +38,2,232,40,9,102,163,50,2,102,184,176,0,0,0,102, +139,14,42,2,232,22,9,102,163,54,2,102,161,46,2,102, +11,192,15,132,227,253,103,128,120,8,0,15,133,218,253,103, +102,141,80,16,103,3,66,4,103,102,15,182,72,12,102,137, +14,94,2,103,102,139,72,8,102,137,14,90,2,102,161,90, +2,102,15,183,14,11,0,102,51,210,102,247,241,102,163,98, +2,102,161,66,2,102,3,6,90,2,102,163,70,2,102,131, +62,50,2,0,15,132,25,0,102,131,62,54,2,0,15,132, +135,253,102,139,30,54,2,30,7,102,139,62,70,2,232,177, +1,102,15,183,14,0,2,102,184,2,2,0,0,232,153,6, +102,11,192,15,132,88,253,103,102,139,0,30,7,102,139,62, +58,2,232,209,4,102,161,58,2,102,187,128,0,0,0,102, +185,0,0,0,0,102,186,0,0,0,0,232,203,0,102,11, +192,15,132,42,253,103,102,15,183,88,12,102,129,227,255,0, +0,0,15,133,30,253,102,139,216,104,0,32,7,102,43,255, +232,79,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,91,0, +255,54,84,0,255,54,86,0,139,195,193,232,4,140,193,3, +193,37,255,15,45,0,16,247,216,139,14,91,0,193,225,5, +81,59,193,118,2,139,193,80,193,232,5,163,91,0,232,61, +252,88,89,43,200,118,11,140,194,3,208,142,194,184,0,16, +235,222,143,6,86,0,143,6,84,0,143,6,91,0,7,90, +89,91,88,195,6,30,102,96,102,139,218,102,15,182,14,13, +0,102,247,225,102,163,84,0,102,139,195,102,247,225,163,91, +0,139,223,131,227,15,140,192,102,193,239,4,3,199,80,7, +232,116,255,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,61, +5,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,18,5,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,239,4,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,127,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,87,3,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,25,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,225,2,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,84,0,137,22,91, +0,6,30,102,96,139,223,131,227,15,140,192,102,193,239,4, +3,199,80,7,232,160,253,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,101,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,74,2,102,161,48,0,102,15,182,30,13,0,102,247,227, +102,163,84,0,102,161,86,2,163,91,0,102,139,30,26,2, +30,7,232,242,252,102,15,183,251,232,111,255,102,161,26,2, +102,187,32,0,0,0,102,185,0,0,0,0,102,186,0,0, +0,0,232,100,253,102,11,192,15,132,87,0,102,139,216,30, +7,102,139,62,22,2,232,249,253,102,139,30,22,2,103,102, +129,59,128,0,0,0,15,132,6,0,103,3,91,4,235,238, +103,102,129,59,128,0,0,0,15,133,39,0,102,83,103,102, +139,67,16,102,139,62,74,2,30,7,232,9,1,102,91,102, +161,82,2,102,1,6,74,2,102,255,6,30,2,103,3,91, +4,235,205,102,97,144,31,7,195,102,139,208,102,139,14,30, +2,102,161,26,2,102,82,102,80,102,81,102,82,102,187,128, +0,0,0,102,185,0,0,0,0,102,186,0,0,0,0,232, +215,252,102,11,192,15,132,64,249,102,139,216,102,88,232,42, +1,102,11,192,15,132,7,0,102,91,102,91,102,91,195,102, +89,102,88,102,90,102,3,6,82,2,226,185,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,232,144,255,102,11,192,15,132,249,248, +102,15,182,30,13,0,102,247,227,102,90,102,3,194,102,163, +84,0,102,89,102,15,182,30,13,0,102,59,203,15,142,19, +0,137,30,91,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,91,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,155,251,102,95,7,102, +3,62,78,2,102,89,102,88,102,131,249,0,15,143,116,255, +102,97,144,31,7,195,6,30,102,96,102,247,38,86,2,102, +139,14,86,2,232,89,255,232,241,253,102,97,144,31,7,195, +6,30,102,96,102,247,38,98,2,102,139,30,50,2,102,139, +14,98,2,30,7,102,139,62,66,2,232,35,253,232,203,253, +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,158,250,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,90,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,47,250,102,11,192,116,206,102,89,102,89, +102,89,195,102,89,102,89,102,51,192,195,6,30,102,96,102, +139,54,66,2,102,185,32,0,0,0,102,247,193,3,0,0, +0,15,133,3,0,232,13,0,102,173,232,105,0,226,235,102, +97,144,31,7,195,6,30,102,96,102,51,192,102,51,219,176, +13,180,14,187,7,0,205,16,176,10,180,14,187,7,0,205, +16,102,97,144,31,7,195,6,30,102,96,102,11,201,15,133, +9,0,232,208,255,102,97,144,31,7,195,102,51,192,102,51, +219,173,180,14,187,7,0,205,16,226,240,232,183,255,102,97, +144,31,7,195,96,172,60,0,116,9,180,14,187,7,0,205, +16,235,242,97,144,195,6,30,102,96,102,185,8,0,0,0, +102,139,208,102,131,226,15,102,82,102,193,232,4,226,241,102, +185,8,0,0,0,102,88,102,131,248,9,15,143,7,0,102, +131,192,48,235,9,144,102,131,232,10,102,131,192,65,102,51, +219,180,14,187,7,0,205,16,226,219,176,32,180,14,187,7, +0,205,16,102,97,144,31,7,232,96,0,195,6,30,102,96, +102,190,22,13,0,0,232,79,245,102,97,144,31,7,195,6, +30,102,96,102,190,38,13,0,0,232,60,245,102,97,144,31, +7,195,6,30,102,96,102,190,54,13,0,0,232,41,245,102, +97,144,31,7,195,6,30,102,96,102,190,70,13,0,0,232, +22,245,102,97,144,31,7,195,6,30,102,96,102,190,86,13, +0,0,232,3,245,102,97,144,31,7,195,102,80,102,184,0, +0,245,255,102,64,102,11,192,117,249,102,88,195,102,81,102, +80,102,184,5,0,0,0,30,7,102,139,249,232,71,252,102, +139,193,102,91,102,83,102,15,183,14,12,2,102,186,14,2, +0,0,232,68,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,9,252,102,139,199, +102,15,183,14,12,2,102,186,14,2,0,0,232,10,248,195, +102,81,102,187,32,0,0,0,102,185,0,0,0,0,102,186, +0,0,0,0,232,242,247,102,11,192,15,132,82,0,102,139, +216,30,7,102,139,62,22,2,232,135,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,68,101,98,117,103,32,80,111,105,110, +116,32,48,13,10,0,68,101,98,117,103,32,80,111,105,110, +116,32,49,13,10,0,68,101,98,117,103,32,80,111,105,110, +116,32,50,13,10,0,68,101,98,117,103,32,80,111,105,110, +116,32,51,13,10,0,68,101,98,117,103,32,80,111,105,110, +116,32,52,13,10,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; diff --git a/private/ntos/boot/bootcode/ntfs/i386/usa/ntfsboot.inc b/private/ntos/boot/bootcode/ntfs/i386/usa/ntfsboot.inc new file mode 100644 index 000000000..429e7d133 --- /dev/null +++ b/private/ntos/boot/bootcode/ntfs/i386/usa/ntfsboot.inc @@ -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 |