Porting Duet module from EDKI to EDKII
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 17 Apr 2008 05:48:13 +0000 (05:48 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 17 Apr 2008 05:48:13 +0000 (05:48 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5076 6f19259b-4bc3-4df7-8a09-765794883524

77 files changed:
DuetPkg/BootSector/BootSector.inf [new file with mode: 0644]
DuetPkg/BootSector/FILE.LST [new file with mode: 0644]
DuetPkg/BootSector/Gpt.asm [new file with mode: 0644]
DuetPkg/BootSector/Makefile [new file with mode: 0644]
DuetPkg/BootSector/Mbr.asm [new file with mode: 0644]
DuetPkg/BootSector/bootsect.asm [new file with mode: 0644]
DuetPkg/BootSector/bs16.asm [new file with mode: 0644]
DuetPkg/BootSector/bs32.asm [new file with mode: 0644]
DuetPkg/BootSector/efi32.asm [new file with mode: 0644]
DuetPkg/BootSector/efi64.asm [new file with mode: 0644]
DuetPkg/BootSector/st16_64.asm [new file with mode: 0644]
DuetPkg/BootSector/st32_64.asm [new file with mode: 0644]
DuetPkg/BootSector/start.asm [new file with mode: 0644]
DuetPkg/BootSector/start16.asm [new file with mode: 0644]
DuetPkg/BootSector/start32.asm [new file with mode: 0644]
DuetPkg/BootSector/start64.asm [new file with mode: 0644]
DuetPkg/CpuDxe/Cpu.c [new file with mode: 0644]
DuetPkg/CpuDxe/Cpu.dxs [new file with mode: 0644]
DuetPkg/CpuDxe/Cpu.inf [new file with mode: 0644]
DuetPkg/CpuDxe/CpuDxe.h [new file with mode: 0644]
DuetPkg/CpuDxe/Ia32/CpuInterrupt.asm [new file with mode: 0644]
DuetPkg/CpuDxe/x64/CpuInterrupt.asm [new file with mode: 0644]
DuetPkg/CpuIoDxe/CpuIo.c [new file with mode: 0644]
DuetPkg/CpuIoDxe/CpuIo.h [new file with mode: 0644]
DuetPkg/CpuIoDxe/CpuIo.inf [new file with mode: 0644]
DuetPkg/CpuIoDxe/CpuIoAccess.h [new file with mode: 0644]
DuetPkg/CpuIoDxe/Ia32/CpuIoAccess.asm [new file with mode: 0644]
DuetPkg/CpuIoDxe/Ia32CpuIo.dxs [new file with mode: 0644]
DuetPkg/CpuIoDxe/x64/CpuIoAccess.asm [new file with mode: 0644]
DuetPkg/DuetPkg.dec
DuetPkg/DuetPkg.dsc
DuetPkg/DuetPkg.fdf [new file with mode: 0644]
DuetPkg/DxeIpl/DxeIpl.inf
DuetPkg/Include/EfiFlashMap.h
DuetPkg/IsaAcpiDxe/ComponentName.c [new file with mode: 0644]
DuetPkg/IsaAcpiDxe/IsaAcpi.c [new file with mode: 0644]
DuetPkg/IsaAcpiDxe/IsaAcpi.inf [new file with mode: 0644]
DuetPkg/IsaAcpiDxe/PcatIsaAcpi.c [new file with mode: 0644]
DuetPkg/IsaAcpiDxe/PcatIsaAcpi.h [new file with mode: 0644]
DuetPkg/KbcResetDxe/Ia32/Ia32Reset.c [new file with mode: 0644]
DuetPkg/KbcResetDxe/Ia32Reset.dxs [new file with mode: 0644]
DuetPkg/KbcResetDxe/Ipf/IpfReset.c [new file with mode: 0644]
DuetPkg/KbcResetDxe/IpfReset.dxs [new file with mode: 0644]
DuetPkg/KbcResetDxe/Reset.c [new file with mode: 0644]
DuetPkg/KbcResetDxe/Reset.h [new file with mode: 0644]
DuetPkg/KbcResetDxe/Reset.inf [new file with mode: 0644]
DuetPkg/KbcResetDxe/x64/x64Reset.c [new file with mode: 0644]
DuetPkg/KbcResetDxe/x64Reset.dxs [new file with mode: 0644]
DuetPkg/LegacyMetronome/Metronome.c [new file with mode: 0644]
DuetPkg/LegacyMetronome/Metronome.dxs [new file with mode: 0644]
DuetPkg/LegacyMetronome/Metronome.h [new file with mode: 0644]
DuetPkg/LegacyMetronome/Metronome.inf [new file with mode: 0644]
DuetPkg/Library/DuetBdsLib/BdsPlatform.c [new file with mode: 0644]
DuetPkg/Library/DuetBdsLib/BdsPlatform.h [new file with mode: 0644]
DuetPkg/Library/DuetBdsLib/PlatformBds.inf [new file with mode: 0644]
DuetPkg/Library/DuetBdsLib/PlatformData.c [new file with mode: 0644]
DuetPkg/PcRtc/Ia32/RealTimeClock.c [new file with mode: 0644]
DuetPkg/PcRtc/Ia32RealTimeClock.dxs [new file with mode: 0644]
DuetPkg/PcRtc/Ipf/IpfPcRtc.c [new file with mode: 0644]
DuetPkg/PcRtc/IpfRealTimeClock.dxs [new file with mode: 0644]
DuetPkg/PcRtc/RealTimeClock.c [new file with mode: 0644]
DuetPkg/PcRtc/RealTimeClock.h [new file with mode: 0644]
DuetPkg/PcRtc/RealTimeClock.inf [new file with mode: 0644]
DuetPkg/PcRtc/x64/RealTimeClock.c [new file with mode: 0644]
DuetPkg/PcRtc/x64RealTimeClock.dxs [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf [new file with mode: 0644]
DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c [new file with mode: 0644]
DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.c [new file with mode: 0644]
DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.inf [new file with mode: 0644]

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