summaryrefslogtreecommitdiffstats
path: root/private/ntos/boot/bootcode/etfs/i386
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/boot/bootcode/etfs/i386')
-rw-r--r--private/ntos/boot/bootcode/etfs/i386/etfsboot.asm584
-rw-r--r--private/ntos/boot/bootcode/etfs/i386/usa/bootetfs.h133
-rw-r--r--private/ntos/boot/bootcode/etfs/i386/usa/etfsboot.inc27
3 files changed, 744 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