--- /dev/null
+[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
--- /dev/null
+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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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
--- /dev/null
+;------------------------------------------------------------------------------\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<