summaryrefslogtreecommitdiff
path: root/DuetPkg/BootSector
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2008-04-17 05:48:13 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2008-04-17 05:48:13 +0000
commitc69dd9dfad3eb97d5e21f520f3ba35d102ec4cfa (patch)
treee6065a748931519b3cf11d9811c0beef9c80d58e /DuetPkg/BootSector
parentfcf03596d10de53e45292bd9eb4767a8ddc344ed (diff)
downloadedk2-platforms-c69dd9dfad3eb97d5e21f520f3ba35d102ec4cfa.tar.xz
Porting Duet module from EDKI to EDKII
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5076 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'DuetPkg/BootSector')
-rw-r--r--DuetPkg/BootSector/BootSector.inf30
-rw-r--r--DuetPkg/BootSector/FILE.LST26
-rw-r--r--DuetPkg/BootSector/Gpt.asm294
-rw-r--r--DuetPkg/BootSector/Makefile276
-rw-r--r--DuetPkg/BootSector/Mbr.asm261
-rw-r--r--DuetPkg/BootSector/bootsect.asm288
-rw-r--r--DuetPkg/BootSector/bs16.asm288
-rw-r--r--DuetPkg/BootSector/bs32.asm310
-rw-r--r--DuetPkg/BootSector/efi32.asm581
-rw-r--r--DuetPkg/BootSector/efi64.asm787
-rw-r--r--DuetPkg/BootSector/st16_64.asm1140
-rw-r--r--DuetPkg/BootSector/st32_64.asm1156
-rw-r--r--DuetPkg/BootSector/start.asm921
-rw-r--r--DuetPkg/BootSector/start16.asm914
-rw-r--r--DuetPkg/BootSector/start32.asm929
-rw-r--r--DuetPkg/BootSector/start64.asm1147
16 files changed, 9348 insertions, 0 deletions
diff --git a/DuetPkg/BootSector/BootSector.inf b/DuetPkg/BootSector/BootSector.inf
new file mode 100644
index 0000000000..149d4e49f6
--- /dev/null
+++ b/DuetPkg/BootSector/BootSector.inf
@@ -0,0 +1,30 @@
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootSector
+ FILE_GUID = A36495C1-C205-414e-B71F-4BE3476D699C
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DuetPkg/DuetPkg.dec
+
+[Sources]
+ bootsect.asm
+ bs16.asm
+ bs32.asm
+ Gpt.asm
+ Mbr.asm
+ Start.asm
+ Start16.asm
+ Start32.asm
+ Efi32.asm
+
+[BuildOptions.common]
+ #MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
+ MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
+ MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
+ MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+ MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny
diff --git a/DuetPkg/BootSector/FILE.LST b/DuetPkg/BootSector/FILE.LST
new file mode 100644
index 0000000000..f0f47a42a9
--- /dev/null
+++ b/DuetPkg/BootSector/FILE.LST
@@ -0,0 +1,26 @@
+IA32
+====
+FAT12 FAT16 FAT32
+bootsect.asm bs16.asm bs32.asm
+start.asm start16.asm start32.asm
+ \ | /
+ \ | /
+ efi32.asm
+
+X64
+===
+FAT12 FAT16 FAT32
+bootsect.asm bs16.asm bs32.asm
+start64.asm st16_64.asm st32_64.asm
+ \ | /
+ \ | /
+ efi64.asm
+
+MBR
+===
+Mbr.asm
+
+
+GPT
+===
+Gpt.asm \ No newline at end of file
diff --git a/DuetPkg/BootSector/Gpt.asm b/DuetPkg/BootSector/Gpt.asm
new file mode 100644
index 0000000000..15f91f5f49
--- /dev/null
+++ b/DuetPkg/BootSector/Gpt.asm
@@ -0,0 +1,294 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* gpt.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+; .dosseg
+ .stack
+ .486p
+ .code
+
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+; ****************************************************************************
+; Code loaded by BIOS at 0x0000:0x7C00
+; ****************************************************************************
+
+ org 0h
+Start:
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ lea si, cs:[StartString]
+ mov cx, 10
+ mov di, 160
+ rep movsw
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+; ****************************************************************************
+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
+; ****************************************************************************
+ xor ax, ax ; AX = 0x0000
+ mov bx, 07c00h ; BX = 0x7C00
+ mov bp, 0600h ; BP = 0x0600
+ mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
+ mov cx, 0200h ; CX = 0x0200
+ sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
+ lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
+ lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
+ mov ss, ax ; SS = 0x0000
+ mov sp, bx ; SP = 0x7C00
+ mov es,ax ; ES = 0x0000
+ mov ds,ax ; DS = 0x0000
+ push ax ; PUSH 0x0000
+ push di ; PUSH 0x0600 + Offset(RelocatedStart)
+ cld ; Clear the direction flag
+ rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
+ retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
+
+; ****************************************************************************
+; Code relocated to 0x0000:0x0600
+; ****************************************************************************
+
+RelocatedStart:
+; ****************************************************************************
+; Get Driver Parameters to 0x0000:0x7BFC
+; ****************************************************************************
+ xor ax,ax ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+; ****************************************************************************
+; Read GPT Header from hard disk to 0x0000:0x0800
+; ****************************************************************************
+ xor ax, ax
+ mov es, ax ; Read to 0x0000:0x0800
+ mov di, 0800h ; Read to 0x0000:0x0800
+ mov eax, 1 ; Read LBA #1
+ mov edx, 0 ; Read LBA #1
+ mov bx, 1 ; Read 1 Block
+ push es
+ call ReadBlocks
+ pop es
+
+; ****************************************************************************
+; Read Target GPT Entry from hard disk to 0x0000:0x0A00
+; ****************************************************************************
+ cmp dword ptr es:[di], 020494645h ; Check for "EFI "
+ jne BadGpt
+ cmp dword ptr es:[di + 4], 054524150h ; Check for "PART"
+ jne BadGpt
+ cmp dword ptr es:[di + 8], 000010000h ; Check Revision - 0x10000
+ jne BadGpt
+
+ mov eax, dword ptr es:[di + 84] ; EAX = SizeOfPartitionEntry
+ mul byte ptr [bp+GptPartitionIndicator] ; EAX = SizeOfPartitionEntry * GptPartitionIndicator
+ mov edx, eax ; EDX = SizeOfPartitionEntry * GptPartitionIndicator
+ shr eax, BLOCK_SHIFT ; EAX = (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE
+ and edx, BLOCK_MASK ; EDX = Targer PartitionEntryLBA Offset
+ ; = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
+ push edx
+ mov ecx, dword ptr es:[di + 72] ; ECX = PartitionEntryLBA (Low)
+ mov ebx, dword ptr es:[di + 76] ; EBX = PartitionEntryLBA (High)
+ add eax, ecx ; EAX = Target PartitionEntryLBA (Low)
+ ; = (PartitionEntryLBA +
+ ; (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE)
+ adc edx, ebx ; EDX = Target PartitionEntryLBA (High)
+
+ mov di, 0A00h ; Read to 0x0000:0x0A00
+ mov bx, 1 ; Read 1 Block
+ push es
+ call ReadBlocks
+ pop es
+
+; ****************************************************************************
+; Read Target DBR from hard disk to 0x0000:0x7C00
+; ****************************************************************************
+ pop edx ; EDX = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
+ add di, dx ; DI = Targer PartitionEntryLBA Offset
+ cmp dword ptr es:[di], 0C12A7328h ; Check for EFI System Partition "C12A7328-F81F-11d2-BA4B-00A0C93EC93B"
+ jne BadGpt
+ cmp dword ptr es:[di + 4], 011d2F81Fh ;
+ jne BadGpt
+ cmp dword ptr es:[di + 8], 0A0004BBAh ;
+ jne BadGpt
+ cmp dword ptr es:[di + 0ch], 03BC93EC9h ;
+ jne BadGpt
+
+ mov eax, dword ptr es:[di + 32] ; EAX = StartingLBA (Low)
+ mov edx, dword ptr es:[di + 36] ; EDX = StartingLBA (High)
+ mov di, 07C00h ; Read to 0x0000:0x7C00
+ mov bx, 1 ; Read 1 Block
+ call ReadBlocks
+
+; ****************************************************************************
+; Transfer control to BootSector - Jump to 0x0000:0x7C00
+; ****************************************************************************
+ xor ax, ax
+ push ax ; PUSH 0x0000
+ mov di, 07c00h
+ push di ; PUSH 0x7C00
+ retf ; JMP 0x0000:0x7C00
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; EDX:EAX = Start LBA
+; BX = Number of Blocks to Read (must < 127)
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; si = DiskAddressPacket
+
+ReadBlocks:
+ pushad
+ push ds
+ xor cx, cx
+ mov ds, cx
+ mov bp, 0600h ; bp = 0x600
+ lea si, [bp + OFFSET AddressPacket] ; DS:SI = Disk Address Packet
+ mov BYTE PTR ds:[si+2],bl ; 02 = Number Of Block transfered
+ mov WORD PTR ds:[si+4],di ; 04 = Transfer Buffer Offset
+ mov WORD PTR ds:[si+6],es ; 06 = Transfer Buffer Segment
+ mov DWORD PTR ds:[si+8],eax ; 08 = Starting LBA (Low)
+ mov DWORD PTR ds:[si+0ch],edx ; 0C = Starting LBA (High)
+ mov ah, 42h ; ah = Function 42
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ int 13h
+ jc BadGpt
+ pop ds
+ popad
+ ret
+
+; ****************************************************************************
+; Address Packet used by ReadBlocks
+; ****************************************************************************
+AddressPacket:
+ db 10h ; Size of address packet
+ db 00h ; Reserved. Must be 0
+ db 01h ; Read blocks at a time (To be fixed each times)
+ db 00h ; Reserved. Must be 0
+ dw 0000h ; Destination Address offset (To be fixed each times)
+ dw 0000h ; Destination Address segment (To be fixed each times)
+AddressPacketLba:
+ dd 0h, 0h ; Start LBA (To be fixed each times)
+AddressPacketEnd:
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+
+BadGpt:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 060h
+ mov ds, ax
+ lea si, cs:[ErrorString]
+ mov cx, 10
+ mov di, 320
+ rep movsw
+Halt:
+ jmp Halt
+
+StartString:
+ db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; PhysicalDrive - Used to indicate which disk to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B6h
+PhysicalDrive db 80h
+
+; ****************************************************************************
+; GptPartitionIndicator - Used to indicate which GPT partition to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B7h
+GptPartitionIndicator db 0
+
+; ****************************************************************************
+; Unique MBR signature
+; ****************************************************************************
+ org 01B8h
+ db 'DUET'
+
+; ****************************************************************************
+; Unknown
+; ****************************************************************************
+ org 01BCh
+ dw 0
+
+; ****************************************************************************
+; PMBR Entry - Can be patched by tool
+; ****************************************************************************
+ org 01BEh
+ db 0 ; Boot Indicator
+ db 0ffh ; Start Header
+ db 0ffh ; Start Sector
+ db 0ffh ; Start Track
+ db 0eeh ; OS Type
+ db 0ffh ; End Header
+ db 0ffh ; End Sector
+ db 0ffh ; End Track
+ dd 1 ; Starting LBA
+ dd 0FFFFFFFFh ; End LBA
+
+ org 01CEh
+ dd 0, 0, 0, 0
+ org 01DEh
+ dd 0, 0, 0, 0
+ org 01EEh
+ dd 0, 0, 0, 0
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01FEh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/Makefile b/DuetPkg/BootSector/Makefile
new file mode 100644
index 0000000000..fc24f37677
--- /dev/null
+++ b/DuetPkg/BootSector/Makefile
@@ -0,0 +1,276 @@
+
+#
+# Platform Macro Definition
+#
+PLATFORM_NAME = DuetPkg
+PLATFORM_GUID = 199E24E0-0989-42aa-87F2-611A8C397E72
+PLATFORM_VERSION = 0.3
+PLATFORM_RELATIVE_DIR = DuetPkg
+PLATFORM_DIR = $(WORKSPACE)\DuetPkg
+PLATFORM_OUTPUT_DIR = Build\DuetPkg
+
+#
+# Module Macro Definition
+#
+MODULE_NAME = BootSector
+MODULE_GUID = 2410F0DF-D915-4137-BD04-AAB6BA4C50E0
+MODULE_VERSION = 1.0
+MODULE_TYPE = USER_DEFINED
+MODULE_FILE_BASE_NAME = BootSector
+BASE_NAME = $(MODULE_NAME)
+MODULE_RELATIVE_DIR = DuetPkg\BootSector
+MODULE_DIR = $(WORKSPACE)\DuetPkg\BootSector
+
+#
+# Build Configuration Macro Definition
+#
+ARCH = IA32
+TOOLCHAIN_TAG = MYTOOLS
+TARGET = DEBUG
+BASETOOLS_DIR=m:\tree\working\BaseTools\Bin\Win32
+
+#
+# Build Directory Macro Definition
+#
+# PLATFORM_BUILD_DIR = m:\tree\working\Build\DuetPkg\DEBUG_MYTOOLS
+BUILD_DIR = $(WORKSPACE)\Build\DuetPkg\DEBUG_MYTOOLS
+BIN_DIR = $(BUILD_DIR)\IA32
+LIB_DIR = $(BIN_DIR)
+MODULE_BUILD_DIR = $(BUILD_DIR)\IA32\DuetPkg\BootSector\BootSector
+OUTPUT_DIR = $(MODULE_BUILD_DIR)\OUTPUT
+DEBUG_DIR = $(MODULE_BUILD_DIR)\DEBUG
+DEST_DIR_OUTPUT = $(OUTPUT_DIR)
+DEST_DIR_DEBUG = $(DEBUG_DIR)
+
+#
+# Default Tools Flags Macro Definition (from tools_def.txt by default)
+#
+DEFAULT_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+DEFAULT_SLINK_FLAGS = /nologo /LTCG
+DEFAULT_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs8192 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+DEFAULT_APP_FLAGS = /nologo /E /TC
+DEFAULT_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FIAutoGen.h
+DEFAULT_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4086 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /MACHINE:I386 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+DEFAULT_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+DEFAULT_TIANO_FLAGS =
+DEFAULT_MAKE_FLAGS = /nologo
+DEFAULT_ASMLINK_FLAGS = /nologo /tiny
+DEFAULT_ASL_FLAGS =
+
+
+#
+# Platform Tools Flags Macro Definition (from platform description file)
+#
+PLATFORM_PP_FLAGS =
+PLATFORM_SLINK_FLAGS =
+PLATFORM_CC_FLAGS =
+PLATFORM_APP_FLAGS =
+PLATFORM_VFRPP_FLAGS =
+PLATFORM_DLINK_FLAGS =
+PLATFORM_ASM_FLAGS =
+PLATFORM_TIANO_FLAGS =
+PLATFORM_MAKE_FLAGS =
+PLATFORM_ASMLINK_FLAGS =
+PLATFORM_ASL_FLAGS =
+
+
+#
+# Module Tools Flags Macro Definition (from platform/module description file)
+#
+MODULE_PP_FLAGS =
+MODULE_SLINK_FLAGS =
+MODULE_CC_FLAGS =
+MODULE_APP_FLAGS =
+MODULE_VFRPP_FLAGS =
+MODULE_DLINK_FLAGS =
+MODULE_ASM_FLAGS =
+MODULE_TIANO_FLAGS =
+MODULE_MAKE_FLAGS =
+MODULE_ASMLINK_FLAGS =
+MODULE_ASL_FLAGS =
+
+
+#
+# Tools Flag Macro
+#
+PP_FLAGS = $(DEFAULT_PP_FLAGS) $(PLATFORM_PP_FLAGS) $(MODULE_PP_FLAGS)
+SLINK_FLAGS = $(DEFAULT_SLINK_FLAGS) $(PLATFORM_SLINK_FLAGS) $(MODULE_SLINK_FLAGS)
+CC_FLAGS = $(DEFAULT_CC_FLAGS) $(PLATFORM_CC_FLAGS) $(MODULE_CC_FLAGS)
+APP_FLAGS = $(DEFAULT_APP_FLAGS) $(PLATFORM_APP_FLAGS) $(MODULE_APP_FLAGS)
+VFRPP_FLAGS = $(DEFAULT_VFRPP_FLAGS) $(PLATFORM_VFRPP_FLAGS) $(MODULE_VFRPP_FLAGS)
+DLINK_FLAGS = $(DEFAULT_DLINK_FLAGS) $(PLATFORM_DLINK_FLAGS) $(MODULE_DLINK_FLAGS)
+ASM_FLAGS = $(DEFAULT_ASM_FLAGS) $(PLATFORM_ASM_FLAGS) $(MODULE_ASM_FLAGS)
+TIANO_FLAGS = $(DEFAULT_TIANO_FLAGS) $(PLATFORM_TIANO_FLAGS) $(MODULE_TIANO_FLAGS)
+MAKE_FLAGS = $(DEFAULT_MAKE_FLAGS) $(PLATFORM_MAKE_FLAGS) $(MODULE_MAKE_FLAGS)
+ASMLINK_FLAGS = $(DEFAULT_ASMLINK_FLAGS) $(PLATFORM_ASMLINK_FLAGS) $(MODULE_ASMLINK_FLAGS)
+ASL_FLAGS = $(DEFAULT_ASL_FLAGS) $(PLATFORM_ASL_FLAGS) $(MODULE_ASL_FLAGS)
+
+
+#
+# Tools Path Macro
+#
+PP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+SLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\lib.exe
+CC = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+APP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+VFRPP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+DLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\link.exe
+ASM = C:\WINDDK\3790.1830\bin\x86\ml.exe
+TIANO = TianoCompress.exe
+MAKE = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\nmake.exe
+#ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link.exe
+ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link16.exe
+ASL = C:\ASL\iasl.exe
+
+
+MAKE_FILE = $(MODULE_BUILD_DIR)\Makefile
+
+#
+# Shell Command Macro
+#
+RD = rmdir /s /q
+RM = del /f /q
+MD = mkdir
+CP = copy /y
+MV = move /y
+
+
+#
+# Build Macro
+#
+ASSEMBLY_CODE_FILE_LIST = $(MODULE_DIR)\bootsect.asm \
+ $(MODULE_DIR)\bs16.asm \
+ $(MODULE_DIR)\bs32.asm \
+ $(MODULE_DIR)\efi32.asm \
+ $(MODULE_DIR)\Gpt.asm \
+ $(MODULE_DIR)\Mbr.asm \
+ $(MODULE_DIR)\start.asm \
+ $(MODULE_DIR)\start16.asm \
+ $(MODULE_DIR)\start32.asm
+
+TARGET_FILES = $(OUTPUT_DIR)\bootsect.com \
+ $(OUTPUT_DIR)\bs16.com \
+ $(OUTPUT_DIR)\bs32.com \
+ $(OUTPUT_DIR)\Gpt.com \
+ $(OUTPUT_DIR)\Mbr.com \
+ $(OUTPUT_DIR)\Start.com \
+ $(OUTPUT_DIR)\Start16.com \
+ $(OUTPUT_DIR)\Start32.com \
+ $(OUTPUT_DIR)\efi32.com2
+
+INC =
+
+
+#OBJECTS =
+
+LIBS =
+
+COMMON_DEPS =
+
+all: init $(TARGET_FILES) loader
+
+init:
+ if not exist $(OUTPUT_DIR) mkdir $(OUTPUT_DIR)
+ if not exist $(DEBUG_DIR) mkdir $(DEBUG_DIR)
+
+#=============
+$(OUTPUT_DIR)\bootsect.obj:$(MODULE_DIR)\bootsect.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bootsect.obj" /FR"$(OUTPUT_DIR)\bootsect.txt" "$(MODULE_DIR)\bootsect.asm"
+
+$(OUTPUT_DIR)\bootsect.com:$(OUTPUT_DIR)\bootsect.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bootsect.obj,$(OUTPUT_DIR)\bootsect.com,$(OUTPUT_DIR)\bootsect.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\bs16.obj:$(MODULE_DIR)\bs16.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs16.obj" "$(MODULE_DIR)\bs16.asm"
+
+$(OUTPUT_DIR)\bs16.com:$(OUTPUT_DIR)\bs16.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs16.obj,$(OUTPUT_DIR)\bs16.com,$(OUTPUT_DIR)\bs16.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\bs32.obj:$(MODULE_DIR)\bs32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs32.obj" "$(MODULE_DIR)\bs32.asm"
+
+$(OUTPUT_DIR)\bs32.com:$(OUTPUT_DIR)\bs32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs32.obj,$(OUTPUT_DIR)\bs32.com,$(OUTPUT_DIR)\bs32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Gpt.obj:$(MODULE_DIR)\Gpt.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Gpt.obj" "$(MODULE_DIR)\Gpt.asm"
+
+$(OUTPUT_DIR)\Gpt.com:$(OUTPUT_DIR)\Gpt.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Gpt.obj,$(OUTPUT_DIR)\Gpt.com,$(OUTPUT_DIR)\Gpt.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Mbr.obj:$(MODULE_DIR)\Mbr.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Mbr.obj" "$(MODULE_DIR)\Mbr.asm"
+
+$(OUTPUT_DIR)\Mbr.com:$(OUTPUT_DIR)\Mbr.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Mbr.obj,$(OUTPUT_DIR)\Mbr.com,$(OUTPUT_DIR)\Mbr.map,,,
+
+#============
+
+$(OUTPUT_DIR)\Start.obj:$(MODULE_DIR)\Start.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start.obj" "$(MODULE_DIR)\Start.asm"
+
+$(OUTPUT_DIR)\Start.com:$(OUTPUT_DIR)\Start.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start.obj,$(OUTPUT_DIR)\Start.com,$(OUTPUT_DIR)\Start.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Start16.obj:$(MODULE_DIR)\Start16.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start16.obj" "$(MODULE_DIR)\Start16.asm"
+
+$(OUTPUT_DIR)\Start16.com:$(OUTPUT_DIR)\Start16.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start16.obj,$(OUTPUT_DIR)\Start16.com,$(OUTPUT_DIR)\Start16.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Start32.obj:$(MODULE_DIR)\Start32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start32.obj" "$(MODULE_DIR)\Start32.asm"
+
+$(OUTPUT_DIR)\Start32.com:$(OUTPUT_DIR)\Start32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start32.obj,$(OUTPUT_DIR)\Start32.com,$(OUTPUT_DIR)\Start32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\efi32.obj:$(MODULE_DIR)\efi32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\efi32.obj" "$(MODULE_DIR)\efi32.asm"
+
+$(OUTPUT_DIR)\efi32.com:$(OUTPUT_DIR)\efi32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\efi32.obj,$(OUTPUT_DIR)\efi32.com,$(OUTPUT_DIR)\efi32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\efi32.com2:$(OUTPUT_DIR)\efi32.com
+ $(BASETOOLS_DIR)\Split.exe -f $(OUTPUT_DIR)\efi32.com -t $(OUTPUT_DIR)\efi32.com2 -s 135168
+#
+# clean all generated files
+#
+
+loader:$(BUILD_DIR)\FV\Efildr
+
+$(BUILD_DIR)\FV\DUETEFIMAINFV.z:$(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DUETEFIMAINFV.z $(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
+
+$(BUILD_DIR)\FV\DxeMain.z:$(BUILD_DIR)\IA32\DxeMain.efi
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeMain.z $(BUILD_DIR)\IA32\DxeMain.efi
+
+$(BUILD_DIR)\FV\DxeIpl.z:$(BUILD_DIR)\IA32\DxeIpl.efi
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\IA32\DxeIpl.efi
+
+$(BUILD_DIR)\FV\Efildr32:$(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
+ $(BASETOOLS_DIR)\EfiLdrImage.exe -o $(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
+
+$(BUILD_DIR)\FV\Efildr:$(OUTPUT_DIR)\Start.com $(OUTPUT_DIR)\Efi32.com2 $(BUILD_DIR)\FV\Efildr32
+ copy /b $(OUTPUT_DIR)\BootSect.com+$(OUTPUT_DIR)\Efi32.com2+$(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\FV\Efildr
+
+clean:
+ if exist $(DEBUG_DIR) rmdir /s /q $(DEBUG_DIR)
+ if exist $(OUTPUT_DIR) rmdir /s /q $(OUTPUT_DIR)
+
+
diff --git a/DuetPkg/BootSector/Mbr.asm b/DuetPkg/BootSector/Mbr.asm
new file mode 100644
index 0000000000..03182a649a
--- /dev/null
+++ b/DuetPkg/BootSector/Mbr.asm
@@ -0,0 +1,261 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* Mbr.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+; .dosseg
+ .stack
+ .486p
+ .code
+
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+; ****************************************************************************
+; Code loaded by BIOS at 0x0000:0x7C00
+; ****************************************************************************
+
+ org 0h
+Start:
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ lea si, cs:[StartString]
+ mov cx, 10
+ mov di, 160
+ rep movsw
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+; ****************************************************************************
+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
+; ****************************************************************************
+ xor ax, ax ; AX = 0x0000
+ mov bx, 07c00h ; BX = 0x7C00
+ mov bp, 0600h ; BP = 0x0600
+ mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
+ mov cx, 0200h ; CX = 0x0200
+ sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
+ lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
+ lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
+ mov ss, ax ; SS = 0x0000
+ mov sp, bx ; SP = 0x7C00
+ mov es,ax ; ES = 0x0000
+ mov ds,ax ; DS = 0x0000
+ push ax ; PUSH 0x0000
+ push di ; PUSH 0x0600 + Offset(RelocatedStart)
+ cld ; Clear the direction flag
+ rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
+ retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
+
+; ****************************************************************************
+; Code relocated to 0x0000:0x0600
+; ****************************************************************************
+
+RelocatedStart:
+; ****************************************************************************
+; Get Driver Parameters to 0x0000:0x7BFC
+; ****************************************************************************
+
+ xor ax,ax ; AX = 0
+ mov ss,ax ; SS = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; SP = 0x7c00
+ mov bp,sp ; BP = 0x7c00
+
+ mov ah,8 ; AH = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; AX = 0
+ mov al,dh ; AL = DH
+ inc al ; MaxHead = AL + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; AL = CL
+ and al,03fh ; MaxSector = AL & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+; ****************************************************************************
+; Read Target DBR from hard disk to 0x0000:0x7C00
+; ****************************************************************************
+
+ xor ax, ax
+ mov al, byte ptr [bp+MbrPartitionIndicator] ; AX = MbrPartitionIndex
+ cmp al, 0ffh ; 0xFF means do legacy MBR boot
+ jnz EfiDbr
+LegacyMbr:
+ mov eax, 00000600h ; Assume LegacyMBR is backuped in Sector 6
+ jmp StartReadTo7C00 ; EAX = Header/Sector/Tracker/Zero
+
+EfiDbr:
+ cmp al, 4 ; MbrPartitionIndex should < 4
+ jae BadDbr
+ shl ax, 4 ; AX = MBREntrySize * Index
+ add ax, 1beh ; AX = MBREntryOffset
+ mov di, ax ; DI = MBREntryOffset
+
+ ; Here we don't use the C/H/S information provided by Partition table
+ ; but calculate C/H/S from LBA ourselves
+ ; Ci: Cylinder number
+ ; Hi: Header number
+ ; Si: Sector number
+ mov eax, dword ptr es:[bp + di + 8] ; Start LBA
+ mov edx, eax
+ shr edx, 16 ; DX:AX = Start LBA
+ ; = Ci * (H * S) + Hi * S + (Si - 1)
+
+ ; Calculate C/H/S according to LBA
+ mov bp, 7bfah
+ div word ptr [bp+2] ; AX = Hi + H*Ci
+ ; DX = Si - 1
+ inc dx ; DX = Si
+ push dx ; 0000:7bfa = Si <----
+ xor dx, dx ; DX:AX = Hi + H*Ci
+ div word ptr [bp+4] ; AX = Ci <----
+ ; DX = Hi <----
+
+StartReadTo7C00:
+
+ mov cl, byte ptr [bp] ; Si
+ mov ch, al ; Ci[0-7]
+ or cl, ah ; Ci[8,9]
+ mov bx, 7c00h ; ES:BX = 0000:7C00h
+ mov ah, 2h ; Function 02h
+ mov al, 1 ; 1 Sector
+ mov dh, dl ; Hi
+ mov bp, 0600h
+ mov dl, byte ptr [bp + PhysicalDrive] ; Drive number
+ int 13h
+ jc BadDbr
+
+
+
+; ****************************************************************************
+; Transfer control to BootSector - Jump to 0x0000:0x7C00
+; ****************************************************************************
+ xor ax, ax
+ push ax ; PUSH 0x0000 - Segment
+ mov di, 07c00h
+ push di ; PUSH 0x7C00 - Offset
+ retf ; JMP 0x0000:0x7C00
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+
+BadDbr:
+ push ax
+ mov ax, 0b800h
+ mov es, ax
+ mov ax, 060h
+ mov ds, ax
+ lea si, cs:[ErrorString]
+ mov di, 320
+ pop ax
+ call A2C
+ mov [si+16], ah
+ mov [si+18], al
+ mov cx, 10
+ rep movsw
+Halt:
+ jmp Halt
+
+StartString:
+ db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, ':', 0ch, '?', 0ch, '?', 0ch
+
+; ****************************************************************************
+; A2C - convert Ascii code stored in AH to character stored in AX
+; ****************************************************************************
+A2C:
+ mov al, ah
+ shr ah, 4
+ and al, 0Fh
+ add ah, '0'
+ add al, '0'
+
+ cmp ah, '9'
+ jle @f
+ add ah, 7
+@@:
+
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+
+; ****************************************************************************
+; PhysicalDrive - Used to indicate which disk to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B6h
+PhysicalDrive db 80h
+
+; ****************************************************************************
+; MbrPartitionIndicator - Used to indicate which MBR partition to be boot
+; Can be patched by tool
+; OxFF means boot to legacy MBR. (LBA OFFSET 6)
+; ****************************************************************************
+ org 01B7h
+MbrPartitionIndicator db 0
+
+; ****************************************************************************
+; Unique MBR signature
+; ****************************************************************************
+ org 01B8h
+ db 'DUET'
+
+; ****************************************************************************
+; Unknown
+; ****************************************************************************
+ org 01BCh
+ dw 0
+
+; ****************************************************************************
+; MBR Entry - To be patched
+; ****************************************************************************
+ org 01BEh
+ dd 0, 0, 0, 0
+ org 01CEh
+ dd 0, 0, 0, 0
+ org 01DEh
+ dd 0, 0, 0, 0
+ org 01EEh
+ dd 0, 0, 0, 0
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01FEh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bootsect.asm b/DuetPkg/BootSector/bootsect.asm
new file mode 100644
index 0000000000..972e36e8a1
--- /dev/null
+++ b/DuetPkg/BootSector/bootsect.asm
@@ -0,0 +1,288 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bootsect.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"
+LOADER_FILENAME_PART3 EQU 020202020h ; "____"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+Id db " " ; Id - 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read entire Root Directory
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
+ mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bs16.asm b/DuetPkg/BootSector/bs16.asm
new file mode 100644
index 0000000000..41040269cd
--- /dev/null
+++ b/DuetPkg/BootSector/bs16.asm
@@ -0,0 +1,288 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bs16.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 036315244h ; "DR16"
+LOADER_FILENAME_PART3 EQU 020202036h ; "6___"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+Id db " " ; Id - 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read entire Root Directory
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
+ mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bs32.asm b/DuetPkg/BootSector/bs32.asm
new file mode 100644
index 0000000000..bc84f83732
--- /dev/null
+++ b/DuetPkg/BootSector/bs32.asm
@@ -0,0 +1,310 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bs32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 030325244h ; "DR20"
+LOADER_FILENAME_PART3 EQU 020202030h ; "0___"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
+ mov word ptr [bp],ax ; Save FirstClusterLBA for later use
+
+ mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read StartCluster of Root Directory
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/efi32.asm b/DuetPkg/BootSector/efi32.asm
new file mode 100644
index 0000000000..d9560221d6
--- /dev/null
+++ b/DuetPkg/BootSector/efi32.asm
@@ -0,0 +1,581 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* efi32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Now in 32-bit protected mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .486
+ .model flat
+ .stack
+ .code
+ org 21000h
+
+DEFAULT_HANDLER_SIZE EQU INT1 - INT0
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit relative
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+
+Start:
+ mov ds,ax
+ mov es,ax
+ mov fs,ax
+ mov gs,ax
+ mov ss,ax
+ mov esp,0001ffff0h
+
+ call ClearScreen
+
+ ; Populate IDT with meaningful offsets for exception handlers...
+ sidt fword ptr [Idtr] ; get fword address of IDT
+
+ mov eax, offset Halt
+ mov ebx, eax ; use bx to copy 15..0 to descriptors
+ shr eax, 16 ; use ax to copy 31..16 to descriptors
+ mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
+ mov esi, [offset Idtr + 2]
+ mov edi, [esi]
+
+@@: ; loop through all IDT entries exception handlers and initialize to default handler
+ mov word ptr [edi], bx ; write bits 15..0 of offset
+ mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
+ mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+ mov word ptr [edi+6], ax ; write bits 31..16 of offset
+ add edi, 8 ; move up to next descriptor
+ add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
+ loop @b ; loop back through again until all descriptors are initialized
+
+ ;; at this point edi contains the offset of the descriptor for INT 20
+ ;; and bx contains the low 16 bits of the offset of the default handler
+ ;; so initialize all the rest of the descriptors with these two values...
+; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
+;@@: ; loop through all IDT entries exception handlers and initialize to default handler
+; mov word ptr [edi], bx ; write bits 15..0 of offset
+; mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
+; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+; mov word ptr [edi+6], ax ; write bits 31..16 of offset
+; add edi, 8 ; move up to next descriptor
+; loop @b ; loop back through again until all descriptors are initialized
+
+
+;; DUMP location of IDT and several of the descriptors
+; mov ecx, 8
+; mov eax, [offset Idtr + 2]
+; mov eax, [eax]
+; mov edi, 0b8000h
+; call PrintDword
+; mov esi, eax
+; mov edi, 0b80a0h
+; jmp OuterLoop
+
+;;
+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
+; mov eax, 011111111h
+; mov ebx, 022222222h
+; mov ecx, 033333333h
+; mov edx, 044444444h
+; mov ebp, 055555555h
+; mov esi, 066666666h
+; mov edi, 077777777h
+; push 011111111h
+; push 022222222h
+; push 033333333h
+; int 119
+
+
+ mov esi,022000h ; esi = 22000
+ mov eax,[esi+014h] ; eax = [22014]
+ add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
+ mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
+ add ebp,esi
+ mov edi,[ebp+034h] ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase
+ mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
+ add eax,edi ; eax = ImageBase + EntryPoint
+ mov dword ptr [EfiLdrOffset],eax ; Modify far jump instruction for correct entry point
+
+ mov bx,word ptr[ebp+6] ; bx = Number of sections
+ xor eax,eax
+ mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
+ add ebp,eax
+ add ebp,018h ; ebp = Start of 1st Section
+
+SectionLoop:
+ push esi ; Save Base of EFILDR.C
+ push edi ; Save ImageBase
+ add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
+ add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
+ mov ecx,[ebp+010h] ; ecs = SizeOfRawData
+
+ cld
+ shr ecx,2
+ rep movsd
+
+ pop edi ; Restore ImageBase
+ pop esi ; Restore Base of EFILDR.C
+
+ add bp,028h ; ebp = ebp + 028h = Pointer to next section record
+ dec bx
+ cmp bx,0
+ jne SectionLoop
+
+ movzx eax, word ptr [Idtr] ; get size of IDT
+ inc eax
+ add eax, dword ptr [Idtr + 2] ; add to base of IDT to get location of memory map...
+ push eax ; push memory map location on stack for call to EFILDR...
+
+ push eax ; push return address (useless, just for stack balance)
+ db 0b8h
+EfiLdrOffset:
+ dd 000401000h ; Offset of EFILDR
+; mov eax, 401000h
+ push eax
+ ret
+
+; db "**** DEFAULT IDT ENTRY ***",0
+ align 02h
+Halt:
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (78h - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+
+commonIdtEntry:
+ pushad
+ mov ebp, esp
+;;
+;; At this point the stack looks like this:
+;;
+;; eflags
+;; Calling CS
+;; Calling EIP
+;; Error code or 0
+;; Int num or 0ffh for unknown int num
+;; eax
+;; ecx
+;; edx
+;; ebx
+;; esp
+;; ebp
+;; esi
+;; edi <------- ESP, EBP
+;;
+
+ call ClearScreen
+ mov esi, offset String1
+ call PrintString
+ mov eax, [ebp + 32] ;; move Int number into EAX
+ cmp eax, 19
+ ja PrintDefaultString
+PrintExceptionString:
+ shl eax, 2 ;; multiply by 4 to get offset from StringTable to actual string address
+ add eax, offset StringTable
+ mov esi, [eax]
+ jmp PrintTheString
+PrintDefaultString:
+ mov esi, offset IntUnknownString
+ ; patch Int number
+ mov edx, eax
+ call A2C
+ mov [esi + 1], al
+ mov eax, edx
+ shr eax, 4
+ call A2C
+ mov [esi], al
+PrintTheString:
+ call PrintString
+ mov esi, offset String2
+ call PrintString
+ mov eax, [ebp+44] ; CS
+ call PrintDword
+ mov al, ':'
+ mov byte ptr [edi], al
+ add edi, 2
+ mov eax, [ebp+40] ; EIP
+ call PrintDword
+ mov esi, offset String3
+ call PrintString
+
+ mov edi, 0b8140h
+
+ mov esi, offset StringEax ; eax
+ call PrintString
+ mov eax, [ebp+28]
+ call PrintDword
+
+ mov esi, offset StringEbx ; ebx
+ call PrintString
+ mov eax, [ebp+16]
+ call PrintDword
+
+ mov esi, offset StringEcx ; ecx
+ call PrintString
+ mov eax, [ebp+24]
+ call PrintDword
+
+ mov esi, offset StringEdx ; edx
+ call PrintString
+ mov eax, [ebp+20]
+ call PrintDword
+
+ mov esi, offset StringEcode ; error code
+ call PrintString
+ mov eax, [ebp+36]
+ call PrintDword
+
+ mov edi, 0b81e0h
+
+ mov esi, offset StringEsp ; esp
+ call PrintString
+ mov eax, [ebp+12]
+ call PrintDword
+
+ mov esi, offset StringEbp ; ebp
+ call PrintString
+ mov eax, [ebp+8]
+ call PrintDword
+
+ mov esi, offset StringEsi ; esi
+ call PrintString
+ mov eax, [ebp+4]
+ call PrintDword
+
+ mov esi, offset StringEdi ; edi
+ call PrintString
+ mov eax, [ebp]
+ call PrintDword
+
+ mov esi, offset StringEflags ; eflags
+ call PrintString
+ mov eax, [ebp+48]
+ call PrintDword
+
+ mov edi, 0b8320h
+
+ mov esi, ebp
+ add esi, 52
+ mov ecx, 8
+
+
+OuterLoop:
+ push ecx
+ mov ecx, 8
+ mov edx, edi
+
+InnerLoop:
+ mov eax, [esi]
+ call PrintDword
+ add esi, 4
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop
+
+
+ mov edi, 0b8960h
+
+ mov eax, [ebp+40] ; EIP
+ sub eax, 32 * 4
+ mov esi, eax ; esi = eip - 32 DWORD linear (total 64 DWORD)
+
+ mov ecx, 8
+
+OuterLoop1:
+ push ecx
+ mov ecx, 8
+ mov edx, edi
+
+InnerLoop1:
+ mov eax, [esi]
+ call PrintDword
+ add esi, 4
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop1
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop1
+
+
+
+; wbinvd ; Ken: this intruction does not support in early than 486 arch
+@@:
+ jmp @b
+;
+; return
+;
+ mov esp, ebp
+ popad
+ add esp, 8 ; error code and INT number
+
+ iretd
+
+
+PrintString:
+ push eax
+@@:
+ mov al, byte ptr [esi]
+ cmp al, 0
+ je @f
+ mov byte ptr [edi], al
+ inc esi
+ add edi, 2
+ jmp @b
+@@:
+ pop eax
+ ret
+
+;; EAX contains dword to print
+;; EDI contains memory location (screen location) to print it to
+PrintDword:
+ push ecx
+ push ebx
+ push eax
+
+ mov ecx, 8
+looptop:
+ rol eax, 4
+ mov bl, al
+ and bl, 0fh
+ add bl, '0'
+ cmp bl, '9'
+ jle @f
+ add bl, 7
+@@:
+ mov byte ptr [edi], bl
+ add edi, 2
+ loop looptop
+ wbinvd
+
+ pop eax
+ pop ebx
+ pop ecx
+ ret
+
+ClearScreen:
+ push eax
+ push ecx
+
+ mov al, ' '
+ mov ah, 0ch
+ mov edi, 0b8000h
+ mov ecx, 80 * 24
+@@:
+ mov word ptr [edi], ax
+ add edi, 2
+ loop @b
+ mov edi, 0b8000h
+
+ pop ecx
+ pop eax
+
+ ret
+
+A2C:
+ and al, 0fh
+ add al, '0'
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+String1 db "*** INT ",0
+
+Int0String db "00h Divide by 0 -",0
+Int1String db "01h Debug exception -",0
+Int2String db "02h NMI -",0
+Int3String db "03h Breakpoint -",0
+Int4String db "04h Overflow -",0
+Int5String db "05h Bound -",0
+Int6String db "06h Invalid opcode -",0
+Int7String db "07h Device not available -",0
+Int8String db "08h Double fault -",0
+Int9String db "09h Coprocessor seg overrun (reserved) -",0
+Int10String db "0Ah Invalid TSS -",0
+Int11String db "0Bh Segment not present -",0
+Int12String db "0Ch Stack fault -",0
+Int13String db "0Dh General protection fault -",0
+Int14String db "0Eh Page fault -",0
+Int15String db "0Fh (Intel reserved) -",0
+Int16String db "10h Floating point error -",0
+Int17String db "11h Alignment check -",0
+Int18String db "12h Machine check -",0
+Int19String db "13h SIMD Floating-Point Exception -",0
+IntUnknownString db "??h Unknown interrupt -",0
+
+StringTable dd offset Int0String, offset Int1String, offset Int2String, offset Int3String,
+ offset Int4String, offset Int5String, offset Int6String, offset Int7String,
+ offset Int8String, offset Int9String, offset Int10String, offset Int11String,
+ offset Int12String, offset Int13String, offset Int14String, offset Int15String,
+ offset Int16String, offset Int17String, offset Int18String, offset Int19String
+
+String2 db " HALT!! *** (",0
+String3 db ")",0
+StringEax db "EAX=",0
+StringEbx db " EBX=",0
+StringEcx db " ECX=",0
+StringEdx db " EDX=",0
+StringEcode db " ECODE=",0
+StringEsp db "ESP=",0
+StringEbp db " EBP=",0
+StringEsi db " ESI=",0
+StringEdi db " EDI=",0
+StringEflags db " EFLAGS=",0
+
+Idtr df 0
+
+ org 21ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/efi64.asm b/DuetPkg/BootSector/efi64.asm
new file mode 100644
index 0000000000..bbf8fee35a
--- /dev/null
+++ b/DuetPkg/BootSector/efi64.asm
@@ -0,0 +1,787 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* efi64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Now in 64-bit long mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .486
+ .model flat
+ .stack
+ .code
+ org 21000h
+
+DEFAULT_HANDLER_SIZE EQU INT1 - INT0
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit reletive
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+
+Start:
+
+ mov esp,0001fffe8h ; make final stack aligned
+
+ ; set OSFXSR and OSXMMEXCPT because some code will use XMM register
+ db 0fh
+ db 20h
+ db 0e0h
+; mov rax, cr4
+ bts eax, 9
+ bts eax, 0ah
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, rax
+
+ call ClearScreen
+
+ ; Populate IDT with meaningful offsets for exception handlers...
+ mov eax, offset Idtr
+ sidt fword ptr [eax] ; get fword address of IDT
+
+ mov eax, offset Halt
+ mov ebx, eax ; use bx to copy 15..0 to descriptors
+ shr eax, 16 ; use ax to copy 31..16 to descriptors
+ ; 63..32 of descriptors is 0
+ mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
+ mov esi, [offset Idtr + 2]
+ mov edi, [esi]
+
+@@: ; loop through all IDT entries exception handlers and initialize to default handler
+ mov word ptr [edi], bx ; write bits 15..0 of offset
+ mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
+ mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+ mov word ptr [edi+6], ax ; write bits 31..16 of offset
+ mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
+ add edi, 16 ; move up to next descriptor
+ add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
+ loop @b ; loop back through again until all descriptors are initialized
+
+ ;; at this point edi contains the offset of the descriptor for INT 20
+ ;; and bx contains the low 16 bits of the offset of the default handler
+ ;; so initialize all the rest of the descriptors with these two values...
+; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
+;@@: ; loop through all IDT entries exception handlers and initialize to default handler
+; mov word ptr [edi], bx ; write bits 15..0 of offset
+; mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
+; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+; mov word ptr [edi+6], ax ; write bits 31..16 of offset
+; mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
+; add edi, 16 ; move up to next descriptor
+; loop @b ; loop back through again until all descriptors are initialized
+
+
+;; DUMP location of IDT and several of the descriptors
+; mov ecx, 8
+; mov eax, [offset Idtr + 2]
+; mov eax, [eax]
+; mov edi, 0b8000h
+; call PrintQword
+; mov esi, eax
+; mov edi, 0b80a0h
+; jmp OuterLoop
+
+;;
+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
+; mov eax, 011111111h
+; mov ebx, 022222222h
+; mov ecx, 033333333h
+; mov edx, 044444444h
+; mov ebp, 055555555h
+; mov esi, 066666666h
+; mov edi, 077777777h
+; push 011111111h
+; push 022222222h
+; push 033333333h
+; int 119
+
+ mov esi,022000h ; esi = 22000
+ mov eax,[esi+014h] ; eax = [22014]
+ add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
+ mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
+ add ebp,esi
+ mov edi,[ebp+030h] ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)
+ mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
+ add eax,edi ; eax = ImageBase + EntryPoint
+ mov ebx, offset EfiLdrOffset
+ mov dword ptr [ebx],eax ; Modify far jump instruction for correct entry point
+
+ mov bx,word ptr[ebp+6] ; bx = Number of sections
+ xor eax,eax
+ mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
+ add ebp,eax
+ add ebp,018h ; ebp = Start of 1st Section
+
+SectionLoop:
+ push esi ; Save Base of EFILDR.C
+ push edi ; Save ImageBase
+ add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
+ add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
+ mov ecx,[ebp+010h] ; ecs = SizeOfRawData
+
+ cld
+ shr ecx,2
+ rep movsd
+
+ pop edi ; Restore ImageBase
+ pop esi ; Restore Base of EFILDR.C
+
+ add bp,028h ; ebp = ebp + 028h = Pointer to next section record
+ db 66h
+ db 0ffh
+ db 0cbh
+; dec bx
+ cmp bx,0
+ jne SectionLoop
+
+ mov edx, offset Idtr
+ movzx eax, word ptr [edx] ; get size of IDT
+ db 0ffh
+ db 0c0h
+; inc eax
+ add eax, dword ptr [edx + 2] ; add to base of IDT to get location of memory map...
+ xor ecx, ecx
+ mov ecx, eax ; put argument to RCX
+
+ db 48h
+ db 0c7h
+ db 0c0h
+EfiLdrOffset:
+ dd 000401000h ; Offset of EFILDR
+; mov rax, 401000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+; db "**** DEFAULT IDT ENTRY ***",0
+ align 02h
+Halt:
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (78h - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+
+commonIdtEntry:
+ push eax
+ push ecx
+ push edx
+ push ebx
+ push esp
+ push ebp
+ push esi
+ push edi
+ db 41h
+ db 50h
+; push r8
+ db 41h
+ db 51h
+; push r9
+ db 41h
+ db 52h
+; push r10
+ db 41h
+ db 53h
+; push r11
+ db 41h
+ db 54h
+; push r12
+ db 41h
+ db 55h
+; push r13
+ db 41h
+ db 56h
+; push r14
+ db 41h
+ db 57h
+; push r15
+ db 48h
+ mov ebp, esp
+; mov rbp, rsp
+
+;;
+;; At this point the stack looks like this:
+;;
+;; Calling SS
+;; Calling RSP
+;; rflags
+;; Calling CS
+;; Calling RIP
+;; Error code or 0
+;; Int num or 0ffh for unknown int num
+;; rax
+;; rcx
+;; rdx
+;; rbx
+;; rsp
+;; rbp
+;; rsi
+;; rdi
+;; r8
+;; r9
+;; r10
+;; r11
+;; r12
+;; r13
+;; r14
+;; r15 <------- RSP, RBP
+;;
+
+ call ClearScreen
+ mov esi, offset String1
+ call PrintString
+ db 48h
+ mov eax, [ebp + 16*8] ;; move Int number into RAX
+ db 48h
+ cmp eax, 18
+ ja PrintDefaultString
+PrintExceptionString:
+ shl eax, 3 ;; multiply by 8 to get offset from StringTable to actual string address
+ add eax, offset StringTable
+ mov esi, [eax]
+ jmp PrintTheString
+PrintDefaultString:
+ mov esi, offset IntUnknownString
+ ; patch Int number
+ mov edx, eax
+ call A2C
+ mov [esi + 1], al
+ mov eax, edx
+ shr eax, 4
+ call A2C
+ mov [esi], al
+PrintTheString:
+ call PrintString
+ mov esi, offset String2
+ call PrintString
+ db 48h
+ mov eax, [ebp+19*8] ; CS
+ call PrintQword
+ mov al, ':'
+ mov byte ptr [edi], al
+ add edi, 2
+ db 48h
+ mov eax, [ebp+18*8] ; RIP
+ call PrintQword
+ mov esi, offset String3
+ call PrintString
+
+ mov edi, 0b8140h
+
+ mov esi, offset StringRax ; rax
+ call PrintString
+ db 48h
+ mov eax, [ebp+15*8]
+ call PrintQword
+
+ mov esi, offset StringRcx ; rcx
+ call PrintString
+ db 48h
+ mov eax, [ebp+14*8]
+ call PrintQword
+
+ mov esi, offset StringRdx ; rdx
+ call PrintString
+ db 48h
+ mov eax, [ebp+13*8]
+ call PrintQword
+
+ mov edi, 0b81e0h
+
+ mov esi, offset StringRbx ; rbx
+ call PrintString
+ db 48h
+ mov eax, [ebp+12*8]
+ call PrintQword
+
+ mov esi, offset StringRsp ; rsp
+ call PrintString
+ db 48h
+ mov eax, [ebp+21*8]
+ call PrintQword
+
+ mov esi, offset StringRbp ; rbp
+ call PrintString
+ db 48h
+ mov eax, [ebp+10*8]
+ call PrintQword
+
+ mov edi, 0b8280h
+
+ mov esi, offset StringRsi ; rsi
+ call PrintString
+ db 48h
+ mov eax, [ebp+9*8]
+ call PrintQword
+
+ mov esi, offset StringRdi ; rdi
+ call PrintString
+ db 48h
+ mov eax, [ebp+8*8]
+ call PrintQword
+
+ mov esi, offset StringEcode ; error code
+ call PrintString
+ db 48h
+ mov eax, [ebp+17*8]
+ call PrintQword
+
+ mov edi, 0b8320h
+
+ mov esi, offset StringR8 ; r8
+ call PrintString
+ db 48h
+ mov eax, [ebp+7*8]
+ call PrintQword
+
+ mov esi, offset StringR9 ; r9
+ call PrintString
+ db 48h
+ mov eax, [ebp+6*8]
+ call PrintQword
+
+ mov esi, offset StringR10 ; r10
+ call PrintString
+ db 48h
+ mov eax, [ebp+5*8]
+ call PrintQword
+
+ mov edi, 0b83c0h
+
+ mov esi, offset StringR11 ; r11
+ call PrintString
+ db 48h
+ mov eax, [ebp+4*8]
+ call PrintQword
+
+ mov esi, offset StringR12 ; r12
+ call PrintString
+ db 48h
+ mov eax, [ebp+3*8]
+ call PrintQword
+
+ mov esi, offset StringR13 ; r13
+ call PrintString
+ db 48h
+ mov eax, [ebp+2*8]
+ call PrintQword
+
+ mov edi, 0b8460h
+
+ mov esi, offset StringR14 ; r14
+ call PrintString
+ db 48h
+ mov eax, [ebp+1*8]
+ call PrintQword
+
+ mov esi, offset StringR15 ; r15
+ call PrintString
+ db 48h
+ mov eax, [ebp+0*8]
+ call PrintQword
+
+ mov esi, offset StringSs ; ss
+ call PrintString
+ db 48h
+ mov eax, [ebp+22*8]
+ call PrintQword
+
+ mov edi, 0b8500h
+
+ mov esi, offset StringRflags ; rflags
+ call PrintString
+ db 48h
+ mov eax, [ebp+20*8]
+ call PrintQword
+
+ mov edi, 0b8640h
+
+ mov esi, ebp
+ add esi, 23*8
+ mov ecx, 4
+
+
+OuterLoop:
+ push ecx
+ mov ecx, 4
+ db 48h
+ mov edx, edi
+
+InnerLoop:
+ db 48h
+ mov eax, [esi]
+ call PrintQword
+ add esi, 8
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop
+
+
+ mov edi, 0b8960h
+
+ db 48h
+ mov eax, [ebp+18*8] ; RIP
+ sub eax, 8 * 8
+ db 48h
+ mov esi, eax ; esi = rip - 8 QWORD linear (total 16 QWORD)
+
+ mov ecx, 4
+
+OuterLoop1:
+ push ecx
+ mov ecx, 4
+ mov edx, edi
+
+InnerLoop1:
+ db 48h
+ mov eax, [esi]
+ call PrintQword
+ add esi, 8
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop1
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop1
+
+
+
+ wbinvd
+@@:
+ jmp @b
+
+;
+; return
+;
+ mov esp, ebp
+; mov rsp, rbp
+ db 41h
+ db 5fh
+; pop r15
+ db 41h
+ db 5eh
+; pop r14
+ db 41h
+ db 5dh
+; pop r13
+ db 41h
+ db 5ch
+; pop r12
+ db 41h
+ db 5bh
+; pop r11
+ db 41h
+ db 5ah
+; pop r10
+ db 41h
+ db 59h
+; pop r9
+ db 41h
+ db 58h
+; pop r8
+ pop edi
+ pop esi
+ pop ebp
+ pop eax ; esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ db 48h
+ db 83h
+ db 0c4h
+ db 10h
+; add esp, 16 ; error code and INT number
+
+ db 48h
+ db 0cfh
+; iretq
+
+PrintString:
+ push eax
+@@:
+ mov al, byte ptr [esi]
+ cmp al, 0
+ je @f
+ mov byte ptr [edi], al
+ db 0ffh
+ db 0c6h
+; inc esi
+ add edi, 2
+ jmp @b
+@@:
+ pop eax
+ ret
+
+;; RAX contains qword to print
+;; RDI contains memory location (screen location) to print it to
+PrintQword:
+ push ecx
+ push ebx
+ push eax
+
+ db 48h
+ db 0c7h
+ db 0c1h
+ dd 16
+; mov rcx, 16
+looptop:
+ db 48h
+ rol eax, 4
+ mov bl, al
+ and bl, 0fh
+ add bl, '0'
+ cmp bl, '9'
+ jle @f
+ add bl, 7
+@@:
+ mov byte ptr [edi], bl
+ add edi, 2
+ loop looptop
+ wbinvd
+
+ pop eax
+ pop ebx
+ pop ecx
+ ret
+
+ClearScreen:
+ push eax
+ push ecx
+
+ mov al, ' '
+ mov ah, 0ch
+ mov edi, 0b8000h
+ mov ecx, 80 * 24
+@@:
+ mov word ptr [edi], ax
+ add edi, 2
+ loop @b
+ mov edi, 0b8000h
+
+ pop ecx
+ pop eax
+
+ ret
+
+A2C:
+ and al, 0fh
+ add al, '0'
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+String1 db "*** INT ",0
+
+Int0String db "00h Divide by 0 -",0
+Int1String db "01h Debug exception -",0
+Int2String db "02h NMI -",0
+Int3String db "03h Breakpoint -",0
+Int4String db "04h Overflow -",0
+Int5String db "05h Bound -",0
+Int6String db "06h Invalid opcode -",0
+Int7String db "07h Device not available -",0
+Int8String db "08h Double fault -",0
+Int9String db "09h Coprocessor seg overrun (reserved) -",0
+Int10String db "0Ah Invalid TSS -",0
+Int11String db "0Bh Segment not present -",0
+Int12String db "0Ch Stack fault -",0
+Int13String db "0Dh General protection fault -",0
+Int14String db "0Eh Page fault -",0
+Int15String db "0Fh (Intel reserved) -",0
+Int16String db "10h Floating point error -",0
+Int17String db "11h Alignment check -",0
+Int18String db "12h Machine check -",0
+Int19String db "13h SIMD Floating-Point Exception -",0
+IntUnknownString db "??h Unknown interrupt -",0
+
+StringTable dq offset Int0String, offset Int1String, offset Int2String, offset Int3String,
+ offset Int4String, offset Int5String, offset Int6String, offset Int7String,
+ offset Int8String, offset Int9String, offset Int10String, offset Int11String,
+ offset Int12String, offset Int13String, offset Int14String, offset Int15String,
+ offset Int16String, offset Int17String, offset Int18String, offset Int19String
+
+String2 db " HALT!! *** (",0
+String3 db ")",0
+StringRax db "RAX=",0
+StringRcx db " RCX=",0
+StringRdx db " RDX=",0
+StringRbx db "RBX=",0
+StringRsp db " RSP=",0
+StringRbp db " RBP=",0
+StringRsi db "RSI=",0
+StringRdi db " RDI=",0
+StringEcode db " ECODE=",0
+StringR8 db "R8 =",0
+StringR9 db " R9 =",0
+StringR10 db " R10=",0
+StringR11 db "R11=",0
+StringR12 db " R12=",0
+StringR13 db " R13=",0
+StringR14 db "R14=",0
+StringR15 db " R15=",0
+StringSs db " SS =",0
+StringRflags db "RFLAGS=",0
+
+Idtr df 0
+ df 0
+
+ org 21ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/st16_64.asm b/DuetPkg/BootSector/st16_64.asm
new file mode 100644
index 0000000000..b2df0eb042
--- /dev/null
+++ b/DuetPkg/BootSector/st16_64.asm
@@ -0,0 +1,1140 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* st16_64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; FatOffset = ClusterNumber * 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/st32_64.asm b/DuetPkg/BootSector/st32_64.asm
new file mode 100644
index 0000000000..970cdc8f0d
--- /dev/null
+++ b/DuetPkg/BootSector/st32_64.asm
@@ -0,0 +1,1156 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* st32_64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+SectorSize dw 0 ; Sector Size - 2 bytes
+SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte
+ReservedSectors dw 0 ; Reserved Sectors - 2 bytes
+NoFats db 0 ; Number of FATs - 1 byte
+RootEntries dw 0 ; Root Entries - 2 bytes
+Sectors dw 0 ; Number of Sectors - 2 bytes
+Media db 0 ; Media - 1 byte
+SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte
+SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes
+Heads dw 0 ; Heads - 2 bytes
+HiddenSectors dd 0 ; Hidden Sectors - 4 bytes
+LargeSectors dd 0 ; Large Sectors - 4 bytes
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,2 ; FatOffset = ClusterNumber * 4
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start.asm b/DuetPkg/BootSector/start.asm
new file mode 100644
index 0000000000..e8eb22982d
--- /dev/null
+++ b/DuetPkg/BootSector/start.asm
@@ -0,0 +1,921 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0ff8h ; ax = ax & 0xff8
+ cmp ax,0ff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; ax = ClusterNumber * 2
+ add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
+ shr ax,1 ; FatOffset = ClusterNumber*3 / 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ and ax,1 ; See if this is an odd cluster number
+ je EvenFatEntry
+ shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
+EvenFatEntry:
+ and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start16.asm b/DuetPkg/BootSector/start16.asm
new file mode 100644
index 0000000000..4775c4e8a3
--- /dev/null
+++ b/DuetPkg/BootSector/start16.asm
@@ -0,0 +1,914 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start16.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; FatOffset = ClusterNumber * 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start32.asm b/DuetPkg/BootSector/start32.asm
new file mode 100644
index 0000000000..6cc6fcaa6c
--- /dev/null
+++ b/DuetPkg/BootSector/start32.asm
@@ -0,0 +1,929 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+SectorSize dw 0 ; Sector Size - 2 bytes
+SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte
+ReservedSectors dw 0 ; Reserved Sectors - 2 bytes
+NoFats db 0 ; Number of FATs - 1 byte
+RootEntries dw 0 ; Root Entries - 2 bytes
+Sectors dw 0 ; Number of Sectors - 2 bytes
+Media db 0 ; Media - 1 byte
+SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte
+SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes
+Heads dw 0 ; Heads - 2 bytes
+HiddenSectors dd 0 ; Hidden Sectors - 4 bytes
+LargeSectors dd 0 ; Large Sectors - 4 bytes
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,2 ; FatOffset = ClusterNumber * 4
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start64.asm b/DuetPkg/BootSector/start64.asm
new file mode 100644
index 0000000000..5491722e58
--- /dev/null
+++ b/DuetPkg/BootSector/start64.asm
@@ -0,0 +1,1147 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0ff8h ; ax = ax & 0xff8
+ cmp ax,0ff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; ax = ClusterNumber * 2
+ add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
+ shr ax,1 ; FatOffset = ClusterNumber*3 / 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ and ax,1 ; See if this is an odd cluster number
+ je EvenFatEntry
+ shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
+EvenFatEntry:
+ and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end