--- /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
+; bounds check (INT 5)\r
+BOUNDS_CHECK_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
+; invalid opcode (INT 6)\r
+INVALID_OPCODE_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
+; device not available (INT 7)\r
+DEV_NOT_AVAIL_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
+; double fault (INT 8)\r
+DOUBLE_FAULT_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
+; Coprocessor segment overrun - reserved (INT 9)\r
+RSVD_INTR_SEL1 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
+; invalid TSS (INT 0ah)\r
+INVALID_TSS_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
+; segment not present (INT 0bh)\r
+SEG_NOT_PRESENT_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
+; stack fault (INT 0ch)\r
+STACK_FAULT_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
+; general protection (INT 0dh)\r
+GP_FAULT_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
+; page fault (INT 0eh)\r
+PAGE_FAULT_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
+; Intel reserved - do not use (INT 0fh)\r
+RSVD_INTR_SEL2 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
+; floating point error (INT 10h)\r
+FLT_POINT_ERR_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
+; alignment check (INT 11h)\r
+ALIGNMENT_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; machine check (INT 12h)\r
+MACHINE_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; SIMD floating-point exception (INT 13h)\r
+SIMD_EXCEPTION_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail\r
+ db (85 * 8) 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_CODE_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
+\r
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
+IRQ1_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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_CODE_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
+\r
+; IRQ 3 (COM 2) - (INT 6bh)\r
+IRQ3_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 4 (COM 1) - (INT 6ch)\r
+IRQ4_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 5 (LPT 2) - (INT 6dh)\r
+IRQ5_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 6 (Floppy controller) - (INT 6eh)\r
+IRQ6_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 7 (LPT 1) - (INT 6fh)\r
+IRQ7_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 8 (RTC Alarm) - (INT 70h)\r
+IRQ8_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 9 - (INT 71h)\r
+IRQ9_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 10 - (INT 72h)\r
+IRQ10_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 11 - (INT 73h)\r
+IRQ11_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 12 (PS/2 mouse) - (INT 74h)\r
+IRQ12_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 13 (Floating point error) - (INT 75h)\r
+IRQ13_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 14 (Secondary IDE) - (INT 76h)\r
+IRQ14_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 15 (Primary IDE) - (INT 77h)\r
+IRQ15_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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
+;* start16.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
+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
+ 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
+; bounds check (INT 5)\r
+BOUNDS_CHECK_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
+; invalid opcode (INT 6)\r
+INVALID_OPCODE_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
+; device not available (INT 7)\r
+DEV_NOT_AVAIL_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
+; double fault (INT 8)\r
+DOUBLE_FAULT_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
+; Coprocessor segment overrun - reserved (INT 9)\r
+RSVD_INTR_SEL1 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
+; invalid TSS (INT 0ah)\r
+INVALID_TSS_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
+; segment not present (INT 0bh)\r
+SEG_NOT_PRESENT_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
+; stack fault (INT 0ch)\r
+STACK_FAULT_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
+; general protection (INT 0dh)\r
+GP_FAULT_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
+; page fault (INT 0eh)\r
+PAGE_FAULT_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
+; Intel reserved - do not use (INT 0fh)\r
+RSVD_INTR_SEL2 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
+; floating point error (INT 10h)\r
+FLT_POINT_ERR_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
+; alignment check (INT 11h)\r
+ALIGNMENT_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; machine check (INT 12h)\r
+MACHINE_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; SIMD floating-point exception (INT 13h)\r
+SIMD_EXCEPTION_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail\r
+ db (85 * 8) 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_CODE_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
+\r
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
+IRQ1_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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_CODE_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
+\r
+; IRQ 3 (COM 2) - (INT 6bh)\r
+IRQ3_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 4 (COM 1) - (INT 6ch)\r
+IRQ4_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 5 (LPT 2) - (INT 6dh)\r
+IRQ5_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 6 (Floppy controller) - (INT 6eh)\r
+IRQ6_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 7 (LPT 1) - (INT 6fh)\r
+IRQ7_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 8 (RTC Alarm) - (INT 70h)\r
+IRQ8_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 9 - (INT 71h)\r
+IRQ9_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 10 - (INT 72h)\r
+IRQ10_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 11 - (INT 73h)\r
+IRQ11_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 12 (PS/2 mouse) - (INT 74h)\r
+IRQ12_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 13 (Floating point error) - (INT 75h)\r
+IRQ13_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 14 (Secondary IDE) - (INT 76h)\r
+IRQ14_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 15 (Primary IDE) - (INT 77h)\r
+IRQ15_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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
+;* start32.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
+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
+ 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
+; bounds check (INT 5)\r
+BOUNDS_CHECK_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
+; invalid opcode (INT 6)\r
+INVALID_OPCODE_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
+; device not available (INT 7)\r
+DEV_NOT_AVAIL_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
+; double fault (INT 8)\r
+DOUBLE_FAULT_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
+; Coprocessor segment overrun - reserved (INT 9)\r
+RSVD_INTR_SEL1 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
+; invalid TSS (INT 0ah)\r
+INVALID_TSS_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
+; segment not present (INT 0bh)\r
+SEG_NOT_PRESENT_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
+; stack fault (INT 0ch)\r
+STACK_FAULT_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
+; general protection (INT 0dh)\r
+GP_FAULT_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
+; page fault (INT 0eh)\r
+PAGE_FAULT_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
+; Intel reserved - do not use (INT 0fh)\r
+RSVD_INTR_SEL2 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
+; floating point error (INT 10h)\r
+FLT_POINT_ERR_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
+; alignment check (INT 11h)\r
+ALIGNMENT_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; machine check (INT 12h)\r
+MACHINE_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; SIMD floating-point exception (INT 13h)\r
+SIMD_EXCEPTION_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail\r
+ db (85 * 8) 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_CODE_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
+\r
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
+IRQ1_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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_CODE_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
+\r
+; IRQ 3 (COM 2) - (INT 6bh)\r
+IRQ3_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 4 (COM 1) - (INT 6ch)\r
+IRQ4_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 5 (LPT 2) - (INT 6dh)\r
+IRQ5_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 6 (Floppy controller) - (INT 6eh)\r
+IRQ6_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 7 (LPT 1) - (INT 6fh)\r
+IRQ7_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 8 (RTC Alarm) - (INT 70h)\r
+IRQ8_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 9 - (INT 71h)\r
+IRQ9_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 10 - (INT 72h)\r
+IRQ10_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 11 - (INT 73h)\r
+IRQ11_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 12 (PS/2 mouse) - (INT 74h)\r
+IRQ12_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 13 (Floating point error) - (INT 75h)\r
+IRQ13_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 14 (Secondary IDE) - (INT 76h)\r
+IRQ14_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 15 (Primary IDE) - (INT 77h)\r
+IRQ15_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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
+;* start64.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
+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,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
+; 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 (c) 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
+Module Name:\r
+ Cpu.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "CpuDxe.h"\r
+\r
+//\r
+// Global Variables\r
+//\r
+\r
+BOOLEAN mInterruptState = FALSE;\r
+extern UINT32 mExceptionCodeSize;\r
+UINTN mTimerVector = 0;\r
+volatile EFI_CPU_INTERRUPT_HANDLER mTimerHandler = NULL;\r
+EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL;\r
+\r
+//\r
+// The Cpu Architectural Protocol that this Driver produces\r
+//\r
+EFI_HANDLE mHandle = NULL;\r
+EFI_CPU_ARCH_PROTOCOL mCpu = {\r
+ CpuFlushCpuDataCache,\r
+ CpuEnableInterrupt,\r
+ CpuDisableInterrupt,\r
+ CpuGetInterruptState,\r
+ CpuInit,\r
+ CpuRegisterInterruptHandler,\r
+ CpuGetTimerValue,\r
+ CpuSetMemoryAttributes,\r
+ 1, // NumberOfTimers\r
+ 4, // DmaBufferAlignment\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuFlushCpuDataCache (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS Start,\r
+ IN UINT64 Length,\r
+ IN EFI_CPU_FLUSH_TYPE FlushType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Flush CPU data cache. If the instruction cache is fully coherent\r
+ with all DMA operations then function can just return EFI_SUCCESS.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ Start - Physical address to start flushing from.\r
+ Length - Number of bytes to flush. Round up to chipset \r
+ granularity.\r
+ FlushType - Specifies the type of flush operation to perform.\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - If cache was flushed\r
+ EFI_UNSUPPORTED - If flush type is not supported.\r
+ EFI_DEVICE_ERROR - If requested range could not be flushed.\r
+\r
+--*/\r
+{\r
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
+ AsmWbinvd ();\r
+ return EFI_SUCCESS;\r
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {\r
+ AsmInvd ();\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuEnableInterrupt (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Enables CPU interrupts.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+\r
+Returns: \r
+ EFI_SUCCESS - If interrupts were enabled in the CPU\r
+ EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.\r
+\r
+--*/\r
+{\r
+ EnableInterrupts (); \r
+\r
+ mInterruptState = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuDisableInterrupt (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Disables CPU interrupts.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+\r
+Returns: \r
+ EFI_SUCCESS - If interrupts were disabled in the CPU.\r
+ EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.\r
+\r
+--*/\r
+{\r
+ DisableInterrupts ();\r
+ \r
+ mInterruptState = FALSE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetInterruptState (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ OUT BOOLEAN *State\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Return the state of interrupts.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ State - Pointer to the CPU's current interrupt state\r
+\r
+Returns: \r
+ EFI_SUCCESS - If interrupts were disabled in the CPU.\r
+ EFI_INVALID_PARAMETER - State is NULL.\r
+ \r
+--*/\r
+{\r
+ if (State == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *State = mInterruptState;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuInit (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_CPU_INIT_TYPE InitType\r
+ )\r
+\r
+/*++\r
+\r
+Routine Description:\r
+ Generates an INIT to the CPU\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ InitType - Type of CPU INIT to perform\r
+\r
+Returns: \r
+ EFI_SUCCESS - If CPU INIT occurred. This value should never be\r
+ seen.\r
+ EFI_DEVICE_ERROR - If CPU INIT failed.\r
+ EFI_NOT_SUPPORTED - Requested type of CPU INIT not supported.\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuRegisterInterruptHandler (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Registers a function to be called from the CPU interrupt handler.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ InterruptType - Defines which interrupt to hook. IA-32 valid range\r
+ is 0x00 through 0xFF\r
+ InterruptHandler - A pointer to a function of type \r
+ EFI_CPU_INTERRUPT_HANDLER that is called when a\r
+ processor interrupt occurs. A null pointer\r
+ is an error condition.\r
+\r
+Returns: \r
+ EFI_SUCCESS - If handler installed or uninstalled.\r
+ EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for \r
+ InterruptType was previously installed\r
+ EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for \r
+ InterruptType was not previously installed.\r
+ EFI_UNSUPPORTED - The interrupt specified by InterruptType is not\r
+ supported.\r
+\r
+--*/\r
+{\r
+ if ((InterruptType < 0) || (InterruptType >= INTERRUPT_VECTOR_NUMBER)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ if ((UINTN)(UINT32)InterruptType != mTimerVector) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ if ((mTimerHandler == NULL) && (InterruptHandler == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else if ((mTimerHandler != NULL) && (InterruptHandler != NULL)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ mTimerHandler = InterruptHandler;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetTimerValue (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN UINT32 TimerIndex,\r
+ OUT UINT64 *TimerValue,\r
+ OUT UINT64 *TimerPeriod OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Returns a timer value from one of the CPU's internal timers. There is no\r
+ inherent time interval between ticks but is a function of the CPU \r
+ frequency.\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ TimerIndex - Specifies which CPU timer ie requested\r
+ TimerValue - Pointer to the returned timer value\r
+ TimerPeriod - \r
+\r
+Returns: \r
+ EFI_SUCCESS - If the CPU timer count was returned.\r
+ EFI_UNSUPPORTED - If the CPU does not have any readable timers\r
+ EFI_DEVICE_ERROR - If an error occurred reading the timer.\r
+ EFI_INVALID_PARAMETER - TimerIndex is not valid\r
+\r
+--*/\r
+{ \r
+ if (TimerValue == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if (TimerIndex == 0) {\r
+ *TimerValue = AsmReadTsc ();\r
+ if (TimerPeriod != NULL) {\r
+ //\r
+ // BugBug: Hard coded. Don't know how to do this generically\r
+ //\r
+ *TimerPeriod = 1000000000;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuSetMemoryAttributes (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Set memory cacheability attributes for given range of memeory\r
+\r
+Arguments:\r
+ This - Protocol instance structure\r
+ BaseAddress - Specifies the start address of the memory range\r
+ Length - Specifies the length of the memory range\r
+ Attributes - The memory cacheability for the memory range\r
+\r
+Returns: \r
+ EFI_SUCCESS - If the cacheability of that memory range is set successfully\r
+ EFI_UNSUPPORTED - If the desired operation cannot be done\r
+ EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+#if CPU_EXCEPTION_DEBUG_OUTPUT\r
+STATIC\r
+VOID\r
+DumpExceptionDataDebugOut (\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ UINT32 ErrorCodeFlag;\r
+\r
+ ErrorCodeFlag = 0x00027d00;\r
+\r
+#ifdef EFI32\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "!!!! IA32 Exception Type - %08x !!!!\n",\r
+ InterruptType\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",\r
+ SystemContext.SystemContextIa32->Eip,\r
+ SystemContext.SystemContextIa32->Cs,\r
+ SystemContext.SystemContextIa32->Eflags\r
+ ));\r
+ if (ErrorCodeFlag & (1 << InterruptType)) {\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "ExceptionData - %08x\n",\r
+ SystemContext.SystemContextIa32->ExceptionData\r
+ ));\r
+ }\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",\r
+ SystemContext.SystemContextIa32->Eax,\r
+ SystemContext.SystemContextIa32->Ecx,\r
+ SystemContext.SystemContextIa32->Edx,\r
+ SystemContext.SystemContextIa32->Ebx\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",\r
+ SystemContext.SystemContextIa32->Esp,\r
+ SystemContext.SystemContextIa32->Ebp,\r
+ SystemContext.SystemContextIa32->Esi,\r
+ SystemContext.SystemContextIa32->Edi\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",\r
+ SystemContext.SystemContextIa32->Ds,\r
+ SystemContext.SystemContextIa32->Es,\r
+ SystemContext.SystemContextIa32->Fs,\r
+ SystemContext.SystemContextIa32->Gs,\r
+ SystemContext.SystemContextIa32->Ss\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",\r
+ SystemContext.SystemContextIa32->Gdtr[0],\r
+ SystemContext.SystemContextIa32->Gdtr[1],\r
+ SystemContext.SystemContextIa32->Idtr[0],\r
+ SystemContext.SystemContextIa32->Idtr[1]\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "LDTR - %08x, TR - %08x\n",\r
+ SystemContext.SystemContextIa32->Ldtr,\r
+ SystemContext.SystemContextIa32->Tr\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",\r
+ SystemContext.SystemContextIa32->Cr0,\r
+ SystemContext.SystemContextIa32->Cr2,\r
+ SystemContext.SystemContextIa32->Cr3,\r
+ SystemContext.SystemContextIa32->Cr4\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",\r
+ SystemContext.SystemContextIa32->Dr0,\r
+ SystemContext.SystemContextIa32->Dr1,\r
+ SystemContext.SystemContextIa32->Dr2,\r
+ SystemContext.SystemContextIa32->Dr3\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DR6 - %08x, DR7 - %08x\n",\r
+ SystemContext.SystemContextIa32->Dr6,\r
+ SystemContext.SystemContextIa32->Dr7\r
+ ));\r
+#else\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "!!!! X64 Exception Type - %016lx !!!!\n",\r
+ (UINT64)InterruptType\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",\r
+ SystemContext.SystemContextX64->Rip,\r
+ SystemContext.SystemContextX64->Cs,\r
+ SystemContext.SystemContextX64->Rflags\r
+ ));\r
+ if (ErrorCodeFlag & (1 << InterruptType)) {\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "ExceptionData - %016lx\n",\r
+ SystemContext.SystemContextX64->ExceptionData\r
+ ));\r
+ }\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
+ SystemContext.SystemContextX64->Rax,\r
+ SystemContext.SystemContextX64->Rcx,\r
+ SystemContext.SystemContextX64->Rdx\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
+ SystemContext.SystemContextX64->Rbx,\r
+ SystemContext.SystemContextX64->Rsp,\r
+ SystemContext.SystemContextX64->Rbp\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "RSI - %016lx, RDI - %016lx\n",\r
+ SystemContext.SystemContextX64->Rsi,\r
+ SystemContext.SystemContextX64->Rdi\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",\r
+ SystemContext.SystemContextX64->R8,\r
+ SystemContext.SystemContextX64->R9,\r
+ SystemContext.SystemContextX64->R10\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
+ SystemContext.SystemContextX64->R11,\r
+ SystemContext.SystemContextX64->R12,\r
+ SystemContext.SystemContextX64->R13\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "R14 - %016lx, R15 - %016lx\n",\r
+ SystemContext.SystemContextX64->R14,\r
+ SystemContext.SystemContextX64->R15\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",\r
+ SystemContext.SystemContextX64->Ds,\r
+ SystemContext.SystemContextX64->Es,\r
+ SystemContext.SystemContextX64->Fs\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "GS - %016lx, SS - %016lx\n",\r
+ SystemContext.SystemContextX64->Gs,\r
+ SystemContext.SystemContextX64->Ss\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",\r
+ SystemContext.SystemContextX64->Gdtr[0],\r
+ SystemContext.SystemContextX64->Gdtr[1],\r
+ SystemContext.SystemContextX64->Ldtr\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "IDTR - %016lx %016lx, TR - %016lx\n",\r
+ SystemContext.SystemContextX64->Idtr[0],\r
+ SystemContext.SystemContextX64->Idtr[1],\r
+ SystemContext.SystemContextX64->Tr\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
+ SystemContext.SystemContextX64->Cr0,\r
+ SystemContext.SystemContextX64->Cr2,\r
+ SystemContext.SystemContextX64->Cr3\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "CR4 - %016lx, CR8 - %016lx\n",\r
+ SystemContext.SystemContextX64->Cr4,\r
+ SystemContext.SystemContextX64->Cr8\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
+ SystemContext.SystemContextX64->Dr0,\r
+ SystemContext.SystemContextX64->Dr1,\r
+ SystemContext.SystemContextX64->Dr2\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
+ SystemContext.SystemContextX64->Dr3,\r
+ SystemContext.SystemContextX64->Dr6,\r
+ SystemContext.SystemContextX64->Dr7\r
+ ));\r
+#endif\r
+ return ;\r
+}\r
+#endif\r
+\r
+STATIC\r
+UINTN\r
+SPrint (\r
+ IN OUT CHAR16 *Buffer,\r
+ IN CONST CHAR16 *Format,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Marker;\r
+ UINTN Index;\r
+ UINTN Flags;\r
+ UINTN Width;\r
+ UINT64 Value;\r
+\r
+ VA_START (Marker, Format);\r
+\r
+ //\r
+ // Process the format string. Stop if Buffer is over run.\r
+ //\r
+\r
+ for (Index = 0; *Format != 0; Format++) {\r
+ if (*Format != L'%') {\r
+ Buffer[Index++] = *Format;\r
+ } else {\r
+ \r
+ //\r
+ // Now it's time to parse what follows after %\r
+ // Support: % [ 0 width ] [ l ] x\r
+ // width - fill 0, to ensure the width of x will be "width"\r
+ // l - UINT64 instead of UINT32\r
+ //\r
+ Width = 0;\r
+ Flags = 0;\r
+ Format ++;\r
+\r
+ if (*Format == L'0') {\r
+ Flags |= PREFIX_ZERO;\r
+ do {\r
+ Width += Width * 10 + (*Format - L'0');\r
+ Format ++;\r
+ } while (*Format >= L'1' && *Format <= L'9');\r
+ }\r
+\r
+ if (*Format == L'l') {\r
+ Flags |= LONG_TYPE;\r
+ Format ++;\r
+ }\r
+\r
+ \r
+ switch (*Format) {\r
+ case 'X':\r
+ Flags |= PREFIX_ZERO;\r
+ Width = sizeof (UINT64) * 2;\r
+ //\r
+ // break skiped on purpose\r
+ //\r
+ case 'x':\r
+ if ((Flags & LONG_TYPE) == LONG_TYPE) {\r
+ Value = VA_ARG (Marker, UINT64);\r
+ } else {\r
+ Value = VA_ARG (Marker, UINTN);\r
+ }\r
+\r
+ UnicodeValueToString (Buffer+Index, Flags, Value, Width);\r
+ \r
+ for ( ; Buffer[Index] != L'\0'; Index ++) {\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // if the type is unknown print it to the screen\r
+ //\r
+ Buffer[Index++] = *Format;\r
+ }\r
+ } \r
+ }\r
+ Buffer[Index++] = '\0'; \r
+ \r
+ VA_END (Marker);\r
+ return Index;\r
+}\r
+\r
+STATIC\r
+VOID\r
+DumpExceptionDataVgaOut (\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ UINTN COLUMN_MAX;\r
+ UINTN ROW_MAX;\r
+ UINT32 ErrorCodeFlag;\r
+ CHAR16 *VideoBufferBase;\r
+ CHAR16 *VideoBuffer;\r
+ UINTN Index;\r
+\r
+ COLUMN_MAX = 80;\r
+ ROW_MAX = 25;\r
+ ErrorCodeFlag = 0x00027d00;\r
+ VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000;\r
+ VideoBuffer = (CHAR16 *) (UINTN) 0xb8000;\r
+\r
+#ifdef EFI32\r
+ SPrint (\r
+ VideoBuffer, \r
+ L"!!!! IA32 Exception Type - %08x !!!!",\r
+ InterruptType\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+ SPrint (\r
+ VideoBuffer, \r
+ L"EIP - %08x, CS - %08x, EFLAGS - %08x",\r
+ SystemContext.SystemContextIa32->Eip,\r
+ SystemContext.SystemContextIa32->Cs,\r
+ SystemContext.SystemContextIa32->Eflags\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+ if (ErrorCodeFlag & (1 << InterruptType)) {\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"ExceptionData - %08x",\r
+ SystemContext.SystemContextIa32->ExceptionData\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+ }\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x",\r
+ SystemContext.SystemContextIa32->Eax,\r
+ SystemContext.SystemContextIa32->Ecx,\r
+ SystemContext.SystemContextIa32->Edx,\r
+ SystemContext.SystemContextIa32->Ebx\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x",\r
+ SystemContext.SystemContextIa32->Esp,\r
+ SystemContext.SystemContextIa32->Ebp,\r
+ SystemContext.SystemContextIa32->Esi,\r
+ SystemContext.SystemContextIa32->Edi\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x",\r
+ SystemContext.SystemContextIa32->Ds,\r
+ SystemContext.SystemContextIa32->Es,\r
+ SystemContext.SystemContextIa32->Fs,\r
+ SystemContext.SystemContextIa32->Gs,\r
+ SystemContext.SystemContextIa32->Ss\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"GDTR - %08x %08x, IDTR - %08x %08x",\r
+ SystemContext.SystemContextIa32->Gdtr[0],\r
+ SystemContext.SystemContextIa32->Gdtr[1],\r
+ SystemContext.SystemContextIa32->Idtr[0],\r
+ SystemContext.SystemContextIa32->Idtr[1]\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"LDTR - %08x, TR - %08x",\r
+ SystemContext.SystemContextIa32->Ldtr,\r
+ SystemContext.SystemContextIa32->Tr\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x",\r
+ SystemContext.SystemContextIa32->Cr0,\r
+ SystemContext.SystemContextIa32->Cr2,\r
+ SystemContext.SystemContextIa32->Cr3,\r
+ SystemContext.SystemContextIa32->Cr4\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x",\r
+ SystemContext.SystemContextIa32->Dr0,\r
+ SystemContext.SystemContextIa32->Dr1,\r
+ SystemContext.SystemContextIa32->Dr2,\r
+ SystemContext.SystemContextIa32->Dr3\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DR6 - %08x, DR7 - %08x",\r
+ SystemContext.SystemContextIa32->Dr6,\r
+ SystemContext.SystemContextIa32->Dr7\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+#else\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"!!!! X64 Exception Type - %016lx !!!!",\r
+ (UINT64)InterruptType\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"RIP - %016lx, CS - %016lx, RFLAGS - %016lx",\r
+ SystemContext.SystemContextX64->Rip,\r
+ SystemContext.SystemContextX64->Cs,\r
+ SystemContext.SystemContextX64->Rflags\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ if (ErrorCodeFlag & (1 << InterruptType)) {\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"ExceptionData - %016lx",\r
+ SystemContext.SystemContextX64->ExceptionData\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+ }\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"RAX - %016lx, RCX - %016lx, RDX - %016lx",\r
+ SystemContext.SystemContextX64->Rax,\r
+ SystemContext.SystemContextX64->Rcx,\r
+ SystemContext.SystemContextX64->Rdx\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"RBX - %016lx, RSP - %016lx, RBP - %016lx",\r
+ SystemContext.SystemContextX64->Rbx,\r
+ SystemContext.SystemContextX64->Rsp,\r
+ SystemContext.SystemContextX64->Rbp\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"RSI - %016lx, RDI - %016lx",\r
+ SystemContext.SystemContextX64->Rsi,\r
+ SystemContext.SystemContextX64->Rdi\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"R8 - %016lx, R9 - %016lx, R10 - %016lx",\r
+ SystemContext.SystemContextX64->R8,\r
+ SystemContext.SystemContextX64->R9,\r
+ SystemContext.SystemContextX64->R10\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"R11 - %016lx, R12 - %016lx, R13 - %016lx",\r
+ SystemContext.SystemContextX64->R11,\r
+ SystemContext.SystemContextX64->R12,\r
+ SystemContext.SystemContextX64->R13\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"R14 - %016lx, R15 - %016lx",\r
+ SystemContext.SystemContextX64->R14,\r
+ SystemContext.SystemContextX64->R15\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DS - %016lx, ES - %016lx, FS - %016lx",\r
+ SystemContext.SystemContextX64->Ds,\r
+ SystemContext.SystemContextX64->Es,\r
+ SystemContext.SystemContextX64->Fs\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"GS - %016lx, SS - %016lx",\r
+ SystemContext.SystemContextX64->Gs,\r
+ SystemContext.SystemContextX64->Ss\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"GDTR - %016lx %016lx, LDTR - %016lx",\r
+ SystemContext.SystemContextX64->Gdtr[0],\r
+ SystemContext.SystemContextX64->Gdtr[1],\r
+ SystemContext.SystemContextX64->Ldtr\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"IDTR - %016lx %016lx, TR - %016lx",\r
+ SystemContext.SystemContextX64->Idtr[0],\r
+ SystemContext.SystemContextX64->Idtr[1],\r
+ SystemContext.SystemContextX64->Tr\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"CR0 - %016lx, CR2 - %016lx, CR3 - %016lx",\r
+ SystemContext.SystemContextX64->Cr0,\r
+ SystemContext.SystemContextX64->Cr2,\r
+ SystemContext.SystemContextX64->Cr3\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"CR4 - %016lx, CR8 - %016lx",\r
+ SystemContext.SystemContextX64->Cr4,\r
+ SystemContext.SystemContextX64->Cr8\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DR0 - %016lx, DR1 - %016lx, DR2 - %016lx",\r
+ SystemContext.SystemContextX64->Dr0,\r
+ SystemContext.SystemContextX64->Dr1,\r
+ SystemContext.SystemContextX64->Dr2\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+\r
+ SPrint (\r
+ VideoBuffer,\r
+ L"DR3 - %016lx, DR6 - %016lx, DR7 - %016lx",\r
+ SystemContext.SystemContextX64->Dr3,\r
+ SystemContext.SystemContextX64->Dr6,\r
+ SystemContext.SystemContextX64->Dr7\r
+ );\r
+ VideoBuffer += COLUMN_MAX;\r
+#endif\r
+\r
+ for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) {\r
+ if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) {\r
+ VideoBufferBase[Index] = 0x0c20;\r
+ } else {\r
+ VideoBufferBase[Index] |= 0x0c00;\r
+ }\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+#if CPU_EXCEPTION_VGA_SWITCH\r
+STATIC\r
+UINT16\r
+SwitchVideoMode (\r
+ UINT16 NewVideoMode\r
+ )\r
+/*++\r
+Description\r
+ Switch Video Mode from current mode to new mode, and return the old mode.\r
+ Use Thuink\r
+\r
+Arguments\r
+ NewVideoMode - new video mode want to set\r
+\r
+Return\r
+ UINT16 - (UINT16) -1 indicates failure\r
+ Other value indicates the old mode, which can be used for restore later\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_THUNK_PROTOCOL *LegacyBios;\r
+ EFI_IA32_REGISTER_SET Regs;\r
+ UINT16 OriginalVideoMode = (UINT16) -1;\r
+ \r
+ //\r
+ // See if the Legacy BIOS Protocol is available\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosThunkProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return OriginalVideoMode;\r
+ }\r
+\r
+ //\r
+ // VESA SuperVGA BIOS - GET CURRENT VIDEO MODE\r
+ // AX = 4F03h\r
+ // Return:AL = 4Fh if function supported\r
+ // AH = status 00h successful\r
+ // BX = video mode (see #0082,#0083)\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.X.AX = 0x4F03;\r
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ if (Regs.X.AX == 0x004F) {\r
+ OriginalVideoMode = Regs.X.BX;\r
+ } else {\r
+ //\r
+ // VIDEO - GET CURRENT VIDEO MODE\r
+ // AH = 0Fh\r
+ // Return:AH = number of character columns\r
+ // AL = display mode (see #0009 at AH=00h)\r
+ // BH = active page (see AH=05h)\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.H.AH = 0x0F;\r
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ OriginalVideoMode = Regs.H.AL;\r
+ }\r
+\r
+ //\r
+ // Set new video mode\r
+ //\r
+ if (NewVideoMode < 0x100) {\r
+ //\r
+ // Set the 80x25 Text VGA Mode: Assume successful always\r
+ //\r
+ // VIDEO - SET VIDEO MODE\r
+ // AH = 00h\r
+ // AL = desired video mode (see #0009)\r
+ // Return:AL = video mode flag (Phoenix, AMI BIOS)\r
+ // 20h mode > 7\r
+ // 30h modes 0-5 and 7\r
+ // 3Fh mode 6\r
+ // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.H.AH = 0x00;\r
+ Regs.H.AL = (UINT8) NewVideoMode;\r
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+\r
+ //\r
+ // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)\r
+ // AX = 1114h\r
+ // BL = block to load\r
+ // Return:Nothing\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.H.AH = 0x11;\r
+ Regs.H.AL = 0x14;\r
+ Regs.H.BL = 0;\r
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ } else {\r
+ //\r
+ // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE\r
+ // AX = 4F02h\r
+ // BX = mode (see #0082,#0083)\r
+ // bit 15 set means don't clear video memory\r
+ // bit 14 set means enable linear framebuffer mode (VBE v2.0+)\r
+ // Return:AL = 4Fh if function supported\r
+ // AH = status\r
+ // 00h successful\r
+ // 01h failed\r
+ //\r
+ gBS->SetMem (&Regs, sizeof (Regs), 0);\r
+ Regs.X.AX = 0x4F02;\r
+ Regs.X.BX = NewVideoMode;\r
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);\r
+ if (Regs.X.AX != 0x004F) {\r
+ DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));\r
+ return (UINT16) -1;\r
+ }\r
+ }\r
+\r
+ return OriginalVideoMode;\r
+}\r
+#endif\r
+\r
+VOID\r
+ExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+#if CPU_EXCEPTION_VGA_SWITCH\r
+ UINT16 VideoMode;\r
+#endif\r
+\r
+#if CPU_EXCEPTION_DEBUG_OUTPUT\r
+ DumpExceptionDataDebugOut (InterruptType, SystemContext);\r
+#endif\r
+\r
+#if CPU_EXCEPTION_VGA_SWITCH\r
+ //\r
+ // Switch to text mode for RED-SCREEN output\r
+ //\r
+ VideoMode = SwitchVideoMode (0x83);\r
+ if (VideoMode == (UINT16) -1) {\r
+ DEBUG ((EFI_D_ERROR, "Video Mode Unknown!\n"));\r
+ }\r
+#endif\r
+\r
+ DumpExceptionDataVgaOut (InterruptType, SystemContext);\r
+\r
+ //\r
+ // Use this macro to hang so that the compiler does not optimize out\r
+ // the following RET instructions. This allows us to return if we\r
+ // have a debugger attached.\r
+ //\r
+ CpuDeadLoop ();\r
+\r
+#if CPU_EXCEPTION_VGA_SWITCH\r
+ //\r
+ // Switch back to the old video mode\r
+ //\r
+ if (VideoMode != (UINT16)-1) {\r
+ SwitchVideoMode (VideoMode);\r
+ }\r
+#endif\r
+\r
+ return ;\r
+}\r
+\r
+VOID\r
+TimerHandler (\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ if (mTimerHandler != NULL) {\r
+ mTimerHandler (InterruptType, SystemContext);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpu (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize the state information for the CPU Architectural Protocol\r
+\r
+Arguments:\r
+ ImageHandle of the loaded driver\r
+ Pointer to the System Table\r
+\r
+Returns:\r
+ EFI_SUCCESS - thread can be successfully created\r
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
+ EFI_DEVICE_ERROR - cannot create the thread\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_8259_IRQ Irq;\r
+ UINT32 InterruptVector;\r
+\r
+ //\r
+ // Find the Legacy8259 protocol.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver\r
+ //\r
+ Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Reload GDT, IDT\r
+ //\r
+ InitDescriptor ();\r
+\r
+ //\r
+ // Install Exception Handler (0x00 ~ 0x1F)\r
+ //\r
+ for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) {\r
+ InstallInterruptHandler (\r
+ InterruptVector,\r
+ (VOID (*)(VOID))(UINTN)((UINTN)SystemExceptionHandler + mExceptionCodeSize * InterruptVector)\r
+ );\r
+ }\r
+\r
+ //\r
+ // Install Timer Handler\r
+ //\r
+ InstallInterruptHandler (mTimerVector, SystemTimerHandler);\r
+\r
+ //\r
+ // BUGBUG: We add all other interrupt vector\r
+ //\r
+ for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) {\r
+ InterruptVector = 0;\r
+ Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector);\r
+ ASSERT_EFI_ERROR (Status);\r
+ InstallInterruptHandler (InterruptVector, SystemTimerHandler);\r
+ }\r
+\r
+ //\r
+ // Install CPU Architectural Protocol and the thunk protocol\r
+ //\r
+ mHandle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEfiCpuArchProtocolGuid,\r
+ &mCpu,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ Cpu.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+#include "EfiDepex.h"\r
+#include EFI_PROTOCOL_DEFINITION (Legacy8259)\r
+\r
+DEPENDENCY_START\r
+ EFI_LEGACY_8259_PROTOCOL_GUID\r
+DEPENDENCY_END\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 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
+# Module Name:\r
+# Cpu.inf\r
+#\r
+# Abstract:\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Cpu\r
+ FILE_GUID = 10527025-78B2-4d3e-A9DF-41E75C220F5A\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializeCpu\r
+\r
+[Packages]\r
+ DuetPkg/DuetPkg.dec\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ PrintLib\r
+ UefiBootServicesTableLib\r
+\r
+[Sources.IA32]\r
+ IA32/CpuInterrupt.asm\r
+\r
+[Sources.X64]\r
+ X64/CpuInterrupt.asm\r
+\r
+[Sources.common]\r
+ Cpu.c\r
+ CpuDxe.h\r
+\r
+[Protocols]\r
+ gEfiCpuArchProtocolGuid\r
+ gEfiLegacyBiosThunkProtocolGuid\r
+ gEfiLegacy8259ProtocolGuid\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ CpuDxe.h\r
+\r
+Abstract:\r
+\r
+--*/\r
+#ifndef _CPU_DXE_H\r
+#define _CPU_DXE_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/Legacy8259.h>\r
+\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/LegacyBiosThunk.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#define CPU_EXCEPTION_DEBUG_OUTPUT 1\r
+#define CPU_EXCEPTION_VGA_SWITCH 1\r
+\r
+#define INTERRUPT_VECTOR_NUMBER 0x100\r
+\r
+//\r
+// Print primitives\r
+//\r
+//#define LEFT_JUSTIFY 0x01\r
+#define PREFIX_SIGN 0x02\r
+#define PREFIX_BLANK 0x04\r
+//#define COMMA_TYPE 0x08\r
+#define LONG_TYPE 0x10\r
+//#define PREFIX_ZERO 0x20\r
+#define OUTPUT_UNICODE 0x40\r
+//#define RADIX_HEX 0x80\r
+#define FORMAT_UNICODE 0x100\r
+#define PAD_TO_WIDTH 0x200\r
+#define ARGUMENT_UNICODE 0x400\r
+#define PRECISION 0x800\r
+#define ARGUMENT_REVERSED 0x1000\r
+\r
+//\r
+// Function declarations\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpu (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuFlushCpuDataCache (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS Start,\r
+ IN UINT64 Length,\r
+ IN EFI_CPU_FLUSH_TYPE FlushType\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuEnableInterrupt (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuDisableInterrupt (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetInterruptState (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ OUT BOOLEAN *State\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuInit (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_CPU_INIT_TYPE InitType\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuRegisterInterruptHandler (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetTimerValue (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN UINT32 TimerIndex,\r
+ OUT UINT64 *TimerValue,\r
+ OUT UINT64 *TimerPeriod OPTIONAL\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+CpuSetMemoryAttributes(\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ ); \r
+\r
+VOID\r
+InstallInterruptHandler (\r
+ UINTN Vector,\r
+ VOID (*Handler)(VOID)\r
+ );\r
+\r
+VOID\r
+SystemExceptionHandler (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+SystemTimerHandler (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+InitDescriptor (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+ TITLE CpuInterrupt.asm: \r
+;------------------------------------------------------------------------------\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
+;* CpuInterrupt.asm\r
+;* \r
+;* Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+.686p\r
+.model flat, C\r
+\r
+PUBLIC SystemTimerHandler\r
+PUBLIC SystemExceptionHandler\r
+EXTERNDEF mExceptionCodeSize:DWORD\r
+\r
+.code\r
+.stack\r
+.MMX\r
+.XMM\r
+\r
+EXTERN TimerHandler: NEAR\r
+EXTERN ExceptionHandler: NEAR\r
+EXTERN mTimerVector: DWORD\r
+\r
+mExceptionCodeSize DD 9\r
+\r
+InitDescriptor PROC C\r
+ lea eax, [GDT_BASE] ; EAX=PHYSICAL address of gdt\r
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr\r
+ lgdt fword ptr [gdtr]\r
+ lea eax, [IDT_BASE] ; EAX=PHYSICAL address of idt\r
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr\r
+ lidt fword ptr [idtr]\r
+ ret\r
+InitDescriptor ENDP\r
+\r
+; VOID\r
+; InstallInterruptHandler (\r
+; UINTN Vector,\r
+; VOID (*Handler)(VOID)\r
+; )\r
+InstallInterruptHandler PROC C \\r
+ Vector:DWORD, \\r
+ Handler:DWORD\r
+\r
+ push edi\r
+ pushfd ; save eflags\r
+ cli ; turn off interrupts\r
+ sub esp, 6 ; open some space on the stack\r
+ mov edi, esp\r
+ sidt es:[edi] ; get fword address of IDT\r
+ mov edi, es:[edi+2] ; move offset of IDT into EDI\r
+ add esp, 6 ; correct stack\r
+ mov eax, Vector ; Get vector number\r
+ shl eax, 3 ; multiply by 8 to get offset\r
+ add edi, eax ; add to IDT base to get entry\r
+ mov eax, Handler ; load new address into IDT entry\r
+ mov word ptr es:[edi], ax ; write bits 15..0 of offset\r
+ shr eax, 16 ; use ax to copy 31..16 to descriptors\r
+ mov word ptr es:[edi+6], ax ; write bits 31..16 of offset\r
+ popfd ; restore flags (possible enabling interrupts)\r
+ pop edi\r
+ ret\r
+\r
+InstallInterruptHandler ENDP\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
+ align 02h\r
+SystemExceptionHandler PROC\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 (32 - 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
+SystemExceptionHandler ENDP\r
+\r
+SystemTimerHandler PROC\r
+ push 0\r
+ push mTimerVector\r
+ JmpCommonIdtEntry\r
+SystemTimerHandler ENDP\r
+\r
+commonIdtEntry:\r
+; +---------------------+\r
+; + EFlags +\r
+; +---------------------+\r
+; + CS +\r
+; +---------------------+\r
+; + EIP +\r
+; +---------------------+\r
+; + Error Code +\r
+; +---------------------+\r
+; + Vector Number +\r
+; +---------------------+\r
+; + EBP +\r
+; +---------------------+ <-- EBP\r
+\r
+ cli\r
+ push ebp\r
+ mov ebp, esp\r
+\r
+ ;\r
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+ ; is 16-byte aligned\r
+ ;\r
+ and esp, 0fffffff0h\r
+ sub esp, 12\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ push eax\r
+ push ecx\r
+ push edx\r
+ push ebx\r
+ lea ecx, [ebp + 6 * 4]\r
+ push ecx ; ESP\r
+ push dword ptr [ebp] ; EBP\r
+ push esi\r
+ push edi\r
+\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+ mov eax, ss\r
+ push eax\r
+ movzx eax, word ptr [ebp + 4 * 4]\r
+ push eax\r
+ mov eax, ds\r
+ push eax\r
+ mov eax, es\r
+ push eax\r
+ mov eax, fs\r
+ push eax\r
+ mov eax, gs\r
+ push eax\r
+\r
+;; UINT32 Eip;\r
+ push dword ptr [ebp + 3 * 4]\r
+\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+ sub esp, 8\r
+ sidt fword ptr [esp]\r
+ sub esp, 8\r
+ sgdt fword ptr [esp]\r
+\r
+;; UINT32 Ldtr, Tr;\r
+ xor eax, eax\r
+ str ax\r
+ push eax\r
+ sldt ax\r
+ push eax\r
+\r
+;; UINT32 EFlags;\r
+ push dword ptr [ebp + 5 * 4]\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ mov eax, cr4\r
+ or eax, 208h\r
+ mov cr4, eax\r
+ push eax\r
+ mov eax, cr3\r
+ push eax\r
+ mov eax, cr2\r
+ push eax\r
+ xor eax, eax\r
+ push eax\r
+ mov eax, cr0\r
+ push eax\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov eax, dr7\r
+ push eax\r
+;; clear Dr7 while executing debugger itself\r
+ xor eax, eax\r
+ mov dr7, eax\r
+\r
+ mov eax, dr6\r
+ push eax\r
+;; insure all status bits in dr6 are clear...\r
+ xor eax, eax\r
+ mov dr6, eax\r
+\r
+ mov eax, dr3\r
+ push eax\r
+ mov eax, dr2\r
+ push eax\r
+ mov eax, dr1\r
+ push eax\r
+ mov eax, dr0\r
+ push eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ sub esp, 512\r
+ mov edi, esp\r
+ db 0fh, 0aeh, 00000111y ;fxsave [edi]\r
+\r
+;; UINT32 ExceptionData;\r
+ push dword ptr [ebp + 2 * 4]\r
+\r
+;; Prepare parameter and call\r
+ mov edx, esp\r
+ push edx\r
+ mov eax, dword ptr [ebp + 1 * 4]\r
+ push eax\r
+ cmp eax, 32\r
+ jb CallException\r
+ call TimerHandler\r
+ jmp ExceptionDone\r
+CallException:\r
+ call ExceptionHandler\r
+ExceptionDone:\r
+ add esp, 8\r
+\r
+ cli\r
+;; UINT32 ExceptionData;\r
+ add esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ mov esi, esp\r
+ db 0fh, 0aeh, 00001110y ; fxrstor [esi]\r
+ add esp, 512\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop eax\r
+ mov dr0, eax\r
+ pop eax\r
+ mov dr1, eax\r
+ pop eax\r
+ mov dr2, eax\r
+ pop eax\r
+ mov dr3, eax\r
+;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add esp, 4\r
+ pop eax\r
+ mov dr7, eax\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ pop eax\r
+ mov cr0, eax\r
+ add esp, 4 ; not for Cr1\r
+ pop eax\r
+ mov cr2, eax\r
+ pop eax\r
+ mov cr3, eax\r
+ pop eax\r
+ mov cr4, eax\r
+\r
+;; UINT32 EFlags;\r
+ pop dword ptr [ebp + 5 * 4]\r
+\r
+;; UINT32 Ldtr, Tr;\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+ add esp, 24\r
+\r
+;; UINT32 Eip;\r
+ pop dword ptr [ebp + 3 * 4]\r
+\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger... We\r
+;; could attempt to insulate ourselves against this possibility,\r
+;; but that poses risks as well.\r
+;;\r
+ pop gs\r
+ pop fs\r
+ pop es\r
+ pop ds\r
+ pop dword ptr [ebp + 4 * 4]\r
+ pop ss\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ pop edi\r
+ pop esi\r
+ add esp, 4 ; not for ebp\r
+ add esp, 4 ; not for esp\r
+ pop ebx\r
+ pop edx\r
+ pop ecx\r
+ pop eax\r
+\r
+ mov esp, ebp\r
+ pop ebp\r
+ add esp, 8\r
+ iretd\r
+\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
+; bounds check (INT 5)\r
+BOUNDS_CHECK_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
+; invalid opcode (INT 6)\r
+INVALID_OPCODE_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
+; device not available (INT 7)\r
+DEV_NOT_AVAIL_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
+; double fault (INT 8)\r
+DOUBLE_FAULT_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
+; Coprocessor segment overrun - reserved (INT 9)\r
+RSVD_INTR_SEL1 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
+; invalid TSS (INT 0ah)\r
+INVALID_TSS_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
+; segment not present (INT 0bh)\r
+SEG_NOT_PRESENT_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
+; stack fault (INT 0ch)\r
+STACK_FAULT_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
+; general protection (INT 0dh)\r
+GP_FAULT_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
+; page fault (INT 0eh)\r
+PAGE_FAULT_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
+; Intel reserved - do not use (INT 0fh)\r
+RSVD_INTR_SEL2 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
+; floating point error (INT 10h)\r
+FLT_POINT_ERR_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
+; alignment check (INT 11h)\r
+ALIGNMENT_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; machine check (INT 12h)\r
+MACHINE_CHECK_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; SIMD floating-point exception (INT 13h)\r
+SIMD_EXCEPTION_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+REPEAT (32 - 20)\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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+ENDM\r
+\r
+; 72 unspecified descriptors\r
+ db (72 * 8) 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_CODE_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
+\r
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
+IRQ1_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\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_CODE_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
+\r
+; IRQ 3 (COM 2) - (INT 6bh)\r
+IRQ3_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 4 (COM 1) - (INT 6ch)\r
+IRQ4_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 5 (LPT 2) - (INT 6dh)\r
+IRQ5_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 6 (Floppy controller) - (INT 6eh)\r
+IRQ6_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 7 (LPT 1) - (INT 6fh)\r
+IRQ7_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 8 (RTC Alarm) - (INT 70h)\r
+IRQ8_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 9 - (INT 71h)\r
+IRQ9_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 10 - (INT 72h)\r
+IRQ10_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 11 - (INT 73h)\r
+IRQ11_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 12 (PS/2 mouse) - (INT 74h)\r
+IRQ12_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 13 (Floating point error) - (INT 75h)\r
+IRQ13_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 14 (Secondary IDE) - (INT 76h)\r
+IRQ14_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+; IRQ 15 (Primary IDE) - (INT 77h)\r
+IRQ15_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 ; (10001110)type = 386 interrupt gate, present\r
+ dw 0 ; offset 31:16\r
+\r
+ db (1 * 8) dup(0)\r
+\r
+IDT_END:\r
+\r
+END\r
--- /dev/null
+ TITLE CpuInterrupt.asm: \r
+;------------------------------------------------------------------------------\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
+;* CpuInterrupt.asm\r
+;* \r
+;* Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+EXTERNDEF mExceptionCodeSize:DWORD\r
+\r
+.code\r
+\r
+EXTERN TimerHandler: FAR\r
+EXTERN ExceptionHandler: NEAR\r
+EXTERN mTimerVector: QWORD\r
+\r
+mExceptionCodeSize DD 9\r
+\r
+InitDescriptor PROC\r
+ lea rax, [GDT_BASE] ; RAX=PHYSICAL address of gdt\r
+ mov qword ptr [gdtr + 2], rax ; Put address of gdt into the gdtr\r
+ lgdt fword ptr [gdtr]\r
+ mov rax, 18h\r
+ mov gs, rax\r
+ mov fs, rax\r
+ lea rax, [IDT_BASE] ; RAX=PHYSICAL address of idt\r
+ mov qword ptr [idtr + 2], rax ; Put address of idt into the idtr\r
+ lidt fword ptr [idtr]\r
+ ret\r
+InitDescriptor ENDP\r
+\r
+; VOID\r
+; InstallInterruptHandler (\r
+; UINTN Vector, // rcx\r
+; void (*Handler)(void) // rdx\r
+; )\r
+InstallInterruptHandler PROC \r
+ push rbx\r
+ pushfq ; save eflags\r
+ cli ; turn off interrupts\r
+ sub rsp, 10h ; open some space on the stack\r
+ mov rbx, rsp\r
+ sidt [rbx] ; get fword address of IDT\r
+ mov rbx, [rbx+2] ; move offset of IDT into RBX\r
+ add rsp, 10h ; correct stack\r
+ mov rax, rcx ; Get vector number\r
+ shl rax, 4 ; multiply by 16 to get offset\r
+ add rbx, rax ; add to IDT base to get entry\r
+ mov rax, rdx ; load new address into IDT entry\r
+ mov word ptr [rbx], ax ; write bits 15..0 of offset\r
+ shr rax, 16 ; use ax to copy 31..16 to descriptors\r
+ mov word ptr [rbx+6], ax ; write bits 31..16 of offset\r
+ shr rax, 16 ; use eax to copy 63..32 to descriptors\r
+ mov dword ptr [rbx+8], eax ; write bits 63..32 of offset\r
+ popfq ; restore flags (possible enabling interrupts)\r
+ pop rbx\r
+ ret\r
+\r
+InstallInterruptHandler ENDP\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
+ align 02h\r
+SystemExceptionHandler PROC\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 (32 - 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
+SystemExceptionHandler ENDP\r
+\r
+SystemTimerHandler PROC\r
+ push 0\r
+ push mTimerVector\r
+ JmpCommonIdtEntry\r
+SystemTimerHandler ENDP\r
+\r
+commonIdtEntry:\r
+; +---------------------+ <-- 16-byte aligned ensured by processor\r
+; + Old SS +\r
+; +---------------------+\r
+; + Old RSP +\r
+; +---------------------+\r
+; + RFlags +\r
+; +---------------------+\r
+; + CS +\r
+; +---------------------+\r
+; + RIP +\r
+; +---------------------+\r
+; + Error Code +\r
+; +---------------------+\r
+; + Vector Number +\r
+; +---------------------+\r
+; + RBP +\r
+; +---------------------+ <-- RBP, 16-byte aligned\r
+\r
+ cli\r
+ push rbp\r
+ mov rbp, rsp\r
+\r
+ ;\r
+ ; Since here the stack pointer is 16-byte aligned, so\r
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+ ; is 16-byte aligned\r
+ ; \r
+\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ push r15\r
+ push r14\r
+ push r13\r
+ push r12\r
+ push r11\r
+ push r10\r
+ push r9\r
+ push r8\r
+ push rax\r
+ push rcx\r
+ push rdx\r
+ push rbx\r
+ push qword ptr [rbp + 6 * 8] ; RSP\r
+ push qword ptr [rbp] ; RBP\r
+ push rsi\r
+ push rdi\r
+\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ movzx rax, word ptr [rbp + 7 * 8]\r
+ push rax ; for ss\r
+ movzx rax, word ptr [rbp + 4 * 8]\r
+ push rax ; for cs\r
+ mov rax, ds\r
+ push rax\r
+ mov rax, es\r
+ push rax\r
+ mov rax, fs\r
+ push rax\r
+ mov rax, gs\r
+ push rax\r
+\r
+;; UINT64 Rip;\r
+ push qword ptr [rbp + 3 * 8]\r
+\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+ sub rsp, 16\r
+ sidt fword ptr [rsp]\r
+ sub rsp, 16\r
+ sgdt fword ptr [rsp]\r
+\r
+;; UINT64 Ldtr, Tr;\r
+ xor rax, rax\r
+ str ax\r
+ push rax\r
+ sldt ax\r
+ push rax\r
+\r
+;; UINT64 RFlags;\r
+ push qword ptr [rbp + 5 * 8]\r
+\r
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ mov rax, cr8\r
+ push rax\r
+ mov rax, cr4\r
+ or rax, 208h\r
+ mov cr4, rax\r
+ push rax\r
+ mov rax, cr3\r
+ push rax\r
+ mov rax, cr2\r
+ push rax\r
+ xor rax, rax\r
+ push rax\r
+ mov rax, cr0\r
+ push rax\r
+\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov rax, dr7\r
+ push rax\r
+;; clear Dr7 while executing debugger itself\r
+ xor rax, rax\r
+ mov dr7, rax\r
+\r
+ mov rax, dr6\r
+ push rax\r
+;; insure all status bits in dr6 are clear...\r
+ xor rax, rax\r
+ mov dr6, rax\r
+\r
+ mov rax, dr3\r
+ push rax\r
+ mov rax, dr2\r
+ push rax\r
+ mov rax, dr1\r
+ push rax\r
+ mov rax, dr0\r
+ push rax\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ sub rsp, 512\r
+ mov rdi, rsp\r
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]\r
+\r
+;; UINT32 ExceptionData;\r
+ push qword ptr [rbp + 2 * 8]\r
+\r
+;; call into exception handler\r
+;; Prepare parameter and call\r
+ mov rcx, qword ptr [rbp + 1 * 8]\r
+ mov rdx, rsp\r
+ ;\r
+ ; Per X64 calling convention, allocate maximum parameter stack space\r
+ ; and make sure RSP is 16-byte aligned\r
+ ;\r
+ sub rsp, 4 * 8 + 8\r
+ cmp rcx, 32\r
+ jb CallException\r
+ call TimerHandler\r
+ jmp ExceptionDone\r
+CallException:\r
+ call ExceptionHandler\r
+ExceptionDone:\r
+ add rsp, 4 * 8 + 8\r
+\r
+ cli\r
+;; UINT64 ExceptionData;\r
+ add rsp, 8\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ mov rsi, rsp\r
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]\r
+ add rsp, 512\r
+\r
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop rax\r
+ mov dr0, rax\r
+ pop rax\r
+ mov dr1, rax\r
+ pop rax\r
+ mov dr2, rax\r
+ pop rax\r
+ mov dr3, rax\r
+;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add rsp, 8\r
+ pop rax\r
+ mov dr7, rax\r
+\r
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ pop rax\r
+ mov cr0, rax\r
+ add rsp, 8 ; not for Cr1\r
+ pop rax\r
+ mov cr2, rax\r
+ pop rax\r
+ mov cr3, rax\r
+ pop rax\r
+ mov cr4, rax\r
+ pop rax\r
+ mov cr8, rax\r
+\r
+;; UINT64 RFlags;\r
+ pop qword ptr [rbp + 5 * 8]\r
+\r
+;; UINT64 Ldtr, Tr;\r
+;; UINT64 Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+ add rsp, 48\r
+\r
+;; UINT64 Rip;\r
+ pop qword ptr [rbp + 3 * 8]\r
+\r
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+ pop rax\r
+ ; mov gs, rax ; not for gs\r
+ pop rax\r
+ ; mov fs, rax ; not for fs\r
+ ; (X64 will not use fs and gs, so we do not restore it)\r
+ pop rax\r
+ mov es, rax\r
+ pop rax\r
+ mov ds, rax\r
+ pop qword ptr [rbp + 4 * 8] ; for cs\r
+ pop qword ptr [rbp + 7 * 8] ; for ss\r
+\r
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pop rdi\r
+ pop rsi\r
+ add rsp, 8 ; not for rbp\r
+ pop qword ptr [rbp + 6 * 8] ; for rsp\r
+ pop rbx\r
+ pop rdx\r
+ pop rcx\r
+ pop rax\r
+ pop r8\r
+ pop r9\r
+ pop r10\r
+ pop r11\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+\r
+ mov rsp, rbp\r
+ pop rbp\r
+ add rsp, 16\r
+ iretq\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; data\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ align 010h\r
+\r
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit\r
+ dq 0 ; (GDT base gets set above)\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; global descriptor table (GDT)\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ align 010h\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
+REPEAT (32 - 20)\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
+ENDM\r
+\r
+; 72 unspecified descriptors\r
+ db (72 * 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
+ db (1 * 16) dup(0)\r
+\r
+IDT_END:\r
+\r
+ align 02h\r
+\r
+END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 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
+Module Name:\r
+ CpuIo.c\r
+\r
+Abstract:\r
+\r
+ This is the code that publishes the CPU I/O Protocol.\r
+ The intent herein is to have a single I/O service that can load\r
+ as early as possible, extend into runtime, and be layered upon by\r
+ the implementations of architectural protocols and the PCI Root\r
+ Bridge I/O Protocol.\r
+\r
+--*/\r
+\r
+#include "CpuIo.h"\r
+#include "CpuIoAccess.h"\r
+\r
+#define IA32_MAX_IO_ADDRESS 0xFFFF\r
+\r
+EFI_CPU_IO_PROTOCOL mCpuIo = {\r
+ {\r
+ CpuMemoryServiceRead,\r
+ CpuMemoryServiceWrite\r
+ },\r
+ {\r
+ CpuIoServiceRead,\r
+ CpuIoServiceWrite\r
+ }\r
+};\r
+\r
+STATIC\r
+EFI_STATUS\r
+CpuIoMemRW (\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN BOOLEAN DestinationStrideFlag,\r
+ OUT PTR Destination,\r
+ IN BOOLEAN SourceStrideFlag,\r
+ IN PTR Source\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Private service to perform memory mapped I/O read/write\r
+\r
+Arguments:\r
+\r
+ Width - Width of the memory mapped I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ DestinationStrideFlag - Boolean flag indicates if the destination is to be incremented\r
+ Destination - Destination of the memory mapped I/O operation\r
+ SourceStrideFlag - Boolean flag indicates if the source is to be incremented\r
+ Source - Source of the memory mapped I/O operation\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Successful operation\r
+ EFI_INVALID_PARAMETER - Width is invalid\r
+\r
+--*/\r
+{\r
+ UINTN Stride;\r
+ UINTN DestinationStride;\r
+ UINTN SourceStride;\r
+\r
+ Width = Width & 0x03;\r
+ Stride = (UINTN)1 << Width;\r
+ DestinationStride = DestinationStrideFlag ? Stride : 0;\r
+ SourceStride = SourceStrideFlag ? Stride : 0;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+ switch (Width) {\r
+ case EfiCpuIoWidthUint8:\r
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
+ MemoryFence();\r
+ *Destination.ui8 = *Source.ui8;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint16:\r
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
+ MemoryFence ();\r
+ *Destination.ui16 = *Source.ui16;\r
+ MemoryFence ();\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint32:\r
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
+ MemoryFence ();\r
+ *Destination.ui32 = *Source.ui32;\r
+ MemoryFence ();\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint64:\r
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {\r
+ MemoryFence ();\r
+ *Destination.ui64 = *Source.ui64;\r
+ MemoryFence ();\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceRead (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the memory mapped I/O read service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the memory mapped I/O operation\r
+ Address - Base address of the memory mapped I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the destination buffer to store the results\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was read.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+{\r
+ PTR Source;\r
+ PTR Destination;\r
+ EFI_STATUS Status;\r
+\r
+ Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Destination.buf = Buffer;\r
+ Source.buf = (VOID *) (UINTN) Address;\r
+\r
+ if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
+ return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceWrite (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the memory mapped I/O write service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the memory mapped I/O operation\r
+ Address - Base address of the memory mapped I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the source buffer from which to write data\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was written.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+{\r
+ PTR Source;\r
+ PTR Destination;\r
+ EFI_STATUS Status;\r
+\r
+ Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Destination.buf = (VOID *) (UINTN) Address;\r
+ Source.buf = Buffer;\r
+\r
+ if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {\r
+ return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceRead (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ OUT VOID *UserBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the port I/O read service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the port I/O operation\r
+ Address - Base address of the port I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the destination buffer to store the results\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was read.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+{\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+ UINTN Address;\r
+ PTR Buffer;\r
+ EFI_STATUS Status;\r
+\r
+ Buffer.buf = (UINT8 *) UserBuffer;\r
+\r
+ if (Width >= EfiCpuIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Address = (UINTN) UserAddress;\r
+ InStride = (UINTN)1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+\r
+ Width = Width & 0x03;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+ switch (Width) {\r
+ case EfiCpuIoWidthUint8:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ *Buffer.ui8 = CpuIoRead8 ((UINT16) Address);\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint16:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ *Buffer.ui16 = CpuIoRead16 ((UINT16) Address);\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint32:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ *Buffer.ui32 = CpuIoRead32 ((UINT16) Address);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceWrite (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN VOID *UserBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the port I/O write service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the port I/O operation\r
+ Address - Base address of the port I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the source buffer from which to write data\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was written.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+{\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+ UINTN Address;\r
+ PTR Buffer;\r
+ EFI_STATUS Status;\r
+\r
+ Buffer.buf = (UINT8 *) UserBuffer;\r
+\r
+ if (Width >= EfiCpuIoWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Address = (UINTN) UserAddress;\r
+ InStride = (UINTN)1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+\r
+ Width = Width & 0x03;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+ switch (Width) {\r
+ case EfiCpuIoWidthUint8:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ CpuIoWrite8 ((UINT16) Address, *Buffer.ui8);\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint16:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ CpuIoWrite16 ((UINT16) Address, *Buffer.ui16);\r
+ }\r
+ break;\r
+\r
+ case EfiCpuIoWidthUint32:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ CpuIoWrite32 ((UINT16) Address, *Buffer.ui32);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ CpuIo driver entry point.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The firmware allocated handle for the EFI image.\r
+ SystemTable - A pointer to the EFI System Table.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The driver was initialized.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = NULL;\r
+ Status = SystemTable->BootServices->InstallProtocolInterface (\r
+ &Handle,\r
+ &gEfiCpuIoProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mCpuIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CpuIoCheckParameter (\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer,\r
+ IN UINT64 Limit\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check the validation of parameters for CPU I/O interface functions.\r
+\r
+Arguments:\r
+\r
+ Width - Width of the Memory Access\r
+ Address - Address of the Memory access\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the buffer to read from memory\r
+ Buffer - Memory buffer for the I/O operation\r
+ Limit - Maximum address supported\r
+\r
+Returns:\r
+\r
+ EFI_INVALID_PARAMETER - Buffer is NULL\r
+ EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid\r
+ EFI_UNSUPPORTED - The memory buffer is not aligned\r
+ EFI_SUCCESS - Parameters are OK\r
+\r
+--*/\r
+{\r
+ UINTN AlignMask;\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Address > Limit) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // For FiFo type, the target address won't increase during the access,\r
+ // so treat count as 1\r
+ //\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ Count = 1;\r
+ }\r
+\r
+ Width = Width & 0x03;\r
+ if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ AlignMask = ((UINTN)1 << Width) - 1;\r
+ if ((UINTN) Buffer & AlignMask) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004, 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
+Module Name:\r
+ CpuIo.h\r
+\r
+Abstract:\r
+ *.h file for the driver\r
+\r
+ Note: the EFIAPI on the CpuIo functions is used to glue MASM (assembler) code\r
+ into C code. By making the MASM functions EFIAPI it ensures that a standard\r
+ C calling convention is assumed by the compiler, reguardless of the compiler\r
+ flags.\r
+\r
+\r
+--*/\r
+\r
+#ifndef _CPU_IO_H\r
+#define _CPU_IO_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/CpuIo.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#define VOLATILE volatile\r
+\r
+typedef union {\r
+ UINT8 VOLATILE *buf;\r
+ UINT8 VOLATILE *ui8;\r
+ UINT16 VOLATILE *ui16;\r
+ UINT32 VOLATILE *ui32;\r
+ UINT64 VOLATILE *ui64;\r
+ UINTN VOLATILE ui;\r
+} PTR;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ CpuIo driver entry point.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The firmware allocated handle for the EFI image.\r
+ SystemTable - A pointer to the EFI System Table.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The driver was initialized.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceRead (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the memory mapped I/O read service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the memory mapped I/O operation\r
+ Address - Base address of the memory mapped I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the destination buffer to store the results\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was read.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuMemoryServiceWrite (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the memory mapped I/O write service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the memory mapped I/O operation\r
+ Address - Base address of the memory mapped I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the source buffer from which to write data\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was written.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceRead (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ OUT VOID *UserBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the port I/O read service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the port I/O operation\r
+ Address - Base address of the port I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the destination buffer to store the results\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was read.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuIoServiceWrite (\r
+ IN EFI_CPU_IO_PROTOCOL *This,\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN VOID *UserBuffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the port I/O write service\r
+\r
+Arguments:\r
+\r
+ This - Pointer to an instance of the CPU I/O Protocol\r
+ Width - Width of the port I/O operation\r
+ Address - Base address of the port I/O operation\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the source buffer from which to write data\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The data was written.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_INVALID_PARAMETER - Buffer is NULL.\r
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.\r
+ EFI_UNSUPPORTED - The address range specified by Address, Width,\r
+ and Count is not valid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+CpuIoCheckParameter (\r
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN VOID *Buffer,\r
+ IN UINT64 Limit\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check the validation of parameters for CPU I/O interface functions.\r
+\r
+Arguments:\r
+\r
+ Width - Width of the Memory Access\r
+ Address - Address of the Memory access\r
+ Count - Count of the number of accesses to perform\r
+ Buffer - Pointer to the buffer to read from memory\r
+ Buffer - Memory buffer for the I/O operation\r
+ Limit - Maximum address supported\r
+\r
+Returns:\r
+\r
+ EFI_INVALID_PARAMETER - Buffer is NULL\r
+ EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid\r
+ EFI_UNSUPPORTED - The memory buffer is not aligned\r
+ EFI_SUCCESS - Parameters are OK\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2004, 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
+# Module Name:\r
+#\r
+# CpuIo.inf\r
+#\r
+# Abstract:\r
+#\r
+# Component description file for CpuIo module\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = CpuIo\r
+ FILE_GUID = BAE7599F-3C6B-43b7-BDF0-9CE07AA91AA6\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = CpuIoInitialize\r
+\r
+[Packages]\r
+ DuetPkg/DuetPkg.dec\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ DebugLib\r
+ UefiDriverEntryPoint\r
+ IoLib\r
+\r
+[Sources.common]\r
+ CpuIo.c\r
+ CpuIo.h\r
+ CpuIoAccess.h\r
+\r
+[Sources.IA32]\r
+ IA32\CpuIoAccess.asm\r
+\r
+[Sources.X64]\r
+ X64\CpuIoAccess.asm\r
+\r
+[Protocols]\r
+ gEfiCpuIoProtocolGuid
\ No newline at end of file
--- /dev/null
+/*++\r
+# \r
+# Copyright (c) 2004, 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
+\r
+Module Name:\r
+\r
+ CpuIoAccess.h\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#ifndef _CPU_IO_ACCESS_H\r
+#define _CPU_IO_ACCESS_H\r
+\r
+\r
+#define IA32API __cdecl\r
+\r
+UINT8\r
+IA32API\r
+CpuIoRead8 (\r
+ IN UINT16 Port\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O read port\r
+Arguments: \r
+ Port: - Port number to read \r
+Returns: \r
+ Return read 8 bit value \r
+--*/\r
+UINT16\r
+IA32API\r
+CpuIoRead16 (\r
+ IN UINT16 Port\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O read port\r
+Arguments: \r
+ Port: - Port number to read \r
+Returns: \r
+ Return read 16 bit value \r
+--*/\r
+UINT32\r
+IA32API\r
+CpuIoRead32 (\r
+ IN UINT16 Port\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O read port\r
+Arguments: \r
+ Port: - Port number to read \r
+Returns: \r
+ Return read 32 bit value \r
+--*/\r
+VOID\r
+IA32API\r
+CpuIoWrite8 (\r
+ IN UINT16 Port,\r
+ IN UINT32 Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+ Data - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O write 8 bit data to port\r
+Arguments: \r
+ Port: - Port number to read \r
+ Data: - Data to write to the Port \r
+Returns: \r
+ None \r
+--*/\r
+VOID\r
+IA32API\r
+CpuIoWrite16 (\r
+ IN UINT16 Port,\r
+ IN UINT32 Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+ Data - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O write 16 bit data to port\r
+Arguments: \r
+ Port: - Port number to read \r
+ Data: - Data to write to the Port \r
+Returns: \r
+ None \r
+--*/\r
+VOID\r
+IA32API\r
+CpuIoWrite32 (\r
+ IN UINT16 Port,\r
+ IN UINT32 Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Port - GC_TODO: add argument description\r
+ Data - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+/*++ \r
+Routine Description: \r
+ Cpu I/O write 32 bit data to port\r
+Arguments: \r
+ Port: - Port number to read \r
+ Data: - Data to write to the Port \r
+Returns: \r
+ None \r
+--*/\r
+#endif\r
--- /dev/null
+ title CpuIoAccess.asm\r
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2005, 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
+;* Module Name:\r
+;* CpuIoAccess.asm\r
+;* \r
+;* Abstract: \r
+;* Supports IA32 CPU IO operation\r
+;* \r
+;------------------------------------------------------------------------------\r
+;\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+ .686\r
+ .MODEL FLAT,C\r
+ .CODE\r
+\r
+\r
+UINT8 TYPEDEF BYTE\r
+UINT16 TYPEDEF WORD\r
+UINT32 TYPEDEF DWORD\r
+UINT64 TYPEDEF QWORD\r
+UINTN TYPEDEF UINT32\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT8\r
+; CpuIoRead8 (\r
+; IN UINT16 Port\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead8 PROC PUBLIC Port:UINT16\r
+ mov dx, Port\r
+ in al, dx\r
+ ret\r
+CpuIoRead8 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT16\r
+; CpuIoRead16 (\r
+; IN UINT16 Port\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead16 PROC PUBLIC Port:UINT16\r
+ mov dx, Port\r
+ in ax, dx\r
+ ret\r
+CpuIoRead16 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT32\r
+; CpuIoRead32 (\r
+; IN UINT16 Port\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead32 PROC PUBLIC Port:UINT16\r
+ mov dx, Port\r
+ in eax, dx\r
+ ret\r
+CpuIoRead32 ENDP\r
+\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite8 (\r
+; IN UINT16 Port,\r
+; IN UINT32 Data\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite8 PROC PUBLIC Port:UINT16, Data:UINT32\r
+ mov eax, Data\r
+ mov dx, Port\r
+ out dx, al\r
+ ret\r
+CpuIoWrite8 ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite16 (\r
+; IN UINT16 Port,\r
+; IN UINT32 Data\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite16 PROC PUBLIC Port:UINT16, Data:UINT32\r
+ mov eax, Data\r
+ mov dx, Port\r
+ out dx, ax\r
+ ret\r
+CpuIoWrite16 ENDP\r
+\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite32 (\r
+; IN UINT16 Port,\r
+; IN UINT32 Data\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite32 PROC PUBLIC Port:UINT16, Data:UINT32\r
+ mov eax, Data\r
+ mov dx, Port\r
+ out dx, eax\r
+ ret\r
+CpuIoWrite32 ENDP\r
+\r
+\r
+END
\ No newline at end of file
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004, 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
+Module Name:\r
+ Ia32CpuIo.dxs\r
+\r
+Abstract:\r
+\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+#include "EfiDepex.h"\r
+\r
+\r
+DEPENDENCY_START\r
+ TRUE \r
+DEPENDENCY_END\r
--- /dev/null
+ title CpuIoAccess.asm\r
+\r
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2005 - 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
+;* Module Name:\r
+;* CpuIoAccess.asm\r
+;* \r
+;* Abstract:\r
+;* Supports x64 CPU IO operation\r
+;*\r
+;------------------------------------------------------------------------------\r
+;\r
+; \r
+; \r
+; Abstract:\r
+; \r
+; \r
+;------------------------------------------------------------------------------\r
+\r
+.CODE\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT8\r
+; CpuIoRead8 (\r
+; UINT16 Port // rcx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead8 PROC PUBLIC\r
+ xor eax, eax\r
+ mov dx, cx\r
+ in al, dx\r
+ ret\r
+CpuIoRead8 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite8 (\r
+; UINT16 Port, // rcx\r
+; UINT32 Data // rdx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite8 PROC PUBLIC\r
+ mov eax, edx\r
+ mov dx, cx\r
+ out dx, al\r
+ ret\r
+CpuIoWrite8 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT16\r
+; CpuIoRead16 (\r
+; UINT16 Port // rcx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead16 PROC PUBLIC\r
+ xor eax, eax\r
+ mov dx, cx\r
+ in ax, dx\r
+ ret\r
+CpuIoRead16 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite16 (\r
+; UINT16 Port, // rcx\r
+; UINT32 Data // rdx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite16 PROC PUBLIC\r
+ mov eax, edx\r
+ mov dx, cx\r
+ out dx, ax\r
+ ret\r
+CpuIoWrite16 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; UINT32\r
+; CpuIoRead32 (\r
+; UINT16 Port // rcx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoRead32 PROC PUBLIC\r
+ mov dx, cx\r
+ in eax, dx\r
+ ret\r
+CpuIoRead32 ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; CpuIoWrite32 (\r
+; UINT16 Port, // rcx\r
+; UINT32 Data // rdx\r
+; )\r
+;------------------------------------------------------------------------------\r
+CpuIoWrite32 PROC PUBLIC\r
+ mov eax, edx\r
+ mov dx, cx\r
+ out dx, eax\r
+ ret\r
+CpuIoWrite32 ENDP\r
+\r
+END\r
\r
[Guids.common]\r
gEfiPciExpressBaseAddressGuid = {0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0 }}\r
- gEfiAcpiDescriptionGuid = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }}
\ No newline at end of file
+ gEfiAcpiDescriptionGuid = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }}\r
+ gEfiFlashMapHobGuid = { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 }}\r
+ \r
+[Protocols.common] \r
+ gEfiLegacyBiosThunkProtocolGuid = {0x4c51a7ba, 0x7195, 0x442d, {0x87, 0x92, 0xbe, 0xea, 0x6e, 0x2f, 0xf6, 0xec}}
\ No newline at end of file
SUPPORTED_ARCHITECTURES = IA32|X64\r
BUILD_TARGETS = DEBUG\r
SKUID_IDENTIFIER = DEFAULT\r
- #FLASH_DEFINITION = DuetPkg/DuetPkg.fdf\r
+ FLASH_DEFINITION = DuetPkg/DuetPkg.fdf\r
\r
[LibraryClasses.common]\r
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
HiiLib|MdePkg/Library/HiiLib/HiiLib.inf\r
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf\r
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+ BaseUefiTianoDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf\r
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf\r
+ PlatformBdsLib|DuetPkg/Library/DuetBdsLib/PlatformBds.inf\r
+ IfrSupportLib|MdePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
+ ExtendedIfrSupportLib|MdeModulePkg/Library/ExtendedIfrSupportLib/ExtendedIfrSupportLib.inf\r
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
+ GraphicsLib|MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf\r
+ ExtendedHiiLib|MdeModulePkg/Library/ExtendedHiiLib/ExtendedHiiLib.inf\r
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf\r
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf\r
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
+ OemHookStatusCodeLib|IntelFrameworkModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf\r
\r
[LibraryClasses.common.DXE_DRIVER]\r
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf\r
+ SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf\r
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
+ IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf\r
+ UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf\r
+\r
+[LibraryClasses.common.DXE_CORE]\r
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf\r
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf\r
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf\r
+\r
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]\r
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf\r
+ SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf\r
+ IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf\r
+ TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf\r
\r
-[Components.IA32]\r
+[LibraryClasses.common.UEFI_DRIVER]\r
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
+\r
+[LibraryClasses.common.UEFI_APPLICATION]\r
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf\r
+\r
+[Components.common]\r
DuetPkg/DxeIpl/DxeIpl.inf\r
+\r
+ MdeModulePkg/Core/Dxe/DxeMain.inf\r
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf\r
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf\r
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf\r
+ \r
+ DuetPkg/FSVariable/FSVariable.inf\r
+\r
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf\r
+ IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf\r
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf\r
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf\r
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+\r
+ IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf\r
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf\r
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf\r
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf\r
+\r
DuetPkg/DataHubGenDxe/DataHubGen.inf\r
+ DuetPkg/FvbRuntimeService/DUETFwh.inf\r
+ DuetPkg/EfiLdr/EfiLdr.inf\r
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf\r
+ DuetPkg/CpuIoDxe/CpuIo.inf\r
+ DuetPkg/CpuDxe/Cpu.inf\r
+ \r
+ IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf\r
+ DuetPkg/KbcResetDxe/Reset.inf\r
+ DuetPkg/LegacyMetronome/Metronome.inf\r
\r
-[Components.X64]\r
- DuetPkg/DxeIpl/DxeIpl.inf\r
- DuetPkg/DataHubGenDxe/DataHubGen.inf
\ No newline at end of file
+ DuetPkg/PcRtc/RealTimeClock.inf\r
+ DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf\r
+ IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf\r
+\r
+ # IDE Support\r
+ #IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf\r
+ \r
+ # Usb Support\r
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf\r
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf\r
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf\r
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf\r
+ MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf\r
+ \r
+ # ISA Support\r
+ DuetPkg/IsaAcpiDxe/IsaAcpi.inf\r
+ DuetPkg/BootSector/BootSector.inf\r
--- /dev/null
+# This is NT32 FDF file with UEFI HII features enabled\r
+#\r
+# Copyright (c) 2007, Intel Corporation\r
+#\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
+\r
+################################################################################\r
+#\r
+# FD Section\r
+# The [FD] Section is made up of the definition statements and a\r
+# description of what goes into the Flash Device Image. Each FD section\r
+# defines one flash "device" image. A flash device image may be one of\r
+# the following: Removable media bootable image (like a boot floppy\r
+# image,) an Option ROM image (that would be "flashed" into an add-in\r
+# card,) a System "Flash" image (that would be burned into a system's\r
+# flash) or an Update ("Capsule") image that will be used to update and\r
+# existing system flash.\r
+#\r
+################################################################################\r
+[FD.DuetMainFd]\r
+BaseAddress = 0x0 #The base address of the FLASH Device.\r
+Size = 0x002a0000 #The size in bytes of the FLASH Device\r
+ErasePolarity = 1\r
+BlockSize = 0x10000\r
+NumBlocks = 0x2a\r
+\r
+0x00000000|0x002a0000\r
+\r
+################################################################################\r
+#\r
+# FV Section\r
+#\r
+# [FV] section is used to define what components or modules are placed within a flash\r
+# device file. This section also defines order the components and modules are positioned\r
+# within the image. The [FV] section consists of define statements, set statements and\r
+# module statements.\r
+#\r
+################################################################################\r
+[FV.DuetEfiMainFv]\r
+FvAlignment = 16 #FV alignment and FV attributes setting.\r
+ERASE_POLARITY = 1\r
+MEMORY_MAPPED = TRUE\r
+STICKY_WRITE = TRUE\r
+LOCK_CAP = TRUE\r
+LOCK_STATUS = TRUE\r
+WRITE_DISABLED_CAP = TRUE\r
+WRITE_ENABLED_CAP = TRUE\r
+WRITE_STATUS = TRUE\r
+WRITE_LOCK_CAP = TRUE\r
+WRITE_LOCK_STATUS = TRUE\r
+READ_DISABLED_CAP = TRUE\r
+READ_ENABLED_CAP = TRUE\r
+READ_STATUS = TRUE\r
+READ_LOCK_CAP = TRUE\r
+READ_LOCK_STATUS = TRUE\r
+\r
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf\r
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf\r
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf\r
+ \r
+INF DuetPkg/FSVariable/FSVariable.inf\r
+\r
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf\r
+INF IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf\r
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf\r
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf\r
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+\r
+INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf\r
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf\r
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf\r
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf\r
+\r
+INF DuetPkg/DataHubGenDxe/DataHubGen.inf\r
+INF DuetPkg/FvbRuntimeService/DUETFwh.inf\r
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf\r
+INF DuetPkg/CpuIoDxe/CpuIo.inf\r
+INF DuetPkg/CpuDxe/Cpu.inf\r
+ \r
+INF IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf\r
+INF DuetPkg/KbcResetDxe/Reset.inf\r
+INF DuetPkg/LegacyMetronome/Metronome.inf\r
+\r
+INF DuetPkg/PcRtc/RealTimeClock.inf\r
+INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf\r
+INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf\r
+\r
+ # IDE Support\r
+ #IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf\r
+ \r
+ # Usb Support\r
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf\r
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf\r
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf\r
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf\r
+INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf\r
+ \r
+ # ISA Support\r
+INF DuetPkg/IsaAcpiDxe/IsaAcpi.inf\r
+\r
+[Rule.Common.PEI_CORE]\r
+ FILE PEI_CORE = $(NAMED_GUID) {\r
+ PE32 PE32 |.efi\r
+ UI STRING ="$(MODULE_NAME)" Optional \r
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) \r
+ }\r
+\r
+[Rule.Common.PEIM]\r
+ FILE PEIM = $(NAMED_GUID) {\r
+ PEI_DEPEX PEI_DEPEX Optional |.depex\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional \r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) \r
+ }\r
+\r
+[Rule.Common.PEIM.TIANOCOMPRESSED]\r
+ FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {\r
+ PEI_DEPEX PEI_DEPEX Optional |.depex\r
+ GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+\r
+[Rule.Common.DXE_CORE]\r
+ FILE DXE_CORE = $(NAMED_GUID) {\r
+ COMPRESS PI_STD {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+\r
+[Rule.Common.UEFI_DRIVER]\r
+ FILE DRIVER = $(NAMED_GUID) {\r
+ DXE_DEPEX DXE_DEPEX Optional |.depex\r
+ COMPRESS PI_STD {\r
+ GUIDED {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+ }\r
+\r
+[Rule.Common.DXE_DRIVER]\r
+ FILE DRIVER = $(NAMED_GUID) {\r
+ DXE_DEPEX DXE_DEPEX Optional |.depex\r
+ COMPRESS PI_STD {\r
+ GUIDED {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+ }\r
+\r
+[Rule.Common.DXE_RUNTIME_DRIVER]\r
+ FILE DRIVER = $(NAMED_GUID) {\r
+ DXE_DEPEX DXE_DEPEX Optional |.depex\r
+ COMPRESS PI_STD {\r
+ GUIDED {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+ }\r
+\r
+[Rule.Common.UEFI_APPLICATION]\r
+ FILE APPLICATION = $(NAMED_GUID) {\r
+ COMPRESS PI_STD {\r
+ GUIDED {\r
+ PE32 PE32 |.efi\r
+ UI STRING="$(MODULE_NAME)" Optional\r
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
+ }\r
+ }\r
+ }\r
INF_VERSION = 0x00010005\r
BASE_NAME = DxeIpl\r
FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC\r
- MODULE_TYPE = USER_DEFINED\r
+ MODULE_TYPE = DXE_DRIVER\r
VERSION_STRING = 1.0\r
EDK_RELEASE_VERSION = 0x00020000\r
EFI_SPECIFICATION_VERSION = 0x00020000\r
BaseMemoryLib\r
PrintLib\r
ReportStatusCodeLib\r
+ UefiDriverEntryPoint\r
\r
[Sources.common]\r
DxeIpl.h\r
Ia32\Paging.c\r
Ia32\VirtualMemory.h\r
\r
-[BuildOptions.common]\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
+ #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
#ifndef _EFI_FLASHMAP_H_\r
#define _EFI_FLASHMAP_H_\r
\r
-\r
//\r
// Definition for flash map GUIDed HOBs\r
//\r
// An individual sub-area Entry.\r
// A single flash area may consist of more than one sub-area.\r
//\r
+/**\r
typedef struct {\r
EFI_FLASH_AREA_ATTRIBUTES Attributes;\r
UINT32 Reserved;\r
UINT8 Reserved[3];\r
EFI_GUID AreaTypeGuid;\r
} EFI_FLASH_AREA_DATA;\r
+**/\r
+\r
+typedef struct {\r
+ EFI_FLASH_AREA_ATTRIBUTES Attributes;\r
+ UINT32 Reserved;\r
+ EFI_PHYSICAL_ADDRESS Base;\r
+ EFI_PHYSICAL_ADDRESS Length;\r
+ EFI_GUID FileSystem;\r
+} EFI_FLASH_SUBAREA_ENTRY;\r
+\r
+typedef struct {\r
+ UINT8 Reserved[3];\r
+ EFI_FLASH_AREA_TYPE AreaType;\r
+ EFI_GUID AreaTypeGuid;\r
+ UINT32 NumberOfEntries;\r
+ EFI_FLASH_SUBAREA_ENTRY Entries[1];\r
+ //\r
+ // Extended Hob data.\r
+ //\r
+ // VolumeId and FilePath indicating a unique file.\r
+ //\r
+ UINT32 VolumeId;\r
+ CHAR16 FilePath[256];\r
+ UINT32 ActuralSize;\r
+ UINT32 Offset;\r
+} EFI_FLASH_MAP_FS_ENTRY_DATA;\r
\r
#pragma pack()\r
\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+\r
+Module Name:\r
+\r
+ ComponentName.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "PcatIsaAcpi.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+\r
+EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PcatIsaAcpiComponentNameGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PcatIsaAcpiComponentNameGetControllerName,\r
+ "en"\r
+};\r
+\r
+EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName = {\r
+ PcatIsaAcpiComponentNameGetDriverName,\r
+ PcatIsaAcpiComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+\r
+static EFI_UNICODE_STRING_TABLE mPcatIsaAcpiDriverNameTable[] = {\r
+ {\r
+ "eng;en",\r
+ L"PC-AT ISA Device Enumeration Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ Language - A pointer to a three character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller \r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a \r
+ driver is up to the driver writer.\r
+ DriverName - A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language \r
+ specified by Language.\r
+\r
+ Returns:\r
+ EFI_SUCCES - The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned \r
+ in DriverName.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - DriverName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the \r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return LookupUnicodeString2 (\r
+ Language,\r
+ This->SupportedLanguages,\r
+ mPcatIsaAcpiDriverNameTable, \r
+ DriverName,\r
+ (BOOLEAN)(This == &gPcatIsaAcpiComponentName)\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by an EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ ControllerHandle - The handle of a controller that the driver specified by \r
+ This is managing. This handle specifies the controller \r
+ whose name is to be returned.\r
+ ChildHandle - The handle of the child controller to retrieve the name \r
+ of. This is an optional parameter that may be NULL. It \r
+ will be NULL for device drivers. It will also be NULL \r
+ for a bus drivers that wish to retrieve the name of the \r
+ bus controller. It will not be NULL for a bus driver \r
+ that wishes to retrieve the name of a child controller.\r
+ Language - A pointer to a three character ISO 639-2 language \r
+ identifier. This is the language of the controller name \r
+ that that the caller is requesting, and it must match one\r
+ of the languages specified in SupportedLanguages. The \r
+ number of languages supported by a driver is up to the \r
+ driver writer.\r
+ ControllerName - A pointer to the Unicode string to return. This Unicode\r
+ string is the name of the controller specified by \r
+ ControllerHandle and ChildHandle in the language specified\r
+ by Language from the point of view of the driver specified\r
+ by This. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Unicode string for the user readable name in the \r
+ language specified by Language for the driver \r
+ specified by This was returned in DriverName.\r
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing \r
+ the controller specified by ControllerHandle and \r
+ ChildHandle.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the \r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+\r
+Module Name:\r
+\r
+ IsaAcpi.c\r
+ \r
+Abstract: \r
+ \r
+ ISA ACPI Protocol Implementation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatIsaAcpi.h"\r
+\r
+//\r
+// Platform specific data for the ISA devices that are present.in the platform\r
+//\r
+\r
+//\r
+// COM 1 UART Controller\r
+//\r
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom1DeviceResources[] = {\r
+ {EfiIsaAcpiResourceIo, 0, 0x3f8, 0x3ff},\r
+ {EfiIsaAcpiResourceInterrupt, 0, 4, 0},\r
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}\r
+};\r
+\r
+//\r
+// COM 2 UART Controller\r
+//\r
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom2DeviceResources[] = {\r
+ {EfiIsaAcpiResourceIo, 0, 0x2f8, 0x2ff},\r
+ {EfiIsaAcpiResourceInterrupt, 0, 3, 0},\r
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}\r
+};\r
+\r
+//\r
+// PS/2 Keyboard Controller\r
+//\r
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2KeyboardDeviceResources[] = {\r
+ {EfiIsaAcpiResourceIo, 0, 0x60, 0x64},\r
+ {EfiIsaAcpiResourceInterrupt, 0, 1, 0},\r
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}\r
+};\r
+\r
+//\r
+// PS/2 Mouse Controller\r
+//\r
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2MouseDeviceResources[] = {\r
+ {EfiIsaAcpiResourceIo, 0, 0x60, 0x64},\r
+ {EfiIsaAcpiResourceInterrupt, 0, 12, 0},\r
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}\r
+};\r
+\r
+//\r
+// Floppy Disk Controller\r
+//\r
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiFloppyResources[] = {\r
+ {EfiIsaAcpiResourceIo, 0, 0x3f0, 0x3f7},\r
+ {EfiIsaAcpiResourceInterrupt, 0, 6, 0},\r
+ {EfiIsaAcpiResourceDma, EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE | EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 | EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE, 2, 0},\r
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}\r
+};\r
+\r
+//\r
+// Table of ISA Controllers\r
+//\r
+EFI_ISA_ACPI_RESOURCE_LIST gPcatIsaAcpiDeviceList[] = {\r
+ {{EISA_PNP_ID(0x501), 0}, mPcatIsaAcpiCom1DeviceResources }, // COM 1 UART Controller\r
+ {{EISA_PNP_ID(0x501), 1}, mPcatIsaAcpiCom2DeviceResources }, // COM 2 UART Controller\r
+ {{EISA_PNP_ID(0x303), 0}, mPcatIsaAcpiPs2KeyboardDeviceResources }, // PS/2 Keyboard Controller\r
+ {{EISA_PNP_ID(0x303), 1}, mPcatIsaAcpiPs2MouseDeviceResources }, // PS/2 Mouse Controller\r
+ {{EISA_PNP_ID(0x604), 0}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller A:\r
+ {{EISA_PNP_ID(0x604), 1}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller B:\r
+ {{0, 0}, NULL } // End if ISA Controllers\r
+};\r
+\r
+//\r
+// ISA ACPI Protocol Functions\r
+//\r
+VOID\r
+IsaDeviceLookup (\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **IsaAcpiDevice,\r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **NextIsaAcpiDevice\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Enumerate the ISA devices on the ISA bus\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ *IsaAcpiDevice = NULL;\r
+ if (NextIsaAcpiDevice != NULL) {\r
+ *NextIsaAcpiDevice = NULL;\r
+ }\r
+ if (Device == NULL) {\r
+ Index = 0;\r
+ } else {\r
+ for(Index = 0; gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL; Index++) {\r
+ if (Device->HID == gPcatIsaAcpiDeviceList[Index].Device.HID && \r
+ Device->UID == gPcatIsaAcpiDeviceList[Index].Device.UID ) {\r
+ break;\r
+ }\r
+ }\r
+ if (gPcatIsaAcpiDeviceList[Index].ResourceItem == NULL) {\r
+ return;\r
+ }\r
+ *IsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);\r
+ Index++;\r
+ }\r
+ if (gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL && NextIsaAcpiDevice != NULL) {\r
+ *NextIsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaDeviceEnumerate (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ OUT EFI_ISA_ACPI_DEVICE_ID **Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Enumerate the ISA devices on the ISA bus\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_ISA_ACPI_RESOURCE_LIST *IsaAcpiDevice;\r
+ EFI_ISA_ACPI_RESOURCE_LIST *NextIsaAcpiDevice;\r
+\r
+ IsaDeviceLookup (*Device, &IsaAcpiDevice, &NextIsaAcpiDevice);\r
+ if (NextIsaAcpiDevice == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ *Device = &(NextIsaAcpiDevice->Device);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaDeviceSetPower (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ IN BOOLEAN OnOff\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Set ISA device power \r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+} \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaGetCurrentResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device, \r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get current Resource of the specific ISA device\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ IsaDeviceLookup (Device, ResourceList, NULL);\r
+ if (*ResourceList == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaGetPossibleResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device, \r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/ \r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaSetResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device, \r
+ IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaEnableDevice (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ IN BOOLEAN Enable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS; \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaInitDevice (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaInterfaceInit (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This\r
+) \r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+} \r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2005, 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
+# Module Name:\r
+# IsaAcpi.inf\r
+#\r
+# Abstract:\r
+# Component description file for PCAT ISA ACPI driver\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = IsaAcpi\r
+ FILE_GUID = 38A0EC22-FBE7-4911-8BC1-176E0D6C1DBD\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+ ENTRY_POINT = PcatIsaAcpiDriverEntryPoint\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+ DuetPkg/DuetPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
+ \r
+[Sources]\r
+ PcatIsaAcpi.h\r
+ PcatIsaAcpi.c\r
+ IsaAcpi.c\r
+ ComponentName.c\r
+\r
+[Protocols]\r
+ gEfiPciIoProtocolGuid\r
+ gEfiIsaAcpiProtocolGuid\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+\r
+Module Name:\r
+\r
+ PcatIsaAcpi.c\r
+ \r
+Abstract:\r
+\r
+ EFI PCAT ISA ACPI Driver for a Generic PC Platform\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatIsaAcpi.h"\r
+\r
+//\r
+// PcatIsaAcpi Driver Binding Protocol\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding = {\r
+ PcatIsaAcpiDriverBindingSupported,\r
+ PcatIsaAcpiDriverBindingStart,\r
+ PcatIsaAcpiDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+ the entry point of the PcatIsaAcpi driver\r
+ \r
+ Arguments:\r
+ \r
+ Returns:\r
+ \r
+--*/ \r
+{\r
+ return EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle, \r
+ SystemTable, \r
+ &gPcatIsaAcpiDriverBinding,\r
+ ImageHandle,\r
+ &gPcatIsaAcpiComponentName,\r
+ &gPcatIsaAcpiComponentName2\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ ControllerDriver Protocol Method\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // Get PciIo protocol instance\r
+ // \r
+ Status = gBS->OpenProtocol (\r
+ Controller, \r
+ &gEfiPciIoProtocolGuid, \r
+ &PciIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof(Pci) / sizeof(UINT32), \r
+ &Pci);\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ if ((Pci.Hdr.Command & 0x03) == 0x03) {\r
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {\r
+ //\r
+ // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code\r
+ //\r
+ if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA) {\r
+ Status = EFI_SUCCESS;\r
+ } \r
+\r
+ //\r
+ // See if this is an Intel PCI to ISA bridge in Positive Decode Mode\r
+ //\r
+ if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA_POSITIVE_DECODE &&\r
+ Pci.Hdr.VendorId == 0x8086 && \r
+ Pci.Hdr.DeviceId == 0x7110) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ } \r
+ }\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller, \r
+ &gEfiPciIoProtocolGuid, \r
+ This->DriverBindingHandle, \r
+ Controller \r
+ );\r
+ \r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Install EFI_ISA_ACPI_PROTOCOL\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;\r
+ \r
+ PcatIsaAcpiDev = NULL;\r
+ //\r
+ // Open the PCI I/O Protocol Interface\r
+ //\r
+ PciIo = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ Controller, \r
+ &gEfiPciIoProtocolGuid, \r
+ &PciIo,\r
+ This->DriverBindingHandle, \r
+ Controller, \r
+ EFI_OPEN_PROTOCOL_BY_DRIVER \r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo, \r
+ EfiPciIoAttributeOperationEnable, \r
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO, \r
+ NULL \r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Allocate memory for the PCAT ISA ACPI Device structure\r
+ //\r
+ PcatIsaAcpiDev = NULL;\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData,\r
+ sizeof(PCAT_ISA_ACPI_DEV),\r
+ &PcatIsaAcpiDev\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Initialize the PCAT ISA ACPI Device structure\r
+ //\r
+ PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE;\r
+ PcatIsaAcpiDev->Handle = Controller;\r
+ PcatIsaAcpiDev->PciIo = PciIo;\r
+ \r
+ //\r
+ // IsaAcpi interface\r
+ //\r
+ (PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate = IsaDeviceEnumerate;\r
+ (PcatIsaAcpiDev->IsaAcpi).SetPower = IsaDeviceSetPower;\r
+ (PcatIsaAcpiDev->IsaAcpi).GetCurResource = IsaGetCurrentResource;\r
+ (PcatIsaAcpiDev->IsaAcpi).GetPosResource = IsaGetPossibleResource;\r
+ (PcatIsaAcpiDev->IsaAcpi).SetResource = IsaSetResource;\r
+ (PcatIsaAcpiDev->IsaAcpi).EnableDevice = IsaEnableDevice;\r
+ (PcatIsaAcpiDev->IsaAcpi).InitDevice = IsaInitDevice;\r
+ (PcatIsaAcpiDev->IsaAcpi).InterfaceInit = IsaInterfaceInit;\r
+ \r
+ //\r
+ // Install the ISA ACPI Protocol interface\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi,\r
+ NULL\r
+ );\r
+\r
+Done:\r
+ if (EFI_ERROR (Status)) {\r
+ if (PciIo) {\r
+ PciIo->Attributes (\r
+ PciIo, \r
+ EfiPciIoAttributeOperationDisable, \r
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,\r
+ NULL \r
+ );\r
+ }\r
+ gBS->CloseProtocol (\r
+ Controller, \r
+ &gEfiPciIoProtocolGuid, \r
+ This->DriverBindingHandle, \r
+ Controller\r
+ );\r
+ if (PcatIsaAcpiDev != NULL) {\r
+ gBS->FreePool (PcatIsaAcpiDev);\r
+ }\r
+ return Status;\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Arguments:\r
+\r
+ Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ISA_ACPI_PROTOCOL *IsaAcpi;\r
+ PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;\r
+ \r
+ //\r
+ // Get the ISA ACPI Protocol Interface\r
+ // \r
+ Status = gBS->OpenProtocol (\r
+ Controller, \r
+ &gEfiIsaAcpiProtocolGuid, \r
+ &IsaAcpi,\r
+ This->DriverBindingHandle, \r
+ Controller, \r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the PCAT ISA ACPI Device structure from the ISA ACPI Protocol\r
+ //\r
+ PcatIsaAcpiDev = PCAT_ISA_ACPI_DEV_FROM_THIS (IsaAcpi);\r
+\r
+ PcatIsaAcpiDev->PciIo->Attributes (\r
+ PcatIsaAcpiDev->PciIo, \r
+ EfiPciIoAttributeOperationDisable, \r
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,\r
+ NULL \r
+ );\r
+ \r
+ //\r
+ // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL\r
+ //\r
+ Status = gBS->UninstallProtocolInterface (\r
+ Controller,\r
+ &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller, \r
+ &gEfiPciIoProtocolGuid, \r
+ This->DriverBindingHandle, \r
+ Controller\r
+ );\r
+ \r
+ gBS->FreePool (PcatIsaAcpiDev);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+\r
+Module Name:\r
+\r
+ PcatIsaAcpi.h\r
+ \r
+Abstract:\r
+\r
+ EFI PCAT ISA ACPI Driver for a Generic PC Platform\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _PCAT_ISA_ACPI_H_\r
+#define _PCAT_ISA_ACPI_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/IsaIo.h>\r
+#include <Protocol/DriverBinding.h>\r
+#include <Protocol/ComponentName.h>\r
+#include <Protocol/ComponentName2.h>\r
+\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/IsaAcpi.h>\r
+//\r
+// PCAT ISA ACPI device private data structure\r
+//\r
+#define PCAT_ISA_ACPI_DEV_SIGNATURE EFI_SIGNATURE_32('L','P','C','D')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle; \r
+ EFI_ISA_ACPI_PROTOCOL IsaAcpi;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+} PCAT_ISA_ACPI_DEV;\r
+\r
+#define PCAT_ISA_ACPI_DEV_FROM_THIS(a) _CR(a, PCAT_ISA_ACPI_DEV, IsaAcpi)\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding;\r
+\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2;\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName;\r
+\r
+\r
+//\r
+// Prototypes for Driver model protocol interface\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatIsaAcpiDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ );\r
+\r
+//\r
+// Prototypes for the ISA ACPI protocol interface\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+IsaDeviceEnumerate (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ OUT EFI_ISA_ACPI_DEVICE_ID **Device\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaDeviceSetPower (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ IN BOOLEAN OnOff\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaGetCurrentResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaGetPossibleResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device, \r
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaSetResource (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaEnableDevice (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,\r
+ IN BOOLEAN Enable\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IsaInitDevice (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This,\r
+ IN EFI_ISA_ACPI_DEVICE_ID *Device\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+IsaInterfaceInit (\r
+ IN EFI_ISA_ACPI_PROTOCOL *This\r
+ ); \r
+\r
+#endif\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ Ia32Reset.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "Reset.h"\r
+\r
+//\r
+// The handle onto which the Reset Architectural Protocol is installed\r
+//\r
+EFI_HANDLE mResetHandle = NULL;\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeReset (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize the state information for the Reset Architectural Protocol\r
+\r
+Arguments:\r
+\r
+ ImageHandle of the loaded driver\r
+ Pointer to the System Table\r
+\r
+Returns:\r
+\r
+ Status\r
+\r
+ EFI_SUCCESS - thread can be successfully created\r
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
+ EFI_DEVICE_ERROR - cannot create the timer service\r
+\r
+--*/\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Make sure the Reset Architectural Protocol is not already installed in the system\r
+ //\r
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);\r
+\r
+ //\r
+ // Hook the runtime service table\r
+ //\r
+ SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;\r
+\r
+ //\r
+ // Now install the Reset RT AP on a new handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mResetHandle,\r
+ &gEfiResetArchProtocolGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ Ia32Reset.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_PROTOCOL_DEFINITION (CpuIO)\r
+\r
+DEPENDENCY_START\r
+ EFI_CPU_IO_PROTOCOL_GUID\r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ IpfReset.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "Cf9Reset.h"\r
+\r
+SAL_RETURN_REGS\r
+ResetEsalServicesClassCommonEntry (\r
+ IN UINT64 FunctionId,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN UINT64 Arg4,\r
+ IN UINT64 Arg5,\r
+ IN UINT64 Arg6,\r
+ IN UINT64 Arg7,\r
+ IN UINT64 Arg8,\r
+ IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,\r
+ IN BOOLEAN VirtualMode,\r
+ IN VOID *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Main entry for Extended SAL Reset Services\r
+\r
+Arguments:\r
+\r
+ FunctionId Function Id which needed to be called.\r
+ Arg2 EFI_RESET_TYPE, whether WARM of COLD reset\r
+ Arg3 Last EFI_STATUS \r
+ Arg4 Data Size of UNICODE STRING passed in ARG5\r
+ Arg5 Unicode String which CHAR16*\r
+\r
+Returns:\r
+\r
+ SAL_RETURN_REGS\r
+\r
+--*/\r
+// TODO: Arg6 - add argument and description to function comment\r
+// TODO: Arg7 - add argument and description to function comment\r
+// TODO: Arg8 - add argument and description to function comment\r
+// TODO: ExtendedSalProc - add argument and description to function comment\r
+// TODO: VirtualMode - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+{\r
+ SAL_RETURN_REGS ReturnVal;\r
+\r
+ switch (FunctionId) {\r
+ case ResetSystem:\r
+ KbcResetSystem (Arg2, Arg3, (UINTN) Arg4, (VOID *) Arg5);\r
+ ReturnVal.Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ default:\r
+ ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT;\r
+ break;\r
+ }\r
+\r
+ return ReturnVal;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeReset (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize the state information for the Reset Architectural Protocol\r
+\r
+Arguments:\r
+\r
+ ImageHandle of the loaded driver\r
+ Pointer to the System Table\r
+\r
+Returns:\r
+\r
+ Status\r
+\r
+ EFI_SUCCESS - thread can be successfully created\r
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
+ EFI_DEVICE_ERROR - cannot create the timer service\r
+\r
+--*/\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);\r
+\r
+ RegisterEsalClass (\r
+ &gEfiExtendedSalResetServicesProtocolGuid,\r
+ NULL,\r
+ ResetEsalServicesClassCommonEntry,\r
+ ResetSystem,\r
+ NULL\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ IpfReset.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)\r
+\r
+DEPENDENCY_START\r
+ EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID\r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ Reset.c\r
+\r
+Abstract:\r
+\r
+ Reset Architectural Protocol implementation\r
+\r
+--*/\r
+\r
+#include "Reset.h"\r
+\r
+VOID\r
+EFIAPI\r
+KbcResetSystem (\r
+ IN EFI_RESET_TYPE ResetType,\r
+ IN EFI_STATUS ResetStatus,\r
+ IN UINTN DataSize,\r
+ IN CHAR16 *ResetData OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Reset the system.\r
+\r
+Arguments:\r
+ \r
+ ResetType - warm or cold\r
+ ResetStatus - possible cause of reset\r
+ DataSize - Size of ResetData in bytes\r
+ ResetData - Optional Unicode string\r
+ For details, see efiapi.h\r
+\r
+Returns:\r
+ Does not return if the reset takes place.\r
+ EFI_INVALID_PARAMETER If ResetType is invalid.\r
+\r
+--*/\r
+{\r
+ UINT8 Data;\r
+\r
+ switch (ResetType) {\r
+ case EfiResetWarm:\r
+ case EfiResetCold:\r
+ case EfiResetShutdown:\r
+ Data = 0xfe;\r
+ IoWrite8 (0x64, Data);\r
+ break;\r
+\r
+ default:\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // Given we should have reset getting here would be bad\r
+ //\r
+ ASSERT (FALSE);\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ Reset.h\r
+\r
+Abstract:\r
+\r
+ some definitions for reset\r
+\r
+--*/\r
+\r
+#ifndef _KBC_RESET_H\r
+#define _KBC_RESET_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/Reset.h>\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeReset (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ ImageHandle - TODO: add argument description\r
+ SystemTable - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+KbcResetSystem (\r
+ IN EFI_RESET_TYPE ResetType,\r
+ IN EFI_STATUS ResetStatus,\r
+ IN UINTN DataSize,\r
+ IN CHAR16 *ResetData OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ ResetType - TODO: add argument description\r
+ ResetStatus - TODO: add argument description\r
+ DataSize - TODO: add argument description\r
+ ResetData - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 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
+# Module Name:\r
+# Reset.inf\r
+#\r
+# Abstract:\r
+#\r
+#--*/\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = KbcReset\r
+ FILE_GUID = 6F0198AA-1F1D-426D-AE3E-39AB633FCC28\r
+ MODULE_TYPE = DXE_RUNTIME_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializeReset\r
+\r
+[Packages]\r
+ DuetPkg/DuetPkg.dec\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+[LibraryClasses]\r
+ DebugLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ IoLib\r
+\r
+[Sources.common]\r
+ Reset.c\r
+ Reset.h\r
+\r
+[Sources.ipf]\r
+ Ipf\IpfReset.c\r
+\r
+[Sources.ia32]\r
+ Ia32\Ia32Reset.c\r
+\r
+[Sources.x64]\r
+ x64\x64Reset.c\r
+\r
+[Protocols]\r
+ gEfiResetArchProtocolGuid\r
+\r
+[Depex]\r
+ gEfiCpuIoProtocolGuid\r
+\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ x64Reset.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "Reset.h"\r
+\r
+//\r
+// The handle onto which the Reset Architectural Protocol is installed\r
+//\r
+EFI_HANDLE mResetHandle = NULL;\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeReset (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize the state information for the Reset Architectural Protocol\r
+\r
+Arguments:\r
+\r
+ ImageHandle of the loaded driver\r
+ Pointer to the System Table\r
+\r
+Returns:\r
+\r
+ Status\r
+\r
+ EFI_SUCCESS - thread can be successfully created\r
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
+ EFI_DEVICE_ERROR - cannot create the timer service\r
+\r
+--*/\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Make sure the Reset Architectural Protocol is not already installed in the system\r
+ //\r
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);\r
+\r
+ //\r
+ // Hook the runtime service table\r
+ //\r
+ SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;\r
+\r
+ //\r
+ // Now install the Reset RT AP on a new handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mResetHandle,\r
+ &gEfiResetArchProtocolGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+ x64Reset.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_PROTOCOL_DEFINITION (CpuIO)\r
+\r
+DEPENDENCY_START\r
+ EFI_CPU_IO_PROTOCOL_GUID\r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ LegacyMetronome.c\r
+\r
+Abstract:\r
+\r
+ This contains the installation function for the driver.\r
+\r
+--*/\r
+\r
+#include "Metronome.h"\r
+\r
+//\r
+// Handle for the Metronome Architectural Protocol instance produced by this driver\r
+//\r
+EFI_HANDLE mMetronomeHandle = NULL;\r
+\r
+//\r
+// The Metronome Architectural Protocol instance produced by this driver\r
+//\r
+EFI_METRONOME_ARCH_PROTOCOL mMetronome = {\r
+ WaitForTick,\r
+ TICK_PERIOD\r
+};\r
+\r
+//\r
+// The CPU I/O Protocol used to access system hardware\r
+//\r
+EFI_CPU_IO_PROTOCOL *mCpuIo = NULL;\r
+\r
+//\r
+// Worker Functions\r
+//\r
+VOID\r
+IoWrite8 (\r
+ UINT16 Port,\r
+ UINT8 Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Write an 8 bit value to an I/O port and save it to the S3 script\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+ None.\r
+\r
+--*/\r
+// TODO: Port - add argument and description to function comment\r
+// TODO: Data - add argument and description to function comment\r
+{\r
+ mCpuIo->Io.Write (\r
+ mCpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ Port,\r
+ 1,\r
+ &Data\r
+ );\r
+\r
+}\r
+\r
+UINT8\r
+ReadRefresh (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Read the refresh bit from the REFRESH_PORT\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINT8 Data;\r
+\r
+ mCpuIo->Io.Read (\r
+ mCpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ REFRESH_PORT,\r
+ 1,\r
+ &Data\r
+ );\r
+ return (UINT8) (Data & REFRESH_ON);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+WaitForTick (\r
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,\r
+ IN UINT32 TickNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Waits for the TickNumber of ticks from a known platform time source.\r
+\r
+Arguments:\r
+\r
+ This Pointer to the protocol instance.\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS If number of ticks occurred.\r
+ EFI_NOT_FOUND Could not locate CPU IO protocol\r
+\r
+--*/\r
+// TODO: TickNumber - add argument and description to function comment\r
+{\r
+ //\r
+ // Wait for TickNumber toggles of the Refresh bit\r
+ //\r
+ for (; TickNumber != 0x00; TickNumber--) {\r
+ while (ReadRefresh () == REFRESH_ON)\r
+ ;\r
+ while (ReadRefresh () == REFRESH_OFF)\r
+ ;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InstallMetronome (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Install the LegacyMetronome driver. Loads a Metronome Arch Protocol based\r
+ on the Port 61 timer.\r
+\r
+Arguments:\r
+\r
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Metronome Architectural Protocol Installed\r
+\r
+--*/\r
+// TODO: ImageHandle - add argument and description to function comment\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Make sure the Metronome Architectural Protocol is not already installed in the system\r
+ //\r
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid);\r
+\r
+ //\r
+ // Get the CPU I/O Protocol that this driver requires\r
+ // If the CPU I/O Protocol is not found, then ASSERT because the dependency expression\r
+ // should guarantee that it is present in the handle database.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &mCpuIo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Program port 61 timer 1 as refresh timer. We could use ACPI timer in the\r
+ // future.\r
+ //\r
+ IoWrite8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB);\r
+ IoWrite8 (TIMER1_COUNT_PORT, COUNTER1_COUNT);\r
+\r
+ //\r
+ // Install on a new handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mMetronomeHandle,\r
+ &gEfiMetronomeArchProtocolGuid,\r
+ &mMetronome,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ LegacyMetronome.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_PROTOCOL_DEFINITION (CpuIo)\r
+\r
+DEPENDENCY_START\r
+ EFI_CPU_IO_PROTOCOL_GUID \r
+DEPENDENCY_END\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ LegacyMetronome.h\r
+\r
+Abstract:\r
+\r
+ Driver implementing the EFI 2.0 metronome protocol using the legacy PORT 61 \r
+ timer.\r
+\r
+--*/\r
+\r
+#ifndef _LEGACY_METRONOME_H\r
+#define _LEGACY_METRONOME_H\r
+\r
+//\r
+// Statements that include other files\r
+//\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/CpuIo.h>\r
+#include <Protocol/Metronome.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+//\r
+// Private definitions\r
+//\r
+#define TICK_PERIOD 300\r
+#define REFRESH_PORT 0x61\r
+#define REFRESH_ON 0x10\r
+#define REFRESH_OFF 0x00\r
+#define TIMER1_CONTROL_PORT 0x43\r
+#define TIMER1_COUNT_PORT 0x41\r
+#define LOAD_COUNTER1_LSB 0x54\r
+#define COUNTER1_COUNT 0x12\r
+\r
+//\r
+// Function Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+WaitForTick (\r
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,\r
+ IN UINT32 TickNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ TickNumber - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2005, 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
+# Module Name:\r
+#\r
+# Abstract:\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Metronome\r
+ FILE_GUID = 07A9330A-F347-11d4-9A49-0090273FC14D\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InstallMetronome\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ DuetPkg/DuetPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ UefiBootServicesTableLib\r
+\r
+[Sources.common]\r
+ Metronome.c\r
+ Metronome.h\r
+\r
+[Protocols]\r
+ gEfiMetronomeArchProtocolGuid\r
+ gEfiCpuIoProtocolGuid\r
+\r
+[Depex]\r
+ gEfiCpuIoProtocolGuid\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+\r
+ BdsPlatform.c\r
+\r
+Abstract:\r
+\r
+ This file include all platform action which can be customized\r
+ by IBV/OEM.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)\r
+\r
+CHAR16 mFirmwareVendor[] = L"TianoCore.org";\r
+extern BOOLEAN gConnectAllHappened;\r
+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;\r
+//\r
+// BDS Platform Functions\r
+//\r
+\r
+VOID\r
+GetSystemTablesFromHob (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *HobList;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *HobStart;\r
+ EFI_PHYSICAL_ADDRESS *Table;\r
+ UINTN Index;\r
+ EFI_GUID *TableGuidArray[] = {\r
+ &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid\r
+ };\r
+\r
+ //\r
+ // Get Hob List\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table\r
+ //\r
+ for (Index = 0; Index < sizeof (TableGuidArray) / sizeof (*TableGuidArray); ++Index) {\r
+ HobStart = HobList;\r
+ Table = NULL;\r
+ Table = GetNextGuidHob (TableGuidArray[Index], &HobStart);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Table != NULL) {\r
+ //\r
+ // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,\r
+ // According to UEFI Spec, we should make sure Smbios table, \r
+ // ACPI table and Mps tables kept in memory of specified type\r
+ //\r
+ ConvertSystemTable(TableGuidArray[Index], &Table);\r
+ gBS->InstallConfigurationTable (TableGuidArray[Index], (VOID *)Table);\r
+ }\r
+ }\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+#define EFI_LDR_MEMORY_DESCRIPTOR_GUID \\r
+ { 0x7701d7e5, 0x7d1d, 0x4432, 0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }\r
+\r
+EFI_GUID gEfiLdrMemoryDescriptorGuid = EFI_LDR_MEMORY_DESCRIPTOR_GUID;\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ EFI_HOB_GUID_TYPE Hob;\r
+ UINTN MemDescCount;\r
+ EFI_MEMORY_DESCRIPTOR *MemDesc;\r
+} MEMORY_DESC_HOB;\r
+\r
+#pragma pack()\r
+\r
+#if 0\r
+VOID\r
+PrintMemoryMap (\r
+ VOID\r
+ )\r
+{\r
+ EFI_MEMORY_DESCRIPTOR *MemMap;\r
+ EFI_MEMORY_DESCRIPTOR *MemMapPtr;\r
+ UINTN MemMapSize;\r
+ UINTN MapKey, DescriptorSize;\r
+ UINTN Index;\r
+ UINT32 DescriptorVersion;\r
+ UINT64 Bytes;\r
+ EFI_STATUS Status;\r
+\r
+ MemMapSize = 0;\r
+ MemMap = NULL;\r
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+ MemMapSize += EFI_PAGE_SIZE;\r
+ Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap);\r
+ ASSERT (Status == EFI_SUCCESS);\r
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
+ ASSERT (Status == EFI_SUCCESS);\r
+ MemMapPtr = MemMap;\r
+\r
+ ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);\r
+\r
+ for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) {\r
+ Bytes = LShiftU64 (MemMap->NumberOfPages, 12);\r
+ DEBUG ((EFI_D_ERROR, "%lX-%lX %lX %lX %X\n",\r
+ MemMap->PhysicalStart, \r
+ MemMap->PhysicalStart + Bytes - 1,\r
+ MemMap->NumberOfPages, \r
+ MemMap->Attribute,\r
+ (UINTN)MemMap->Type));\r
+ MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize);\r
+ }\r
+\r
+ gBS->FreePool (MemMapPtr);\r
+}\r
+#endif\r
+\r
+VOID\r
+UpdateMemoryMap (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *HobList;\r
+ VOID *Table;\r
+ MEMORY_DESC_HOB MemoryDescHob;\r
+ UINTN Index;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+\r
+ //\r
+ // Get Hob List\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ Table = GetNextGuidHob (&gEfiLdrMemoryDescriptorGuid, &HobList);\r
+ MemoryDescHob.MemDescCount = *(UINTN *)Table;\r
+ MemoryDescHob.MemDesc = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));\r
+\r
+ //\r
+ // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap\r
+ //\r
+ for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {\r
+ if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {\r
+ continue;\r
+ }\r
+ if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000) {\r
+ continue;\r
+ }\r
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {\r
+ DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%x, ", MemoryDescHob.MemDesc[Index].PhysicalStart));\r
+ DEBUG ((EFI_D_ERROR, "PageNumber - 0x%x, ", MemoryDescHob.MemDesc[Index].NumberOfPages));\r
+ DEBUG ((EFI_D_ERROR, "Type - 0x%x\n", MemoryDescHob.MemDesc[Index].Type));\r
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {\r
+ //\r
+ // Skip RuntimeSevicesData and RuntimeServicesCode, they are BFV\r
+ //\r
+ continue;\r
+ }\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeSystemMemory,\r
+ MemoryDescHob.MemDesc[Index].PhysicalStart,\r
+ LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),\r
+ MemoryDescHob.MemDesc[Index].Attribute\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "AddMemorySpace fail!\n"));\r
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||\r
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {\r
+ //\r
+ // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.\r
+ // For EfiReservedMemoryType, there maybe overlap. So skip check here.\r
+ //\r
+// ASSERT_EFI_ERROR (Status);\r
+ }\r
+ continue;\r
+ }\r
+\r
+ Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ MemoryDescHob.MemDesc[Index].Type,\r
+ (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,\r
+ &Memory\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "AllocatePages fail!\n"));\r
+ //\r
+ // For the page added, it must be allocated.\r
+ //\r
+// ASSERT_EFI_ERROR (Status);\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ \r
+}\r
+\r
+EFI_STATUS\r
+DisableUsbLegacySupport(\r
+ void\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Disabble the USB legacy Support in all Ehci and Uhci.\r
+ This function assume all PciIo handles have been created in system.\r
+ \r
+Arguments:\r
+ None\r
+ \r
+Returns:\r
+ EFI_SUCCESS\r
+ EFI_NOT_FOUND\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleArray;\r
+ UINTN HandleArrayCount;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Class[3];\r
+ UINT16 Command;\r
+ UINT32 HcCapParams;\r
+ UINT32 ExtendCap;\r
+ UINT32 Value;\r
+ UINT32 TimeOut;\r
+ \r
+ //\r
+ // Find the usb host controller \r
+ // \r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleArrayCount,\r
+ &HandleArray\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < HandleArrayCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleArray[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **)&PciIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Find the USB host controller controller\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((PCI_CLASS_SERIAL == Class[2]) &&\r
+ (PCI_CLASS_SERIAL_USB == Class[1])) {\r
+ if (PCI_CLASSC_PI_UHCI == Class[0]) {\r
+ //\r
+ // Found the UHCI, then disable the legacy support\r
+ //\r
+ Command = 0;\r
+ Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command);\r
+ } else if (PCI_CLASSC_PI_EHCI == Class[0]) {\r
+ //\r
+ // Found the EHCI, then disable the legacy support\r
+ //\r
+ Status = PciIo->Mem.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0, //EHC_BAR_INDEX\r
+ (UINT64) 0x08, //EHC_HCCPARAMS_OFFSET\r
+ 1,\r
+ &HcCapParams\r
+ );\r
+ \r
+ ExtendCap = (HcCapParams >> 8) & 0xFF;\r
+ //\r
+ // Disable the SMI in USBLEGCTLSTS firstly\r
+ //\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);\r
+ Value &= 0xFFFF0000;\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);\r
+ \r
+ //\r
+ // Get EHCI Ownership from legacy bios\r
+ //\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r
+ Value |= (0x1 << 24);\r
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r
+\r
+ TimeOut = 40;\r
+ while (TimeOut--) {\r
+ gBS->Stall (500);\r
+\r
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);\r
+\r
+ if ((Value & 0x01010000) == 0x01000000) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ } \r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ return Status;\r
+ }\r
+ gBS->FreePool (HandleArray);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+VOID\r
+PlatformBdsInit (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Platform Bds init. Incude the platform firmware vendor, revision\r
+ and so crc check.\r
+\r
+Arguments:\r
+\r
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ //\r
+ // set firmwarevendor, here can be IBV/OEM customize\r
+ //\r
+ gST->FirmwareVendor = AllocateRuntimeCopyPool (\r
+ sizeof (mFirmwareVendor),\r
+ &mFirmwareVendor\r
+ );\r
+ ASSERT (gST->FirmwareVendor != NULL);\r
+\r
+ gST->FirmwareRevision = 0;\r
+\r
+ //\r
+ // Fixup Tasble CRC after we updated Firmware Vendor and Revision\r
+ //\r
+ gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);\r
+}\r
+\r
+UINT64\r
+GetPciExpressBaseAddressForRootBridge (\r
+ IN UINTN HostBridgeNumber,\r
+ IN UINTN RootBridgeNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This routine is to get PciExpress Base Address for this RootBridge\r
+\r
+Arguments:\r
+ HostBridgeNumber - The number of HostBridge\r
+ RootBridgeNumber - The number of RootBridge\r
+ \r
+Returns:\r
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge\r
+\r
+--*/\r
+{\r
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;\r
+ UINTN BufferSize;\r
+ UINT32 Index;\r
+ UINT32 Number;\r
+ VOID *HobList;\r
+ EFI_STATUS Status;\r
+\r
+ BufferSize = 0;\r
+ //\r
+ // Get Hob List from configuration table\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
+ if (EFI_ERROR (Status)) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Get PciExpressAddressInfo Hob\r
+ //\r
+ PciExpressBaseAddressInfo = NULL;\r
+ PciExpressBaseAddressInfo = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);\r
+\r
+ //\r
+ // Search the PciExpress Base Address in the Hob for current RootBridge\r
+ //\r
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));\r
+ for (Index = 0; Index < Number; Index++) {\r
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&\r
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {\r
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do not find the PciExpress Base Address in the Hob\r
+ //\r
+ return 0;\r
+}\r
+\r
+VOID\r
+PatchPciRootBridgeDevicePath (\r
+ IN UINTN HostBridgeNumber,\r
+ IN UINTN RootBridgeNumber,\r
+ IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH *RootBridge\r
+ )\r
+{\r
+ UINT64 PciExpressBase;\r
+\r
+ PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);\r
+\r
+ if (PciExpressBase != 0) {\r
+ RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+ConnectRootBridge (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Connect RootBridge\r
+\r
+Arguments:\r
+\r
+ None.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - Connect RootBridge successfully.\r
+ EFI_STATUS - Connect RootBridge fail.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE RootHandle;\r
+\r
+ //\r
+ // Patch Pci Root Bridge Device Path\r
+ //\r
+ PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);\r
+\r
+ //\r
+ // Make all the PCI_IO protocols on PCI Seg 0 show up\r
+ //\r
+ BdsLibConnectDevicePath (gPlatformRootBridges[0]);\r
+\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid, \r
+ &gPlatformRootBridges[0], \r
+ &RootHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PrepareLpcBridgeDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add IsaKeyboard to ConIn,\r
+ add IsaSerial to ConOut, ConIn, ErrOut.\r
+ LPC Bridge: 06 01 00\r
+\r
+Arguments:\r
+\r
+ DeviceHandle - Handle of PCIIO protocol.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
+ EFI_STATUS - No LPC bridge is added.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ TempDevicePath = DevicePath;\r
+\r
+ //\r
+ // Register Keyboard\r
+ //\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
+\r
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+\r
+ //\r
+ // Register COM1\r
+ //\r
+ DevicePath = TempDevicePath;\r
+ gPnp16550ComPortDeviceNode.UID = 0;\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+\r
+ //\r
+ // Register COM2\r
+ //\r
+ DevicePath = TempDevicePath;\r
+ gPnp16550ComPortDeviceNode.UID = 1;\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+EFI_STATUS\r
+GetGopDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE PciDeviceHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
+ UINTN GopHandleCount;\r
+ EFI_HANDLE *GopHandleBuffer;\r
+\r
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Initialize the GopDevicePath to be PciDevicePath\r
+ //\r
+ *GopDevicePath = PciDevicePath;\r
+ TempPciDevicePath = PciDevicePath;\r
+\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TempPciDevicePath,\r
+ &PciDeviceHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Try to connect this handle, so that GOP dirver could start on this \r
+ // device and create child handles with GraphicsOutput Protocol installed\r
+ // on them, then we get device paths of these child handles and select \r
+ // them as possible console device.\r
+ //\r
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ NULL,\r
+ &GopHandleCount,\r
+ &GopHandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Add all the child handles as possible Console Device\r
+ //\r
+ for (Index = 0; Index < GopHandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, &TempDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ if (CompareMem (\r
+ PciDevicePath,\r
+ TempDevicePath,\r
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
+ ) == 0) {\r
+ //\r
+ // In current implementation, we only enable one of the child handles\r
+ // as console device, i.e. sotre one of the child handle's device\r
+ // path to variable "ConOut"\r
+ // In futhure, we could select all child handles to be console device\r
+ // \r
+\r
+ *GopDevicePath = TempDevicePath;\r
+\r
+ //\r
+ // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
+ // Add the integrity GOP device path.\r
+ //\r
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);\r
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);\r
+ }\r
+ }\r
+ gBS->FreePool (GopHandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+#endif\r
+\r
+EFI_STATUS\r
+PreparePciVgaDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add PCI VGA to ConOut.\r
+ PCI VGA: 03 00 00\r
+\r
+Arguments:\r
+\r
+ DeviceHandle - Handle of PCIIO protocol.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - PCI VGA is added to ConOut.\r
+ EFI_STATUS - No PCI VGA device is added.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
+#endif \r
+\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+ GetGopDevicePath (DevicePath, &GopDevicePath);\r
+ DevicePath = GopDevicePath;\r
+#endif\r
+\r
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PreparePciSerialDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add PCI Serial to ConOut, ConIn, ErrOut.\r
+ PCI Serial: 07 00 02\r
+\r
+Arguments:\r
+\r
+ DeviceHandle - Handle of PCIIO protocol.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
+ EFI_STATUS - No PCI Serial device is added.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DetectAndPreparePlatformPciDevicePath (\r
+ BOOLEAN DetectVgaOnly\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
+\r
+Arguments:\r
+\r
+ DetectVgaOnly - Only detect VGA device if it's TRUE.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
+ EFI_STATUS - PCI Device check or Console variable update fail.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+\r
+ //\r
+ // Start to check all the PciIo to find all possible device\r
+ //\r
+ HandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, &PciIo);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check for all PCI device\r
+ //\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if (!DetectVgaOnly) {\r
+ //\r
+ // Here we decide whether it is LPC Bridge\r
+ //\r
+ if ((IS_PCI_LPC (&Pci)) ||\r
+ ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {\r
+ //\r
+ // Add IsaKeyboard to ConIn,\r
+ // add IsaSerial to ConOut, ConIn, ErrOut\r
+ //\r
+ PrepareLpcBridgeDevicePath (HandleBuffer[Index]);\r
+ continue;\r
+ }\r
+ //\r
+ // Here we decide which Serial device to enable in PCI bus \r
+ //\r
+ if (IS_PCI_16550SERIAL (&Pci)) {\r
+ //\r
+ // Add them to ConOut, ConIn, ErrOut.\r
+ //\r
+ PreparePciSerialDevicePath (HandleBuffer[Index]);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Here we decide which VGA device to enable in PCI bus \r
+ //\r
+ if (IS_PCI_VGA (&Pci)) {\r
+ //\r
+ // Add them to ConOut.\r
+ //\r
+ PreparePciVgaDevicePath (HandleBuffer[Index]);\r
+ continue;\r
+ }\r
+ }\r
+ \r
+ gBS->FreePool (HandleBuffer);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Connect the predefined platform default console device. Always try to find\r
+ and enable the vga device if have.\r
+\r
+Arguments:\r
+\r
+ PlatformConsole - Predfined platform default console device array.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - Success connect at least one ConIn and ConOut \r
+ device, there must have one ConOut device is \r
+ active vga device.\r
+ \r
+ EFI_STATUS - Return the status of \r
+ BdsLibConnectAllDefaultConsoles ()\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
+ UINTN DevicePathSize;\r
+\r
+ //\r
+ // Connect RootBridge\r
+ //\r
+ ConnectRootBridge ();\r
+\r
+ VarConout = BdsLibGetVariableAndSize (\r
+ VarConsoleOut,\r
+ &gEfiGlobalVariableGuid,\r
+ &DevicePathSize\r
+ );\r
+ VarConin = BdsLibGetVariableAndSize (\r
+ VarConsoleInp,\r
+ &gEfiGlobalVariableGuid,\r
+ &DevicePathSize\r
+ );\r
+ if (VarConout == NULL || VarConin == NULL) {\r
+ //\r
+ // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
+ //\r
+ DetectAndPreparePlatformPciDevicePath (FALSE);\r
+\r
+ //\r
+ // Have chance to connect the platform default console,\r
+ // the platform default console is the minimue device group\r
+ // the platform should support\r
+ //\r
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
+ //\r
+ // Update the console variable with the connect type\r
+ //\r
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
+ BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);\r
+ }\r
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
+ BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);\r
+ }\r
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
+ BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Only detect VGA device and add them to ConOut\r
+ //\r
+ DetectAndPreparePlatformPciDevicePath (TRUE);\r
+ }\r
+ \r
+ //\r
+ // The ConIn devices connection will start the USB bus, should disable all\r
+ // Usb legacy support firstly.\r
+ // Caution: Must ensure the PCI bus driver has been started. Since the \r
+ // ConnectRootBridge() will create all the PciIo protocol, it's safe here now\r
+ //\r
+ Status = DisableUsbLegacySupport();\r
+ \r
+ //\r
+ // Connect the all the default console with current cosole variable\r
+ //\r
+ Status = BdsLibConnectAllDefaultConsoles ();\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Connect with predeined platform connect sequence, \r
+ the OEM/IBV can customize with their own connect sequence.\r
+ \r
+Arguments:\r
+\r
+ None.\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ Index = 0;\r
+\r
+ //\r
+ // Here we can get the customized platform connect sequence\r
+ // Notes: we can connect with new variable which record the\r
+ // last time boots connect device path sequence\r
+ //\r
+ while (gPlatformConnectSequence[Index] != NULL) {\r
+ //\r
+ // Build the platform boot option\r
+ //\r
+ BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);\r
+ Index++;\r
+ }\r
+\r
+}\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+ IN OUT LIST_ENTRY *BdsDriverLists\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Load the predefined driver option, OEM/IBV can customize this\r
+ to load their own drivers\r
+ \r
+Arguments:\r
+\r
+ BdsDriverLists - The header of the driver option link list.\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ Index = 0;\r
+\r
+ //\r
+ // Here we can get the customized platform driver option\r
+ //\r
+ while (gPlatformDriverOption[Index] != NULL) {\r
+ //\r
+ // Build the platform boot option\r
+ //\r
+ BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");\r
+ Index++;\r
+ }\r
+\r
+}\r
+\r
+VOID\r
+PlatformBdsDiagnostics (\r
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
+ IN BOOLEAN QuietBoot\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the platform diagnostic, such like test memory. OEM/IBV also\r
+ can customize this fuction to support specific platform diagnostic.\r
+ \r
+Arguments:\r
+\r
+ MemoryTestLevel - The memory test intensive level\r
+ \r
+ QuietBoot - Indicate if need to enable the quiet boot\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Here we can decide if we need to show\r
+ // the diagnostics screen\r
+ // Notes: this quiet boot code should be remove\r
+ // from the graphic lib\r
+ //\r
+ if (QuietBoot) {\r
+ EnableQuietBootEx (&gEfiDefaultBmpLogoGuid, mBdsImageHandle);\r
+ //\r
+ // Perform system diagnostic\r
+ //\r
+ Status = BdsMemoryTest (MemoryTestLevel);\r
+ if (EFI_ERROR (Status)) {\r
+ DisableQuietBoot ();\r
+ }\r
+\r
+ return ;\r
+ }\r
+ //\r
+ // Perform system diagnostic\r
+ //\r
+ Status = BdsMemoryTest (MemoryTestLevel);\r
+}\r
+\r
+VOID\r
+PlatformBdsPolicyBehavior (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,\r
+ IN OUT LIST_ENTRY *DriverOptionList,\r
+ IN OUT LIST_ENTRY *BootOptionList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The function will excute with as the platform policy, current policy\r
+ is driven by boot mode. IBV/OEM can customize this code for their specific\r
+ policy action.\r
+ \r
+Arguments:\r
+\r
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+ \r
+ DriverOptionList - The header of the driver option link list\r
+ \r
+ BootOptionList - The header of the boot option link list\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Timeout;\r
+ EFI_EVENT UserInputDurationTime;\r
+ LIST_ENTRY *Link;\r
+ BDS_COMMON_OPTION *BootOption;\r
+ UINTN Index;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Init the time out value\r
+ //\r
+ Timeout = BdsLibGetTimeout ();\r
+\r
+ //\r
+ // Load the driver option as the driver option list\r
+ //\r
+ PlatformBdsGetDriverOption (DriverOptionList);\r
+\r
+ //\r
+ // Get current Boot Mode\r
+ //\r
+ Status = BdsLibGetBootMode (&PrivateData->BootMode);\r
+ DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", PrivateData->BootMode));\r
+\r
+ //\r
+ // Go the different platform policy with different boot mode\r
+ // Notes: this part code can be change with the table policy\r
+ //\r
+ ASSERT (PrivateData->BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
+ //\r
+ // Connect platform console\r
+ //\r
+ Status = PlatformBdsConnectConsole (gPlatformConsole);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Here OEM/IBV can customize with defined action\r
+ //\r
+ PlatformBdsNoConsoleAction ();\r
+ }\r
+ //\r
+ // Create a 300ms duration event to ensure user has enough input time to enter Setup\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EFI_EVENT_TIMER,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ &UserInputDurationTime\r
+ );\r
+ ASSERT (Status == EFI_SUCCESS);\r
+ Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);\r
+ ASSERT (Status == EFI_SUCCESS);\r
+ //\r
+ // Memory test and Logo show\r
+ //\r
+ PlatformBdsDiagnostics (IGNORE, TRUE);\r
+\r
+ //\r
+ // Perform some platform specific connect sequence\r
+ //\r
+ PlatformBdsConnectSequence ();\r
+\r
+ //\r
+ // Give one chance to enter the setup if we\r
+ // have the time out\r
+ //\r
+ if (Timeout != 0) {\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+ }\r
+\r
+ //\r
+ //BdsLibConnectAll ();\r
+ //BdsLibEnumerateAllBootOption (BootOptionList); \r
+ \r
+ //\r
+ // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot\r
+ // checking code in real production tip.\r
+ // \r
+ // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device \r
+ // and do enumerate all the default boot options. But in development system board, the boot mode \r
+ // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box\r
+ // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.\r
+ //\r
+ Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // If cannot find "BootOrder" variable, it may be first boot. \r
+ // Try to connect all devices and enumerate all boot options here.\r
+ //\r
+ BdsLibConnectAll ();\r
+ BdsLibEnumerateAllBootOption (BootOptionList);\r
+ } \r
+\r
+ //\r
+ // To give the User a chance to enter Setup here, if user set TimeOut is 0.\r
+ // BDS should still give user a chance to enter Setup\r
+ //\r
+ // Connect first boot option, and then check user input before exit \r
+ //\r
+ for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {\r
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+ //\r
+ // skip the header of the link list, becuase it has no boot option\r
+ //\r
+ continue;\r
+ } else {\r
+ //\r
+ // Make sure the boot option device path connected, but ignore the BBS device path\r
+ //\r
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+ } \r
+ break; \r
+ }\r
+ } \r
+\r
+ //\r
+ // Check whether the user input after the duration time has expired \r
+ //\r
+ OldTpl = BdsLibGetCurrentTpl();\r
+ gBS->RestoreTPL (TPL_APPLICATION); \r
+ gBS->WaitForEvent (1, &UserInputDurationTime, &Index);\r
+ gBS->CloseEvent (UserInputDurationTime);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ gBS->RaiseTPL (OldTpl); \r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Enter Setup if user input \r
+ //\r
+ Timeout = 0xffff;\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+ }\r
+ \r
+ return ;\r
+\r
+}\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Hook point after a boot attempt succeeds. We don't expect a boot option to\r
+ return, so the EFI 1.0 specification defines that you will default to an\r
+ interactive mode and stop processing the BootOrder list in this case. This\r
+ is alos a platform implementation and can be customized by IBV/OEM.\r
+\r
+Arguments:\r
+\r
+ Option - Pointer to Boot Option that succeeded to boot.\r
+\r
+Returns:\r
+ \r
+ None.\r
+\r
+--*/\r
+{\r
+ CHAR16 *TmpStr;\r
+\r
+ //\r
+ // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
+ // select loop then we need to pop up a UI and wait for user input.\r
+ //\r
+ TmpStr = Option->StatusString;\r
+ if (TmpStr != NULL) {\r
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+}\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+ IN BDS_COMMON_OPTION *Option,\r
+ IN EFI_STATUS Status,\r
+ IN CHAR16 *ExitData,\r
+ IN UINTN ExitDataSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Hook point after a boot attempt fails.\r
+\r
+Arguments:\r
+ \r
+ Option - Pointer to Boot Option that failed to boot.\r
+\r
+ Status - Status returned from failed boot.\r
+\r
+ ExitData - Exit data returned from failed boot.\r
+\r
+ ExitDataSize - Exit data size returned from failed boot.\r
+\r
+Returns:\r
+ \r
+ None.\r
+\r
+--*/\r
+{\r
+ CHAR16 *TmpStr;\r
+\r
+ //\r
+ // If Boot returned with failed status then we need to pop up a UI and wait\r
+ // for user input.\r
+ //\r
+ TmpStr = Option->StatusString;\r
+ if (TmpStr != NULL) {\r
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function is remained for IBV/OEM to do some platform action,\r
+ if there no console device can be connected.\r
+\r
+Arguments:\r
+ \r
+ None.\r
+ \r
+Returns:\r
+ \r
+ EFI_SUCCESS - Direct return success now.\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConvertSystemTable (\r
+ IN EFI_GUID *TableGuid,\r
+ IN OUT VOID **Table\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000\r
+ Assumption here:\r
+ As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg, \r
+ So here we just check if the range is E/F seg, \r
+ and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS\r
+\r
+Arguments:\r
+ TableGuid - Guid of the table\r
+ Table - pointer to the table \r
+\r
+Returns:\r
+ EFI_SUCEESS - Convert Table successfully\r
+ Other - Failed\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *AcpiHeader;\r
+ UINTN AcpiTableLen;\r
+ \r
+ //\r
+ // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version. \r
+ //\r
+ AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));\r
+ \r
+ if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){\r
+ if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){\r
+ //\r
+ // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size\r
+ //\r
+ AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+ } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){\r
+ //\r
+ // If Acpi 2.0 or later, use RSDP Length fied.\r
+ //\r
+ AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;\r
+ } else {\r
+ //\r
+ // Invalid Acpi Version, return\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = ConvertAcpiTable (AcpiTableLen, Table);\r
+ return Status; \r
+ }\r
+ \r
+ //\r
+ // If matches smbios guid, convert Smbios table.\r
+ //\r
+ if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){\r
+ Status = ConvertSmbiosTable (Table);\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // If the table is MP table?\r
+ //\r
+ if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){\r
+ Status = ConvertMpsTable (Table);\r
+ return Status;\r
+ }\r
+ \r
+ return EFI_UNSUPPORTED;\r
+} \r
+\r
+UINT8\r
+GetBufferCheckSum (\r
+ IN VOID * Buffer,\r
+ IN UINTN Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Caculate buffer checksum (8-bit)\r
+\r
+Arguments:\r
+ Buffer - Pointer to Buffer that to be caculated\r
+ Length - How many bytes are to be caculated \r
+\r
+Returns:\r
+ Checksum of the buffer\r
+\r
+--*/\r
+{\r
+ UINT8 CheckSum;\r
+ UINT8 *Ptr8;\r
+ \r
+ CheckSum = 0;\r
+ Ptr8 = (UINT8 *) Buffer;\r
+ \r
+ while (Length > 0) {\r
+ CheckSum = (UINT8) (CheckSum + *Ptr8++);\r
+ Length--;\r
+ }\r
+ \r
+ return ((0xFF - CheckSum) + 1);\r
+} \r
+\r
+EFI_STATUS\r
+ConvertAcpiTable (\r
+ IN UINTN TableLen,\r
+ IN OUT VOID **Table\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Convert RSDP of ACPI Table if its location is lower than Address:0x100000\r
+ Assumption here:\r
+ As in legacy Bios, ACPI table is required to place in E/F Seg, \r
+ So here we just check if the range is E/F seg, \r
+ and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS\r
+\r
+Arguments:\r
+ TableLen - Acpi RSDP length\r
+ Table - pointer to the table \r
+\r
+Returns:\r
+ EFI_SUCEESS - Convert Table successfully\r
+ Other - Failed\r
+\r
+--*/\r
+{\r
+ VOID *AcpiTableOri;\r
+ VOID *AcpiTableNew;\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS BufferPtr;\r
+\r
+ \r
+ AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table));\r
+ if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {\r
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES(TableLen),\r
+ &BufferPtr\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ AcpiTableNew = (VOID *)(UINTN)BufferPtr;\r
+ CopyMem (AcpiTableNew, AcpiTableOri, TableLen);\r
+ } else {\r
+ AcpiTableNew = AcpiTableOri;\r
+ }\r
+ //\r
+ // Change configuration table Pointer\r
+ //\r
+ *Table = AcpiTableNew;\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConvertSmbiosTable (\r
+ IN OUT VOID **Table\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000\r
+ Assumption here:\r
+ As in legacy Bios, Smbios table is required to place in E/F Seg, \r
+ So here we just check if the range is F seg, \r
+ and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData\r
+Arguments:\r
+ Table - pointer to the table\r
+\r
+Returns:\r
+ EFI_SUCEESS - Convert Table successfully\r
+ Other - Failed\r
+\r
+--*/\r
+{\r
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;\r
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;\r
+ EFI_STATUS Status;\r
+ UINT32 SmbiosEntryLen;\r
+ UINT32 BufferLen;\r
+ EFI_PHYSICAL_ADDRESS BufferPtr;\r
+ \r
+ SmbiosTableNew = NULL;\r
+ SmbiosTableOri = NULL;\r
+ \r
+ //\r
+ // Get Smibos configuration Table \r
+ //\r
+ SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));\r
+ \r
+ if ((SmbiosTableOri == NULL) ||\r
+ ((UINTN)SmbiosTableOri > 0x100000) ||\r
+ ((UINTN)SmbiosTableOri < 0xF0000)){\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Relocate the Smibos memory\r
+ //\r
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;\r
+ if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {\r
+ SmbiosEntryLen = SmbiosTableOri->EntryPointLength;\r
+ } else {\r
+ //\r
+ // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1\r
+ //\r
+ SmbiosEntryLen = 0x1F;\r
+ }\r
+ BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES(BufferLen),\r
+ &BufferPtr\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;\r
+ CopyMem (\r
+ SmbiosTableNew, \r
+ SmbiosTableOri,\r
+ SmbiosEntryLen\r
+ );\r
+ // \r
+ // Get Smbios Structure table address, and make sure the start address is 32-bit align\r
+ //\r
+ BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);\r
+ CopyMem (\r
+ (VOID *)(UINTN)BufferPtr, \r
+ (VOID *)(UINTN)(SmbiosTableOri->TableAddress),\r
+ SmbiosTableOri->TableLength\r
+ );\r
+ SmbiosTableNew->TableAddress = (UINT32)BufferPtr;\r
+ SmbiosTableNew->IntermediateChecksum = 0;\r
+ SmbiosTableNew->IntermediateChecksum = \r
+ GetBufferCheckSum ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);\r
+ //\r
+ // Change the SMBIOS pointer\r
+ //\r
+ *Table = SmbiosTableNew;\r
+ \r
+ return EFI_SUCCESS; \r
+} \r
+\r
+EFI_STATUS\r
+ConvertMpsTable (\r
+ IN OUT VOID **Table\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000\r
+ Assumption here:\r
+ As in legacy Bios, MP table is required to place in E/F Seg, \r
+ So here we just check if the range is E/F seg, \r
+ and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData\r
+Arguments:\r
+ Table - pointer to the table\r
+\r
+Returns:\r
+ EFI_SUCEESS - Convert Table successfully\r
+ Other - Failed\r
+\r
+--*/\r
+{\r
+ UINT32 Data32;\r
+ UINT32 FPLength;\r
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;\r
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;\r
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;\r
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;\r
+ VOID *OemTableOri;\r
+ VOID *OemTableNew;\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS BufferPtr;\r
+ \r
+ //\r
+ // Get MP configuration Table \r
+ //\r
+ MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));\r
+ if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) && \r
+ ((UINTN)MpsFloatingPointerOri >= 0xF0000))){\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Get Floating pointer structure length\r
+ //\r
+ FPLength = MpsFloatingPointerOri->Length * 16;\r
+ Data32 = FPLength + SYS_TABLE_PAD (FPLength);\r
+ MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);\r
+ if (MpsTableOri != NULL) {\r
+ Data32 += MpsTableOri->BaseTableLength;\r
+ Data32 += MpsTableOri->ExtendedTableLength;\r
+ if (MpsTableOri->OemTablePointer != 0x00) {\r
+ Data32 += SYS_TABLE_PAD (Data32);\r
+ Data32 += MpsTableOri->OemTableSize;\r
+ }\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Relocate memory\r
+ //\r
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES(Data32),\r
+ &BufferPtr\r
+ );\r
+ ASSERT_EFI_ERROR (Status); \r
+ MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;\r
+ CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);\r
+ //\r
+ // If Mp Table exists\r
+ //\r
+ if (MpsTableOri != NULL) {\r
+ //\r
+ // Get Mps table length, including Ext table\r
+ //\r
+ BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);\r
+ MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;\r
+ CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);\r
+ \r
+ if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){\r
+ BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;\r
+ BufferPtr += SYS_TABLE_PAD (BufferPtr);\r
+ OemTableNew = (VOID *)(UINTN)BufferPtr;\r
+ OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;\r
+ CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);\r
+ MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;\r
+ }\r
+ MpsTableNew->Checksum = 0;\r
+ MpsTableNew->Checksum = GetBufferCheckSum (MpsTableNew, MpsTableOri->BaseTableLength);\r
+ MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;\r
+ MpsFloatingPointerNew->Checksum = 0;\r
+ MpsFloatingPointerNew->Checksum = GetBufferCheckSum (MpsFloatingPointerNew, FPLength);\r
+ }\r
+ //\r
+ // Change the pointer\r
+ //\r
+ *Table = MpsFloatingPointerNew;\r
+ \r
+ return EFI_SUCCESS; \r
+} \r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name: \r
+\r
+ BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+ Head file for BDS Platform specific code\r
+\r
+--*/\r
+\r
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/Smbios.h>\r
+#include <IndustryStandard/LegacyBiosMpTable.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+\r
+#include <Guid/Bmp.h>\r
+#include <Guid/Acpi.h>\r
+#include <Guid/Smbios.h>\r
+#include <Guid/Mps.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/PciExpressBaseAddress.h>\r
+#include <Guid/GlobalVariable.h>\r
+\r
+extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];\r
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];\r
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[];\r
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[];\r
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;\r
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;\r
+extern UART_DEVICE_PATH gUartDeviceNode;\r
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;\r
+//\r
+//\r
+//\r
+#define VarConsoleInpDev L"ConInDev"\r
+#define VarConsoleInp L"ConIn"\r
+#define VarConsoleOutDev L"ConOutDev"\r
+#define VarConsoleOut L"ConOut"\r
+#define VarErrorOutDev L"ErrOutDev"\r
+#define VarErrorOut L"ErrOut"\r
+\r
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
+ { \\r
+ HARDWARE_DEVICE_PATH, \\r
+ HW_PCI_DP, \\r
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8), \\r
+ (Func), \\r
+ (Dev) \\r
+ }\r
+\r
+#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
+ { \\r
+ ACPI_DEVICE_PATH, \\r
+ ACPI_DP, \\r
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), \\r
+ EISA_PNP_ID((PnpId)), \\r
+ 0 \\r
+ }\r
+\r
+#define gPciRootBridge \\r
+ PNPID_DEVICE_PATH_NODE(0x0A03)\r
+\r
+#define gPciIsaBridge \\r
+ PCI_DEVICE_PATH_NODE(0, 0x1f)\r
+\r
+#define gP2PBridge \\r
+ PCI_DEVICE_PATH_NODE(0, 0x1e)\r
+\r
+#define gPnpPs2Keyboard \\r
+ PNPID_DEVICE_PATH_NODE(0x0303)\r
+\r
+#define gPnp16550ComPort \\r
+ PNPID_DEVICE_PATH_NODE(0x0501)\r
+\r
+#define gUart \\r
+ { \\r
+ MESSAGING_DEVICE_PATH, \\r
+ MSG_UART_DP, \\r
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8), \\r
+ 0, \\r
+ 115200, \\r
+ 8, \\r
+ 1, \\r
+ 1 \\r
+ }\r
+\r
+#define gPcAnsiTerminal \\r
+ { \\r
+ MESSAGING_DEVICE_PATH, \\r
+ MSG_VENDOR_DP, \\r
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), \\r
+ DEVICE_PATH_MESSAGING_PC_ANSI \\r
+ }\r
+\r
+#define gEndEntire \\r
+ { \\r
+ END_DEVICE_PATH_TYPE, \\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \\r
+ END_DEVICE_PATH_LENGTH, \\r
+ 0 \\r
+ }\r
+\r
+#define PCI_CLASS_SCC 0x07\r
+#define PCI_SUBCLASS_SERIAL 0x00\r
+#define PCI_IF_16550 0x02\r
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)\r
+\r
+#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF\r
+#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )\r
+//\r
+// Platform Root Bridge\r
+//\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH PciRootBridge;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;\r
+\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH PciRootBridge;\r
+ PCI_DEVICE_PATH IsaBridge;\r
+ ACPI_HID_DEVICE_PATH Keyboard;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH;\r
+\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH PciRootBridge;\r
+ PCI_DEVICE_PATH IsaBridge;\r
+ ACPI_HID_DEVICE_PATH IsaSerial;\r
+ UART_DEVICE_PATH Uart;\r
+ VENDOR_DEVICE_PATH TerminalType;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH;\r
+\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH PciRootBridge;\r
+ PCI_DEVICE_PATH VgaDevice;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;\r
+\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH PciRootBridge;\r
+ PCI_DEVICE_PATH PciBridge;\r
+ PCI_DEVICE_PATH SerialDevice;\r
+ UART_DEVICE_PATH Uart;\r
+ VENDOR_DEVICE_PATH TerminalType;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;\r
+\r
+//\r
+// the short form device path for Usb keyboard\r
+//\r
+#define CLASS_HID 3\r
+#define SUBCLASS_BOOT 1\r
+#define PROTOCOL_KEYBOARD 1\r
+\r
+typedef struct {\r
+ USB_CLASS_DEVICE_PATH UsbClass;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} USB_CLASS_FORMAT_DEVICE_PATH; \r
+\r
+extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0;\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+VOID\r
+PlatformBdsInit (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsPolicyBehavior (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,\r
+ IN LIST_ENTRY *DriverOptionList,\r
+ IN LIST_ENTRY *BootOptionList\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+ IN LIST_ENTRY *BdsDriverLists\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+ EXTENDMEM_COVERAGE_LEVEL Level\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ CHAR16 *Title,\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ UINTN Progress,\r
+ UINTN PreviousValue\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+ VOID\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+ IN BDS_COMMON_OPTION *Option,\r
+ IN EFI_STATUS Status,\r
+ IN CHAR16 *ExitData,\r
+ IN UINTN ExitDataSize\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+ EFI_BOOT_MODE BootMode\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+ VOID\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+ConvertMpsTable (\r
+ IN OUT VOID **Table\r
+ )\r
+;\r
+ \r
+EFI_STATUS\r
+ConvertSmbiosTable (\r
+ IN OUT VOID **Table\r
+ )\r
+;\r
+ \r
+EFI_STATUS\r
+ConvertAcpiTable (\r
+ IN UINTN TableLen,\r
+ IN OUT VOID **Table\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+ConvertSystemTable (\r
+ IN EFI_GUID *TableGuid,\r
+ IN OUT VOID **Table\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+ IN UINT16 TimeoutDefault,\r
+ IN BOOLEAN ConnectAllHappened\r
+ )\r
+;\r
+\r
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
--- /dev/null
+#/*++\r
+#\r
+# Copyright (c) 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
+# Module Name:\r
+#\r
+# PlatformBds.inf\r
+#\r
+# Abstract:\r
+#\r
+# Component description file for Bds module.\r
+#\r
+#--*/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DuetBds\r
+ FILE_GUID = A6F691AC-31C8-4444-854C-E2C1A6950F92\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER \r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+\r
+[Sources.common]\r
+ BdsPlatform.c\r
+ PlatformData.c\r
+ BdsPlatform.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ Nt32Pkg/Nt32Pkg.dec\r
+ DuetPkg/DuetPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PcdLib\r
+ GraphicsLib\r
+ GenericBdsLib\r
+ HobLib\r
+ UefiLib\r
+ DevicePathLib\r
+\r
+[Guids]\r
+ gEfiDefaultBmpLogoGuid\r
+ gEfiGlobalVariableGuid\r
+ gEfiPciExpressBaseAddressGuid\r
+ gEfiAcpi20TableGuid\r
+ gEfiMpsTableGuid\r
+ gEfiSmbiosTableGuid\r
+ gEfiAcpiTableGuid
\ No newline at end of file
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name: \r
+\r
+ PlatformData.c\r
+\r
+Abstract:\r
+ \r
+ Defined the platform specific device path which will be used by\r
+ platform Bbd to perform the platform policy connect.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// Predefined platform default time out value\r
+//\r
+UINT16 gPlatformBootTimeOutDefault = 3;\r
+\r
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;\r
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;\r
+UART_DEVICE_PATH gUartDeviceNode = gUart;\r
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;\r
+\r
+//\r
+// Predefined platform root bridge\r
+//\r
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {\r
+ gPciRootBridge,\r
+ gEndEntire\r
+};\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,\r
+ NULL\r
+};\r
+\r
+USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {\r
+ {\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_CLASS_DP,\r
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)\r
+ },\r
+ 0xffff, // VendorId \r
+ 0xffff, // ProductId \r
+ CLASS_HID, // DeviceClass \r
+ SUBCLASS_BOOT, // DeviceSubClass\r
+ PROTOCOL_KEYBOARD // DeviceProtocol\r
+ },\r
+\r
+ { \r
+ END_DEVICE_PATH_TYPE, \r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \r
+ END_DEVICE_PATH_LENGTH, \r
+ 0\r
+ }\r
+};\r
+\r
+/*\r
+//\r
+// Platform specific Dummy ISA keyboard device path\r
+//\r
+PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH gDummyIsaKeyboardDevicePath = {\r
+ gPciRootBridge,\r
+ gPciIsaBridge,\r
+ gPnpPs2Keyboard,\r
+ gEndEntire\r
+};\r
+\r
+//\r
+// Platform specific Dummy ISA serial device path\r
+//\r
+PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH gDummyIsaSerialDevicePath = {\r
+ gPciRootBridge,\r
+ gPciIsaBridge,\r
+ gPnp16550ComPort,\r
+ gUart,\r
+ gPcAnsiTerminal,\r
+ gEndEntire\r
+};\r
+\r
+//\r
+// Platform specific Dummy PCI VGA device path\r
+//\r
+PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH gDummyPciVgaDevicePath = {\r
+ gPciRootBridge,\r
+ PCI_DEVICE_PATH_NODE(0, 0x2),\r
+ gEndEntire\r
+};\r
+\r
+//\r
+// Platform specific Dummy PCI serial device path\r
+//\r
+PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH gDummyPciSerialDevicePath = {\r
+ gPciRootBridge,\r
+ gP2PBridge,\r
+ PCI_DEVICE_PATH_NODE(0, 0x0),\r
+ gUart,\r
+ gPcAnsiTerminal,\r
+ gEndEntire\r
+};\r
+*/\r
+//\r
+// Predefined platform default console device path\r
+//\r
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {\r
+ //\r
+ // need update dynamically\r
+ //\r
+// {\r
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaSerialDevicePath,\r
+// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
+// },\r
+// {\r
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaKeyboardDevicePath,\r
+// (CONSOLE_IN | STD_ERROR)\r
+// },\r
+// {\r
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciVgaDevicePath,\r
+// CONSOLE_OUT\r
+// },\r
+// {\r
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciSerialDevicePath,\r
+// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
+// },\r
+ {\r
+ (EFI_DEVICE_PATH_PROTOCOL*) &gUsbClassKeyboardDevicePath, \r
+ CONSOLE_IN\r
+ },\r
+ {\r
+ NULL,\r
+ 0\r
+ }\r
+};\r
+\r
+//\r
+// Predefined platform specific driver option\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };\r
+\r
+//\r
+// Predefined platform connect sequence\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ Ia32PcRtc.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+#include "RealTimeClock.h"\r
+\r
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetTime (\r
+ OUT EFI_TIME *Time,\r
+ OUT EFI_TIME_CAPABILITIES *Capabilities\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ Capabilities - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetTime (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcSetTime (Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enabled - TODO: add argument description\r
+ Pending - TODO: add argument description\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetWakeupTime (\r
+ IN BOOLEAN Enabled,\r
+ OUT EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enabled - TODO: add argument description\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeRealTimeClock (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: ImageHandle - add argument and description to function comment\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE NewHandle;\r
+\r
+\r
+ EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);\r
+\r
+ Status = PcRtcInit (&mModuleGlobal);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;\r
+ SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;\r
+ SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;\r
+ SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;\r
+\r
+ NewHandle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewHandle,\r
+ &gEfiRealTimeClockArchProtocolGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ Ia32PcRtc.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)\r
+#include EFI_PROTOCOL_DEFINITION (CpuIo)\r
+\r
+DEPENDENCY_START\r
+ EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID \r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ IpfPcRtc.c\r
+\r
+Abstract:\r
+ Register the extended SAL infrastructure.\r
+\r
+ Make the EFI RT APIs call extended SAL calls via the RT lib wrappers.\r
+ We can not do this on IA-32 as RT lib wrappers call via rRT.\r
+\r
+--*/\r
+\r
+#include "RealTimeClock.h"\r
+\r
+//\r
+// Don't use directly after virtual address have been registered.\r
+//\r
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;\r
+\r
+SAL_RETURN_REGS\r
+PcRtcEsalServicesClassCommonEntry (\r
+ IN UINT64 FunctionId,\r
+ IN UINT64 Arg2,\r
+ IN UINT64 Arg3,\r
+ IN UINT64 Arg4,\r
+ IN UINT64 Arg5,\r
+ IN UINT64 Arg6,\r
+ IN UINT64 Arg7,\r
+ IN UINT64 Arg8,\r
+ IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,\r
+ IN BOOLEAN VirtualMode,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Main entry for Extended SAL Reset Services\r
+\r
+Arguments:\r
+\r
+ FunctionId Function Id which needed to be called.\r
+ Arg2 EFI_RESET_TYPE, whether WARM of COLD reset\r
+ Arg3 Last EFI_STATUS \r
+ Arg4 Data Size of UNICODE STRING passed in ARG5\r
+ Arg5 Unicode String which CHAR16*\r
+\r
+Returns:\r
+\r
+ SAL_RETURN_REGS\r
+\r
+--*/\r
+// TODO: Arg6 - add argument and description to function comment\r
+// TODO: Arg7 - add argument and description to function comment\r
+// TODO: Arg8 - add argument and description to function comment\r
+// TODO: ExtendedSalProc - add argument and description to function comment\r
+// TODO: VirtualMode - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+{\r
+ EFI_STATUS EfiStatus;\r
+ SAL_RETURN_REGS ReturnVal;\r
+\r
+ switch (FunctionId) {\r
+ case GetTime:\r
+ EfiStatus = PcRtcGetTime ((EFI_TIME *) Arg2, (EFI_TIME_CAPABILITIES *) Arg3, Global);\r
+ break;\r
+\r
+ case SetTime:\r
+ EfiStatus = PcRtcSetTime ((EFI_TIME *) Arg2, Global);\r
+ break;\r
+\r
+ case GetWakeupTime:\r
+ EfiStatus = PcRtcGetWakeupTime ((BOOLEAN *) Arg2, (BOOLEAN *) Arg3, (EFI_TIME *) Arg4, Global);\r
+ break;\r
+\r
+ case SetWakeupTime:\r
+ EfiStatus = PcRtcSetWakeupTime ((BOOLEAN) Arg2, (EFI_TIME *) Arg3, Global);\r
+ break;\r
+\r
+ case InitializeThreshold:\r
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;\r
+ break;\r
+\r
+ case BumpThresholdCount:\r
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;\r
+ break;\r
+\r
+ case GetThresholdCount:\r
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;\r
+ break;\r
+\r
+ case GetRtcFreq:\r
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;\r
+ break;\r
+\r
+ default:\r
+ EfiStatus = EFI_SAL_INVALID_ARGUMENT;\r
+ break;;\r
+ }\r
+\r
+ ReturnVal.Status = EfiStatus;\r
+ return ReturnVal;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcRtc (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: ImageHandle - add argument and description to function comment\r
+// TODO: SystemTable - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_TIME Time;\r
+ EFI_TIME_CAPABILITIES Capabilities;\r
+ EFI_STATUS EfiStatus;\r
+\r
+ EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);\r
+\r
+ EfiInitializeLock (&mModuleGlobal.RtcLock, EFI_TPL_HIGH_LEVEL);\r
+\r
+ EfiStatus = PcRtcInit (&mModuleGlobal);\r
+ if (EFI_ERROR (EfiStatus)) {\r
+ return EfiStatus;\r
+ }\r
+\r
+ RegisterEsalClass (\r
+ &gEfiExtendedSalRtcServicesProtocolGuid,\r
+ &mModuleGlobal,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ GetTime,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ SetTime,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ GetWakeupTime,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ SetWakeupTime,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ GetRtcFreq,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ InitializeThreshold,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ BumpThresholdCount,\r
+ PcRtcEsalServicesClassCommonEntry,\r
+ GetThresholdCount,\r
+ NULL\r
+ );\r
+ //\r
+ // the following code is to initialize the RTC fields in case the values read\r
+ // back from CMOS are invalid at the first time.\r
+ //\r
+ EfiStatus = PcRtcGetTime (&Time, &Capabilities, &mModuleGlobal);\r
+ if (EFI_ERROR (EfiStatus)) {\r
+ Time.Second = RTC_INIT_SECOND;\r
+ Time.Minute = RTC_INIT_MINUTE;\r
+ Time.Hour = RTC_INIT_HOUR;\r
+ Time.Day = RTC_INIT_DAY;\r
+ Time.Month = RTC_INIT_MONTH;\r
+ Time.Year = RTC_INIT_YEAR;\r
+ PcRtcSetTime (&Time, &mModuleGlobal);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ IpfPcRtc.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)\r
+\r
+DEPENDENCY_START\r
+ EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID\r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcRtc.c\r
+\r
+Abstract:\r
+\r
+ RTC Architectural Protocol GUID as defined in EFI 2.0\r
+\r
+--*/\r
+\r
+#include "RealTimeClock.h"\r
+\r
+BOOLEAN\r
+DayValid (\r
+ IN EFI_TIME *Time\r
+ );\r
+\r
+BOOLEAN\r
+IsLeapYear (\r
+ IN EFI_TIME *Time\r
+ );\r
+\r
+BOOLEAN \r
+IsWithinOneDay (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ );\r
+\r
+INTN\r
+CompareHMS (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ );\r
+ \r
+UINT8\r
+RtcRead (\r
+ IN UINT8 Address\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Address - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
+ return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+}\r
+\r
+INTN\r
+CompareHMS (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Compare the Hour, Minute and Second of the 'From' time and the 'To' time.\r
+ Only compare H/M/S in EFI_TIME and ignore other fields here. \r
+\r
+Arguments:\r
+\r
+ From - the first time\r
+ To - the second time \r
+\r
+Returns:\r
+\r
+ >0 : The H/M/S of the 'From' time is later than those of 'To' time\r
+ ==0 : The H/M/S of the 'From' time is same as those of 'To' time\r
+ <0 : The H/M/S of the 'From' time is earlier than those of 'To' time\r
+\r
+--*/\r
+\r
+{\r
+ if ((From->Hour > To->Hour) ||\r
+ ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||\r
+ ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {\r
+ return 1; \r
+ } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {\r
+ return 0;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+VOID\r
+RtcWrite (\r
+ IN UINT8 Address,\r
+ IN UINT8 Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Address - TODO: add argument description\r
+ Data - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);\r
+}\r
+\r
+EFI_STATUS\r
+PcRtcInit (\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_DEVICE_ERROR - TODO: Add description for return value\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_A RegisterA;\r
+ RTC_REGISTER_B RegisterB;\r
+ RTC_REGISTER_C RegisterC;\r
+ RTC_REGISTER_D RegisterD;\r
+ UINT8 Century;\r
+ EFI_TIME Time;\r
+\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ EfiAcquireLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Initialize RTC Register\r
+ //\r
+ // Make sure Division Chain is properly configured,\r
+ // or RTC clock won't "tick" -- time won't increment\r
+ //\r
+ RegisterA.Data = RTC_INIT_REGISTER_A;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);\r
+\r
+ //\r
+ // Read Register B\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ //\r
+ // Clear RTC flag register\r
+ //\r
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
+\r
+ //\r
+ // Clear RTC register D\r
+ //\r
+ RegisterD.Data = RTC_INIT_REGISTER_D;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (100000);\r
+ if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ Time.Second = RtcRead (RTC_ADDRESS_SECONDS);\r
+ Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
+ Time.Hour = RtcRead (RTC_ADDRESS_HOURS);\r
+ Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time.Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time.Year = RtcRead (RTC_ADDRESS_YEAR);\r
+\r
+ ConvertRtcTimeToEfiTime (&Time, RegisterB);\r
+\r
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ } else {\r
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
+ }\r
+\r
+ Time.Year = (UINT16) (Century * 100 + Time.Year);\r
+\r
+ //\r
+ // Set RTC configuration after get original time\r
+ //\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ EfiReleaseLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Validate time fields\r
+ //\r
+ Status = RtcTimeFieldsValid (&Time);\r
+ if (EFI_ERROR (Status)) {\r
+ Time.Second = RTC_INIT_SECOND;\r
+ Time.Minute = RTC_INIT_MINUTE;\r
+ Time.Hour = RTC_INIT_HOUR;\r
+ Time.Day = RTC_INIT_DAY;\r
+ Time.Month = RTC_INIT_MONTH;\r
+ Time.Year = RTC_INIT_YEAR;\r
+ }\r
+ //\r
+ // Reset time value according to new RTC configuration\r
+ //\r
+ PcRtcSetTime (&Time, Global);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcRtcGetTime (\r
+ OUT EFI_TIME *Time,\r
+ IN EFI_TIME_CAPABILITIES *Capabilities,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ Returns: \r
+--*/\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: Capabilities - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+ UINTN BufferSize;\r
+\r
+ //\r
+ // Check parameters for null pointer\r
+ //\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ EfiAcquireLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (100000);\r
+ if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ return Status;\r
+ }\r
+ //\r
+ // Read Register B\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS);\r
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS);\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+\r
+ ConvertRtcTimeToEfiTime (Time, RegisterB);\r
+\r
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ } else {\r
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
+ }\r
+\r
+ Time->Year = (UINT16) (Century * 100 + Time->Year);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ EfiReleaseLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Get the variable that containts the TimeZone and Daylight fields\r
+ //\r
+ Time->TimeZone = Global->SavedTimeZone;\r
+ Time->Daylight = Global->Daylight;\r
+\r
+ BufferSize = sizeof (INT16) + sizeof (UINT8);\r
+\r
+ //\r
+ // Make sure all field values are in correct range\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Fill in Capabilities if it was passed in\r
+ //\r
+ if (Capabilities) {\r
+ Capabilities->Resolution = 1;\r
+ //\r
+ // 1 hertz\r
+ //\r
+ Capabilities->Accuracy = 50000000;\r
+ //\r
+ // 50 ppm\r
+ //\r
+ Capabilities->SetsToZero = FALSE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcRtcSetTime (\r
+ IN EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ Returns: \r
+--*/\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TIME RtcTime;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Make sure that the time fields are valid\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
+\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ EfiAcquireLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (100000);\r
+ if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ return Status;\r
+ }\r
+ //\r
+ // Read Register B, and inhibit updates of the RTC\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+ RegisterB.Bits.SET = 1;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+\r
+ RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
+ RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);\r
+ RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);\r
+ RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);\r
+ RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);\r
+ RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);\r
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
+ Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80));\r
+ }\r
+\r
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
+\r
+ //\r
+ // Allow updates of the RTC registers\r
+ //\r
+ RegisterB.Bits.SET = 0;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ EfiReleaseLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Set the variable that containts the TimeZone and Daylight fields\r
+ //\r
+ Global->SavedTimeZone = Time->TimeZone;\r
+ Global->Daylight = Time->Daylight;\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: Enabled - add argument and description to function comment\r
+// TODO: Pending - add argument and description to function comment\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_B RegisterB;\r
+ RTC_REGISTER_C RegisterC;\r
+ UINT8 Century;\r
+\r
+ //\r
+ // Check paramters for null pointers\r
+ //\r
+ if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ EfiAcquireLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (100000);\r
+ if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Read Register B and Register C\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
+\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ *Enabled = RegisterB.Bits.AIE;\r
+ if (*Enabled) {\r
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);\r
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);\r
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+ } else {\r
+ Time->Second = 0;\r
+ Time->Minute = 0;\r
+ Time->Hour = 0;\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+ }\r
+\r
+ ConvertRtcTimeToEfiTime (Time, RegisterB);\r
+\r
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ } else {\r
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));\r
+ }\r
+\r
+ Time->Year = (UINT16) (Century * 100 + Time->Year);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ EfiReleaseLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Make sure all field values are in correct range\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ *Pending = RegisterC.Bits.AF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcSetWakeupTime (\r
+ IN BOOLEAN Enable,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: Enable - add argument and description to function comment\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: Global - add argument and description to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// TODO: EFI_UNSUPPORTED - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TIME RtcTime;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+ EFI_TIME_CAPABILITIES Capabilities;\r
+\r
+ if (Enable) {\r
+\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Make sure that the time fields are valid\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Just support set alarm time within 24 hours\r
+ //\r
+ PcRtcGetTime (&RtcTime, &Capabilities, Global);\r
+ if (!IsWithinOneDay (&RtcTime, Time)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Make a local copy of the time and date\r
+ //\r
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ EfiAcquireLock (&Global->RtcLock);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (100000);\r
+ if (EFI_ERROR (Status)) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Read Register B, and inhibit updates of the RTC\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ RegisterB.Bits.SET = 1;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ if (Enable) {\r
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+\r
+ //\r
+ // Set RTC alarm time\r
+ //\r
+ RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);\r
+ RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);\r
+ RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);\r
+\r
+ RegisterB.Bits.AIE = 1;\r
+\r
+ } else {\r
+ RegisterB.Bits.AIE = 0;\r
+ }\r
+ //\r
+ // Allow updates of the RTC registers\r
+ //\r
+ RegisterB.Bits.SET = 0;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ EfiReleaseLock (&Global->RtcLock);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINT8\r
+BcdToDecimal (\r
+ IN UINT8 BcdValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: BcdValue - add argument and description to function comment\r
+{\r
+ UINTN High;\r
+ UINTN Low;\r
+\r
+ High = BcdValue >> 4;\r
+ Low = BcdValue - (High << 4);\r
+\r
+ return (UINT8) (Low + (High * 10));\r
+}\r
+\r
+EFI_STATUS\r
+RtcTestCenturyRegister (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+{\r
+ UINT8 Century;\r
+ UINT8 Temp;\r
+\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
+ //\r
+ // RtcWrite (RTC_ADDRESS_CENTURY, 0x00);\r
+ //\r
+ Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
+ if (Temp == 0x19 || Temp == 0x20) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+}\r
+\r
+VOID\r
+ConvertRtcTimeToEfiTime (\r
+ IN EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: RegisterB - add argument and description to function comment\r
+{\r
+ BOOLEAN PM;\r
+\r
+ if ((Time->Hour) & 0x80) {\r
+ PM = TRUE;\r
+ } else {\r
+ PM = FALSE;\r
+ }\r
+\r
+ Time->Hour = (UINT8) (Time->Hour & 0x7f);\r
+\r
+ if (RegisterB.Bits.DM == 0) {\r
+ Time->Year = BcdToDecimal ((UINT8) Time->Year);\r
+ Time->Month = BcdToDecimal (Time->Month);\r
+ Time->Day = BcdToDecimal (Time->Day);\r
+ Time->Hour = BcdToDecimal (Time->Hour);\r
+ Time->Minute = BcdToDecimal (Time->Minute);\r
+ Time->Second = BcdToDecimal (Time->Second);\r
+ }\r
+ //\r
+ // If time is in 12 hour format, convert it to 24 hour format\r
+ //\r
+ if (RegisterB.Bits.MIL == 0) {\r
+ if (PM && Time->Hour < 12) {\r
+ Time->Hour = (UINT8) (Time->Hour + 12);\r
+ }\r
+\r
+ if (!PM && Time->Hour == 12) {\r
+ Time->Hour = 0;\r
+ }\r
+ }\r
+\r
+ Time->Nanosecond = 0;\r
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
+ Time->Daylight = 0;\r
+}\r
+\r
+EFI_STATUS\r
+RtcWaitToUpdate (\r
+ UINTN Timeout\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: Timeout - add argument and description to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ RTC_REGISTER_A RegisterA;\r
+ RTC_REGISTER_D RegisterD;\r
+\r
+ //\r
+ // See if the RTC is functioning correctly\r
+ //\r
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
+\r
+ if (RegisterD.Bits.VRT == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be ready.\r
+ //\r
+ Timeout = (Timeout / 10) + 1;\r
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
+ while (RegisterA.Bits.UIP == 1 && Timeout > 0) {\r
+ MicroSecondDelay (10);\r
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
+ Timeout--;\r
+ }\r
+\r
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
+ if (Timeout == 0 || RegisterD.Bits.VRT == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RtcTimeFieldsValid (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+ \r
+ Returns: \r
+--*/\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ if (Time->Year < 1998 ||\r
+ Time->Year > 2099 ||\r
+ Time->Month < 1 ||\r
+ Time->Month > 12 ||\r
+ (!DayValid (Time)) ||\r
+ Time->Hour > 23 ||\r
+ Time->Minute > 59 ||\r
+ Time->Second > 59 ||\r
+ Time->Nanosecond > 999999999 ||\r
+ (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||\r
+ (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+DayValid (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+\r
+ INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+\r
+ if (Time->Day < 1 ||\r
+ Time->Day > DayOfMonth[Time->Month - 1] ||\r
+ (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
+ ) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+BOOLEAN\r
+IsLeapYear (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ if (Time->Year % 4 == 0) {\r
+ if (Time->Year % 100 == 0) {\r
+ if (Time->Year % 400 == 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+VOID\r
+ConvertEfiTimeToRtcTime (\r
+ IN EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB,\r
+ IN UINT8 *Century\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+\r
+Returns: \r
+--*/\r
+// TODO: Time - add argument and description to function comment\r
+// TODO: RegisterB - add argument and description to function comment\r
+// TODO: Century - add argument and description to function comment\r
+{\r
+ BOOLEAN PM;\r
+\r
+ PM = TRUE;\r
+ //\r
+ // Adjust hour field if RTC in in 12 hour mode\r
+ //\r
+ if (RegisterB.Bits.MIL == 0) {\r
+ if (Time->Hour < 12) {\r
+ PM = FALSE;\r
+ }\r
+\r
+ if (Time->Hour >= 13) {\r
+ Time->Hour = (UINT8) (Time->Hour - 12);\r
+ } else if (Time->Hour == 0) {\r
+ Time->Hour = 12;\r
+ }\r
+ }\r
+ //\r
+ // Set the Time/Date/Daylight Savings values.\r
+ //\r
+ *Century = DecimaltoBcd ((UINT8) (Time->Year / 100));\r
+\r
+ Time->Year = (UINT16) (Time->Year % 100);\r
+\r
+ if (RegisterB.Bits.DM == 0) {\r
+ Time->Year = DecimaltoBcd ((UINT8) Time->Year);\r
+ Time->Month = DecimaltoBcd (Time->Month);\r
+ Time->Day = DecimaltoBcd (Time->Day);\r
+ Time->Hour = DecimaltoBcd (Time->Hour);\r
+ Time->Minute = DecimaltoBcd (Time->Minute);\r
+ Time->Second = DecimaltoBcd (Time->Second);\r
+ }\r
+ //\r
+ // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.\r
+ //\r
+ if (RegisterB.Bits.MIL == 0 && PM) {\r
+ Time->Hour = (UINT8) (Time->Hour | 0x80);\r
+ }\r
+}\r
+ \r
+BOOLEAN \r
+IsWithinOneDay (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Judge whether two days are adjacent.\r
+\r
+Arguments:\r
+\r
+ From - the first day\r
+ To - the second day\r
+\r
+Returns:\r
+\r
+ TRUE - The interval of two days are within one day.\r
+ FALSE - The interval of two days exceed ony day or parameter error.\r
+\r
+--*/\r
+{\r
+ UINT8 DayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};\r
+ BOOLEAN Adjacent = FALSE;\r
+\r
+ if (From->Year == To->Year) {\r
+ if (From->Month == To->Month) {\r
+ if ((From->Day + 1) == To->Day) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ } else if (From->Day == To->Day) {\r
+ if ((CompareHMS(From, To) <= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+ } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {\r
+ if ((From->Month == 2) && !IsLeapYear(From)) {\r
+ if (From->Day == 28) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ } \r
+ }\r
+ } else if (From->Day == DayOfMonth[From->Month - 1]) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+ }\r
+ } else if (((From->Year + 1) == To->Year) &&\r
+ (From->Month == 12) &&\r
+ (From->Day == 31) &&\r
+ (To->Month == 1) &&\r
+ (To->Day == 1)) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+\r
+ return Adjacent;\r
+}\r
+\r
+UINT8\r
+DecimaltoBcd (\r
+ IN UINT8 DecValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments: \r
+\r
+Returns: \r
+\r
+--*/\r
+// TODO: DecValue - add argument and description to function comment\r
+{\r
+ UINTN High;\r
+ UINTN Low;\r
+\r
+ High = DecValue / 10;\r
+ Low = DecValue - (High * 10);\r
+\r
+ return (UINT8) (Low + (High << 4));\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ PcRtc.h\r
+\r
+Abstract:\r
+\r
+ Include for real time clock driver\r
+\r
+Revision History\r
+\r
+\r
+--*/\r
+\r
+#ifndef _RTC_H_\r
+#define _RTC_H_\r
+\r
+#include <FrameworkDxe.h>\r
+\r
+#include <Protocol/RealTimeClock.h>\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+typedef struct {\r
+ EFI_LOCK RtcLock;\r
+ UINT16 SavedTimeZone;\r
+ UINT8 Daylight;\r
+} PC_RTC_MODULE_GLOBALS;\r
+\r
+#define PCAT_RTC_ADDRESS_REGISTER 0x70\r
+#define PCAT_RTC_DATA_REGISTER 0x71\r
+\r
+//\r
+// Dallas DS12C887 Real Time Clock\r
+//\r
+#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59\r
+#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59\r
+#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59\r
+#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59\r
+#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7\r
+#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31\r
+#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12\r
+#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99\r
+#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]\r
+#define RTC_ADDRESS_REGISTER_B 11 // R/W\r
+#define RTC_ADDRESS_REGISTER_C 12 // RO\r
+#define RTC_ADDRESS_REGISTER_D 13 // RO\r
+#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W\r
+//\r
+// Date and time initial values.\r
+// They are used if the RTC values are invalid during driver initialization\r
+//\r
+#define RTC_INIT_SECOND 0\r
+#define RTC_INIT_MINUTE 0\r
+#define RTC_INIT_HOUR 0\r
+#define RTC_INIT_DAY 1\r
+#define RTC_INIT_MONTH 1\r
+#define RTC_INIT_YEAR 2001\r
+\r
+//\r
+// Register initial values\r
+//\r
+#define RTC_INIT_REGISTER_A 0x26\r
+#define RTC_INIT_REGISTER_B 0x02\r
+#define RTC_INIT_REGISTER_D 0x0\r
+\r
+#pragma pack(1)\r
+//\r
+// Register A\r
+//\r
+typedef struct {\r
+ UINT8 RS : 4; // Rate Selection Bits\r
+ UINT8 DV : 3; // Divisor\r
+ UINT8 UIP : 1; // Update in progress\r
+} RTC_REGISTER_A_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_A_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_A;\r
+\r
+//\r
+// Register B\r
+//\r
+typedef struct {\r
+ UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled\r
+ UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode\r
+ UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format\r
+ UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output\r
+ UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled\r
+ UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled\r
+ UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled\r
+ UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited\r
+} RTC_REGISTER_B_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_B_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_B;\r
+\r
+//\r
+// Register C\r
+//\r
+typedef struct {\r
+ UINT8 Reserved : 4; // Read as zero. Can not be written.\r
+ UINT8 UF : 1; // Update End Interrupt Flag\r
+ UINT8 AF : 1; // Alarm Interrupt Flag\r
+ UINT8 PF : 1; // Periodic Interrupt Flag\r
+ UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE\r
+} RTC_REGISTER_C_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_C_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_C;\r
+\r
+//\r
+// Register D\r
+//\r
+typedef struct {\r
+ UINT8 Reserved : 7; // Read as zero. Can not be written.\r
+ UINT8 VRT : 1; // Valid RAM and Time\r
+} RTC_REGISTER_D_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_D_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_D;\r
+\r
+#pragma pack()\r
+\r
+EFI_STATUS\r
+PcRtcInit (\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+PcRtcSetTime (\r
+ IN EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+PcRtcGetTime (\r
+ OUT EFI_TIME *Time,\r
+ IN EFI_TIME_CAPABILITIES *Capabilities,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ Capabilities - TODO: add argument description\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcSetWakeupTime (\r
+ IN BOOLEAN Enable,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enable - TODO: add argument description\r
+ Time - TODO: add argument description\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enabled - TODO: add argument description\r
+ Pending - TODO: add argument description\r
+ Time - TODO: add argument description\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcRtc (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ ImageHandle - TODO: add argument description\r
+ SystemTable - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+UINT8\r
+BcdToDecimal (\r
+ IN UINT8 BcdValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ BcdValue - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+RtcTimeFieldsValid (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+UINT8\r
+DecimaltoBcd (\r
+ IN UINT8 DecValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ DecValue - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+ConvertEfiTimeToRtcTime (\r
+ IN EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB,\r
+ IN UINT8 *Century\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ RegisterB - TODO: add argument description\r
+ Century - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+RtcTestCenturyRegister (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+ConvertRtcTimeToEfiTime (\r
+ IN EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ RegisterB - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+RtcWaitToUpdate (\r
+ UINTN Timeout\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Timeout - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+UINT8\r
+RtcSaveContext (\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+RtcRestoreContext (\r
+ IN UINT8 SavedAddressRegister,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ SavedAddressRegister - TODO: add argument description\r
+ Global - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2005, 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
+# Module Name:\r
+#\r
+# Abstract:\r
+#\r
+#--*/\r
+\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = RealTimeClock\r
+ FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1\r
+ MODULE_TYPE = DXE_RUNTIME_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializeRealTimeClock\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ DuetPkg/DuetPkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
+ IoLib\r
+ TimerLib\r
+ BaseMemoryLib\r
+\r
+[Sources.common]\r
+ RealTimeClock.c\r
+ RealTimeClock.h\r
+\r
+[Sources.ia32]\r
+ Ia32/RealTimeClock.c\r
+\r
+[Sources.x64]\r
+ x64/RealTimeClock.c\r
+\r
+[Sources.ipf]\r
+ Ipf/RealTimeClock.c\r
+\r
+[Protocols]\r
+ gEfiCpuArchProtocolGuid\r
+ gEfiMetronomeArchProtocolGuid \r
+ gEfiCpuIoProtocolGuid\r
+ gEfiRealTimeClockArchProtocolGuid\r
+\r
+[Depex]\r
+ gEfiCpuArchProtocolGuid AND gEfiMetronomeArchProtocolGuid AND gEfiCpuIoProtocolGuid
\ No newline at end of file
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ x64PcRtc.c\r
+\r
+Abstract:\r
+\r
+--*/\r
+\r
+#include "RealTimeClock.h"\r
+\r
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetTime (\r
+ OUT EFI_TIME *Time,\r
+ OUT EFI_TIME_CAPABILITIES *Capabilities\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+ Capabilities - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetTime (\r
+ IN EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcSetTime (Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enabled - TODO: add argument description\r
+ Pending - TODO: add argument description\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetWakeupTime (\r
+ IN BOOLEAN Enabled,\r
+ OUT EFI_TIME *Time\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Enabled - TODO: add argument description\r
+ Time - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeRealTimeClock (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Arguments:\r
+\r
+ \r
+\r
+Returns: \r
+--*/\r
+// TODO: ImageHandle - add argument and description to function comment\r
+// TODO: SystemTable - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE NewHandle;\r
+\r
+ EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);\r
+\r
+ Status = PcRtcInit (&mModuleGlobal);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;\r
+ SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;\r
+ SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;\r
+ SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;\r
+\r
+ NewHandle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewHandle,\r
+ &gEfiRealTimeClockArchProtocolGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ x64PcRtc.dxs\r
+\r
+Abstract:\r
+ Dependency expression source file.\r
+ \r
+--*/ \r
+\r
+\r
+#include "EfiDepex.h"\r
+\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)\r
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)\r
+#include EFI_PROTOCOL_DEFINITION (CpuIo)\r
+\r
+DEPENDENCY_START\r
+ EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID \r
+DEPENDENCY_END\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+\r
+ DeviceIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC-AT PCI Device IO driver\r
+\r
+--*/\r
+#include "PcatPciRootBridge.h"\r
+#include "DeviceIo.h"\r
+\r
+EFI_STATUS\r
+DeviceIoConstructor (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINT16 PrimaryBus,\r
+ IN UINT16 SubordinateBus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Initialize and install a Device IO protocol on a empty device path handle.\r
+\r
+Arguments:\r
+ \r
+ Handle - Handle of PCI RootBridge IO instance\r
+ PciRootBridgeIo - PCI RootBridge IO instance\r
+ DevicePath - Device Path of PCI RootBridge IO instance\r
+ PrimaryBus - Primary Bus\r
+ SubordinateBus - Subordinate Bus\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - This driver is added to ControllerHandle. \r
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. \r
+ Others - This driver does not support this device.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ //\r
+ // Initialize the Device IO device instance.\r
+ //\r
+ Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));\r
+ if (Private == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;\r
+ Private->Handle = Handle;\r
+ Private->PciRootBridgeIo = PciRootBridgeIo;\r
+ Private->DevicePath = DevicePath;\r
+ Private->PrimaryBus = PrimaryBus;\r
+ Private->SubordinateBus = SubordinateBus;\r
+\r
+ Private->DeviceIo.Mem.Read = DeviceIoMemRead;\r
+ Private->DeviceIo.Mem.Write = DeviceIoMemWrite;\r
+ Private->DeviceIo.Io.Read = DeviceIoIoRead;\r
+ Private->DeviceIo.Io.Write = DeviceIoIoWrite;\r
+ Private->DeviceIo.Pci.Read = DeviceIoPciRead;\r
+ Private->DeviceIo.Pci.Write = DeviceIoPciWrite;\r
+ Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;\r
+ Private->DeviceIo.Map = DeviceIoMap;\r
+ Private->DeviceIo.Unmap = DeviceIoUnmap;\r
+ Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;\r
+ Private->DeviceIo.Flush = DeviceIoFlush;\r
+ Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;\r
+\r
+ //\r
+ // Install protocol interfaces for the Device IO device.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Handle,\r
+ &gEfiDeviceIoProtocolGuid,\r
+ &Private->DeviceIo,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMemRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading memory mapped I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device. \r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width > MMIO_COPY_UINT64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Width >= MMIO_COPY_UINT8) {\r
+ Width = Width - MMIO_COPY_UINT8;\r
+ Status = Private->PciRootBridgeIo->CopyMem (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ (UINT64) Buffer,\r
+ Address,\r
+ Count\r
+ );\r
+ } else {\r
+ Status = Private->PciRootBridgeIo->Mem.Read (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMemWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing memory mapped I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width > MMIO_COPY_UINT64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Width >= MMIO_COPY_UINT8) {\r
+ Width = Width - MMIO_COPY_UINT8;\r
+ Status = Private->PciRootBridgeIo->CopyMem (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ (UINT64) Buffer,\r
+ Count\r
+ );\r
+ } else {\r
+ Status = Private->PciRootBridgeIo->Mem.Write (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoIoRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width >= MMIO_COPY_UINT8) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Private->PciRootBridgeIo->Io.Read (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoIoWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations.\r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width >= MMIO_COPY_UINT8) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Private->PciRootBridgeIo->Io.Write (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading PCI configuration space of device\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Private->PciRootBridgeIo->Pci.Read (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing PCI configuration space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Private->PciRootBridgeIo->Pci.Write (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+ Address,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+AppendPciDevicePath (\r
+ IN DEVICE_IO_PRIVATE_DATA *Private,\r
+ IN UINT8 Bus,\r
+ IN UINT8 Device,\r
+ IN UINT8 Function,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN OUT UINT16 *BridgePrimaryBus,\r
+ IN OUT UINT16 *BridgeSubordinateBus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Append a PCI device path node to another device path.\r
+\r
+Arguments:\r
+ \r
+ Private - A pointer to DEVICE_IO_PRIVATE_DATA instance. \r
+ Bus - PCI bus number of the device.\r
+ Device - PCI device number of the device.\r
+ Function - PCI function number of the device.\r
+ DevicePath - Original device path which will be appended a PCI device path node.\r
+ BridgePrimaryBus - Primary bus number of the bridge.\r
+ BridgeSubordinateBus - Subordinate bus number of the bridge.\r
+\r
+Returns:\r
+ \r
+ Pointer to the appended PCI device path.\r
+\r
+--*/\r
+{\r
+ UINT16 ThisBus;\r
+ UINT8 ThisDevice;\r
+ UINT8 ThisFunc;\r
+ UINT64 Address;\r
+ PCI_TYPE01 PciBridge;\r
+ PCI_TYPE01 *PciPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;\r
+ PCI_DEVICE_PATH PciNode;\r
+\r
+ PciPtr = &PciBridge;\r
+ for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {\r
+ for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {\r
+ for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {\r
+ Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);\r
+ ZeroMem (PciPtr, sizeof (PCI_TYPE01));\r
+ Private->DeviceIo.Pci.Read (\r
+ &Private->DeviceIo,\r
+ IO_UINT32,\r
+ Address,\r
+ 1,\r
+ &(PciPtr->Hdr.VendorId)\r
+ );\r
+ if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {\r
+ break;\r
+ }\r
+ if (PciPtr->Hdr.VendorId == 0xffff) {\r
+ continue;\r
+ }\r
+\r
+ Private->DeviceIo.Pci.Read (\r
+ &Private->DeviceIo,\r
+ IO_UINT32,\r
+ Address,\r
+ sizeof (PCI_TYPE01) / sizeof (UINT32),\r
+ PciPtr\r
+ );\r
+ if (IS_PCI_BRIDGE (PciPtr)) {\r
+ if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {\r
+\r
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
+ PciNode.Header.SubType = HW_PCI_DP;\r
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+\r
+ PciNode.Device = ThisDevice;\r
+ PciNode.Function = ThisFunc;\r
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
+\r
+ *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;\r
+ *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;\r
+ return ReturnDevicePath;\r
+ }\r
+ }\r
+\r
+ if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {\r
+ //\r
+ // Skip sub functions, this is not a multi function device\r
+ //\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ ZeroMem (&PciNode, sizeof (PciNode));\r
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;\r
+ PciNode.Header.SubType = HW_PCI_DP;\r
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+ PciNode.Device = Device;\r
+ PciNode.Function = Function;\r
+\r
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);\r
+\r
+ *BridgePrimaryBus = 0xffff;\r
+ *BridgeSubordinateBus = 0xffff;\r
+ return ReturnDevicePath;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciDevicePath (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN UINT64 Address,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Provides an EFI Device Path for a PCI device with the given PCI configuration space address.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. \r
+ Address - The PCI configuration space address of the device whose Device Path\r
+ is going to be returned. \r
+ PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.\r
+ Memory for the Device Path is allocated from the pool.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.\r
+ EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path. \r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+\r
+--*/\r
+{\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+ UINT16 PrimaryBus;\r
+ UINT16 SubordinateBus;\r
+ UINT8 Bus;\r
+ UINT8 Device;\r
+ UINT8 Func;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);\r
+ Device = (UINT8) (((UINT32) Address >> 16) & 0xff);\r
+ Func = (UINT8) (((UINT32) Address >> 8) & 0xff);\r
+\r
+ if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *PciDevicePath = Private->DevicePath;\r
+ PrimaryBus = Private->PrimaryBus;\r
+ SubordinateBus = Private->SubordinateBus;\r
+ do {\r
+ *PciDevicePath = AppendPciDevicePath (\r
+ Private,\r
+ Bus,\r
+ Device,\r
+ Func,\r
+ *PciDevicePath,\r
+ &PrimaryBus,\r
+ &SubordinateBus\r
+ );\r
+ if (*PciDevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } while (PrimaryBus != 0xffff);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMap (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_OPERATION_TYPE Operation,\r
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Provides the device-specific addresses needed to access system memory.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. \r
+ Operation - Indicates if the bus master is going to read or write to system memory. \r
+ HostAddress - The system memory address to map to the device.\r
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes\r
+ that were mapped.\r
+ DeviceAddress - The resulting map address for the bus master device to use to access the\r
+ hosts HostAddress.\r
+ Mapping - A resulting value to pass to Unmap().\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. \r
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. \r
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.\r
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address. \r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = Private->PciRootBridgeIo->Map (\r
+ Private->PciRootBridgeIo,\r
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+ (VOID *) (UINTN) (*HostAddress),\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoUnmap (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Mapping - The mapping value returned from Map().\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The range was unmapped.\r
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Status = Private->PciRootBridgeIo->Unmap (\r
+ Private->PciRootBridgeIo,\r
+ Mapping\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoAllocateBuffer (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Type - The type allocation to perform.\r
+ MemoryType - The type of memory to allocate, EfiBootServicesData or\r
+ EfiRuntimeServicesData.\r
+ Pages - The number of pages to allocate.\r
+ PhysicalAddress - A pointer to store the base address of the allocated range.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The requested memory pages were allocated.\r
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.\r
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.\r
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on\r
+ this platform.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS HostAddress;\r
+\r
+ HostAddress = *PhysicalAddress;\r
+\r
+ if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {\r
+ Type = AllocateMaxAddress;\r
+ HostAddress = MAX_COMMON_BUFFER;\r
+ }\r
+\r
+ Status = gBS->AllocatePages (\r
+ Type,\r
+ MemoryType,\r
+ Pages,\r
+ &HostAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+\r
+ *PhysicalAddress = HostAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoFlush (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Flushes any posted write data to the device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The buffers were flushed.\r
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ DEVICE_IO_PRIVATE_DATA *Private;\r
+\r
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoFreeBuffer (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN EFI_PHYSICAL_ADDRESS HostAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Frees pages that were allocated with AllocateBuffer().\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Pages - The number of pages to free.\r
+ HostAddress - The base address of the range to free.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The requested memory pages were freed.\r
+ EFI_NOT_FOUND - The requested memory pages were not allocated with\r
+ AllocateBuffer(). \r
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.\r
+\r
+--*/\r
+{\r
+ if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return gBS->FreePages (HostAddress, Pages);\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+\r
+ DeviceIo.h\r
+ \r
+Abstract:\r
+\r
+ Private Data definition for Device IO driver\r
+\r
+--*/\r
+\r
+#ifndef _DEVICE_IO_H\r
+#define _DEVICE_IO_H\r
+\r
+\r
+\r
+#define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 'e', 'v', 'I')\r
+\r
+#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_IO_PROTOCOL DeviceIo;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINT16 PrimaryBus;\r
+ UINT16 SubordinateBus;\r
+} DEVICE_IO_PRIVATE_DATA;\r
+\r
+#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)\r
+\r
+EFI_STATUS\r
+DeviceIoConstructor (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN UINT16 PrimaryBus,\r
+ IN UINT16 SubordinateBus\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize and install a Device IO protocol on a empty device path handle.\r
+\r
+Arguments:\r
+\r
+ Handle - Handle of PCI RootBridge IO instance\r
+ PciRootBridgeIo - PCI RootBridge IO instance\r
+ DevicePath - Device Path of PCI RootBridge IO instance\r
+ PrimaryBus - Primary Bus\r
+ SubordinateBus - Subordinate Bus\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - This driver is added to ControllerHandle. \r
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. \r
+ Others - This driver does not support this device.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMemRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading memory mapped I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device. \r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMemWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing memory mapped I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoIoRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoIoWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing I/O space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations.\r
+ Address - The base address of I/O operations.\r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciRead (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform reading PCI configuration space of device\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The destination buffer to store results.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was read from the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciWrite (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform writing PCI configuration space of device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO protocol instance. \r
+ Width - Width of I/O operations. \r
+ Address - The base address of I/O operations. \r
+ Count - The number of I/O operations to perform. \r
+ Bytes moves is Width size * Count, starting at Address. \r
+ Buffer - The source buffer of data to be written.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The data was written to the device.\r
+ EFI_INVALID_PARAMETER - Width is invalid.\r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoPciDevicePath (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN UINT64 Address,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Append a PCI device path node to another device path.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to EFI_DEVICE_IO_PROTOCOL. \r
+ Address - PCI bus,device, function.\r
+ PciDevicePath - PCI device path.\r
+\r
+Returns:\r
+ \r
+ Pointer to the appended PCI device path.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoMap (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_IO_OPERATION_TYPE Operation,\r
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Provides the device-specific addresses needed to access system memory.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. \r
+ Operation - Indicates if the bus master is going to read or write to system memory. \r
+ HostAddress - The system memory address to map to the device.\r
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes\r
+ that were mapped.\r
+ DeviceAddress - The resulting map address for the bus master device to use to access the\r
+ hosts HostAddress.\r
+ Mapping - A resulting value to pass to Unmap().\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. \r
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. \r
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.\r
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address. \r
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoUnmap (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Mapping - The mapping value returned from Map().\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The range was unmapped.\r
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoAllocateBuffer (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *HostAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Type - The type allocation to perform.\r
+ MemoryType - The type of memory to allocate, EfiBootServicesData or\r
+ EfiRuntimeServicesData.\r
+ Pages - The number of pages to allocate.\r
+ HostAddress - A pointer to store the base address of the allocated range.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The requested memory pages were allocated.\r
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.\r
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.\r
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on\r
+ this platform.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoFlush (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Flushes any posted write data to the device.\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The buffers were flushed.\r
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceIoFreeBuffer (\r
+ IN EFI_DEVICE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ IN EFI_PHYSICAL_ADDRESS HostAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Frees pages that were allocated with AllocateBuffer().\r
+\r
+Arguments:\r
+ \r
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.\r
+ Pages - The number of pages to free.\r
+ HostAddress - The base address of the range to free.\r
+\r
+Returns:\r
+ \r
+ EFI_SUCCESS - The requested memory pages were freed.\r
+ EFI_NOT_FOUND - The requested memory pages were not allocated with\r
+ AllocateBuffer(). \r
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridgeIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC AT PCI Root Bridge Io Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+\r
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;\r
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ return gCpuIo->Io.Read (\r
+ gCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
+ UserAddress,\r
+ Count,\r
+ UserBuffer\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ return gCpuIo->Io.Write (\r
+ gCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
+ UserAddress,\r
+ Count,\r
+ UserBuffer\r
+ );\r
+\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoGetIoPortMapping (\r
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
+ )\r
+/*++\r
+\r
+ Get the IO Port Mapping. For IA-32 it is always 0.\r
+ \r
+--*/\r
+{\r
+ *IoPortMapping = 0;\r
+ *MemoryPortMapping = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoPciRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Write,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ PCI_CONFIG_ACCESS_CF8 Pci;\r
+ PCI_CONFIG_ACCESS_CF8 PciAligned;\r
+ UINT32 InStride;\r
+ UINT32 OutStride;\r
+ UINTN PciData;\r
+ UINTN PciDataStride;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
+ UINT64 PciExpressRegAddr;\r
+ BOOLEAN UsePciExpressAccess;\r
+\r
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if ((Width & 0x03) >= EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ InStride = 1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+\r
+ UsePciExpressAccess = FALSE;\r
+\r
+ CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));\r
+\r
+ if (PciAddress.ExtendedRegister > 0xFF) {\r
+ //\r
+ // Check PciExpressBaseAddress\r
+ //\r
+ if ((PrivateData->PciExpressBaseAddress == 0) ||\r
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {\r
+ return EFI_UNSUPPORTED;\r
+ } else {\r
+ UsePciExpressAccess = TRUE;\r
+ }\r
+ } else {\r
+ if (PciAddress.ExtendedRegister != 0) {\r
+ Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;\r
+ } else {\r
+ Pci.Bits.Reg = PciAddress.Register;\r
+ }\r
+ //\r
+ // Note: We can also use PciExpress access here, if wanted.\r
+ //\r
+ }\r
+\r
+ if (!UsePciExpressAccess) {\r
+ Pci.Bits.Func = PciAddress.Function;\r
+ Pci.Bits.Dev = PciAddress.Device;\r
+ Pci.Bits.Bus = PciAddress.Bus;\r
+ Pci.Bits.Reserved = 0;\r
+ Pci.Bits.Enable = 1;\r
+\r
+ //\r
+ // PCI Config access are all 32-bit alligned, but by accessing the\r
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
+ // are possible on PCI.\r
+ //\r
+ // To read a byte of PCI config space you load 0xcf8 and \r
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff\r
+ //\r
+ PciDataStride = Pci.Bits.Reg & 0x03;\r
+\r
+ while (Count) {\r
+ PciAligned = Pci;\r
+ PciAligned.Bits.Reg &= 0xfc;\r
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;\r
+ EfiAcquireLock(&PrivateData->PciLock);\r
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);\r
+ if (Write) {\r
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);\r
+ } else {\r
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);\r
+ }\r
+ EfiReleaseLock(&PrivateData->PciLock);\r
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;\r
+ PciDataStride = (PciDataStride + InStride) % 4;\r
+ Pci.Bits.Reg += InStride;\r
+ Count -= 1;\r
+ }\r
+ } else {\r
+ //\r
+ // Access PCI-Express space by using memory mapped method.\r
+ //\r
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |\r
+ (PciAddress.Bus << 20) |\r
+ (PciAddress.Device << 15) |\r
+ (PciAddress.Function << 12);\r
+ if (PciAddress.ExtendedRegister != 0) {\r
+ PciExpressRegAddr += PciAddress.ExtendedRegister;\r
+ } else {\r
+ PciExpressRegAddr += PciAddress.Register;\r
+ }\r
+ while (Count) {\r
+ if (Write) {\r
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
+ } else {\r
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
+ }\r
+\r
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;\r
+ PciExpressRegAddr += InStride;\r
+ Count -= 1;\r
+ }\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+static\r
+VOID\r
+ScanPciBus(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,\r
+ VOID *Context\r
+ )\r
+ \r
+{\r
+ UINT16 Bus;\r
+ UINT16 Device;\r
+ UINT16 Func;\r
+ UINT64 Address;\r
+ PCI_TYPE00 PciHeader;\r
+\r
+ //\r
+ // Loop through all busses\r
+ //\r
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {\r
+ // \r
+ // Loop 32 devices per bus\r
+ //\r
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {\r
+ //\r
+ // Loop through 8 functions per device\r
+ //\r
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {\r
+\r
+ //\r
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device\r
+ //\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+ //\r
+ // Read the VendorID from this PCI Device's Confioguration Header\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);\r
+ \r
+ //\r
+ // If VendorId = 0xffff, there does not exist a device at this \r
+ // location. For each device, if there is any function on it, \r
+ // there must be 1 function at Function 0. So if Func = 0, there\r
+ // will be no more functions in the same device, so we can break\r
+ // loop to deal with the next device.\r
+ // \r
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {\r
+ break;\r
+ }\r
+ \r
+ if (PciHeader.Hdr.VendorId != 0xffff) {\r
+\r
+ //\r
+ // Read the HeaderType to determine if this is a multi-function device\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);\r
+\r
+ //\r
+ // Call the callback function for the device that was found\r
+ //\r
+ Callback(\r
+ IoDev, \r
+ MinBus, MaxBus,\r
+ MinDevice, MaxDevice,\r
+ MinFunc, MaxFunc,\r
+ Bus,\r
+ Device,\r
+ Func,\r
+ Context\r
+ );\r
+\r
+ //\r
+ // If this is not a multi-function device, we can leave the loop \r
+ // to deal with the next device.\r
+ //\r
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {\r
+ break;\r
+ }\r
+ } \r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static\r
+VOID\r
+CheckForRom (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ PCI_TYPE00 PciHeader;\r
+ PCI_TYPE01 *PciBridgeHeader;\r
+ UINT32 Register;\r
+ UINT32 RomBar;\r
+ UINT32 RomBarSize;\r
+ EFI_PHYSICAL_ADDRESS RomBuffer;\r
+ UINT32 MaxRomSize;\r
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;\r
+ PCI_DATA_STRUCTURE Pcir;\r
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;\r
+ BOOLEAN LastImage;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+ //\r
+ // Save the contents of the PCI Configuration Header\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
+\r
+ if (IS_PCI_BRIDGE(&PciHeader)) {\r
+\r
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);\r
+\r
+ //\r
+ // See if the PCI-PCI Bridge has its secondary interface enabled.\r
+ //\r
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {\r
+\r
+ //\r
+ // Disable the Prefetchable Memory Window\r
+ //\r
+ Register = 0x00000000;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);\r
+ Register = 0xffffffff;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);\r
+\r
+ //\r
+ // Program Memory Window to the PCI Root Bridge Memory Window\r
+ //\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);\r
+\r
+ //\r
+ // Enable the Memory decode for the PCI-PCI Bridge\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register |= 0x02;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+\r
+ //\r
+ // Recurse on the Secondary Bus Number\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ CheckForRom, Context\r
+ );\r
+ }\r
+ } else {\r
+\r
+ //\r
+ // Check if an Option ROM Register is present and save the Option ROM Window Register\r
+ //\r
+ RomBar = 0xffffffff;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+\r
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;\r
+\r
+ //\r
+ // Make sure the size of the ROM is between 0 and 16 MB\r
+ //\r
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {\r
+\r
+ //\r
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window\r
+ //\r
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;\r
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;\r
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {\r
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;\r
+ RomBar = RomBar + 1;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ RomBar = RomBar - 1;\r
+\r
+ //\r
+ // Enable the Memory decode for the PCI Device\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register |= 0x02;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+\r
+ //\r
+ // Follow the chain of images to determine the size of the Option ROM present\r
+ // Keep going until the last image is found by looking at the Indicator field\r
+ // or the size of an image is 0, or the size of all the images is bigger than the\r
+ // size of the window programmed into the PPB.\r
+ //\r
+ RomBarSize = 0;\r
+ do {\r
+\r
+ LastImage = TRUE;\r
+\r
+ ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));\r
+ IoDev->Mem.Read (\r
+ IoDev, \r
+ EfiPciWidthUint8, \r
+ RomBar + RomBarSize, \r
+ sizeof(EfiRomHeader),\r
+ &EfiRomHeader\r
+ );\r
+\r
+ Pcir.ImageLength = 0;\r
+\r
+ if (EfiRomHeader.Signature == 0xaa55) {\r
+\r
+ ZeroMem (&Pcir, sizeof(Pcir));\r
+ IoDev->Mem.Read (\r
+ IoDev, \r
+ EfiPciWidthUint8, \r
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset, \r
+ sizeof(Pcir),\r
+ &Pcir\r
+ );\r
+\r
+ if ((Pcir.Indicator & 0x80) == 0x00) {\r
+ LastImage = FALSE;\r
+ }\r
+\r
+ RomBarSize += Pcir.ImageLength * 512;\r
+ }\r
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);\r
+\r
+ if (RomBarSize > 0) {\r
+\r
+ //\r
+ // Allocate a memory buffer for the Option ROM contents.\r
+ //\r
+ Status = gBS->AllocatePages(\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ EFI_SIZE_TO_PAGES(RomBarSize),\r
+ &RomBuffer\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ //\r
+ // Copy the contents of the Option ROM to the memory buffer\r
+ //\r
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);\r
+\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),\r
+ &TempPciOptionRomDescriptors\r
+ );\r
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {\r
+ CopyMem(\r
+ TempPciOptionRomDescriptors, \r
+ mPciOptionRomTable.PciOptionRomDescriptors, \r
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)\r
+ );\r
+\r
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);\r
+ }\r
+\r
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; \r
+\r
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);\r
+\r
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;\r
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;\r
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;\r
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;\r
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;\r
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;\r
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;\r
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;\r
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;\r
+\r
+ mPciOptionRomTable.PciOptionRomCount++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Disable the Memory decode for the PCI-PCI Bridge\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register &= (~0x02);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Restore the PCI Configuration Header \r
+ //\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
+}\r
+\r
+static\r
+VOID\r
+SaveCommandRegister (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ UINTN Index;\r
+ UINT16 Command;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
+\r
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
+\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
+\r
+ //\r
+ // Clear the memory enable bit\r
+ //\r
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);\r
+\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);\r
+}\r
+\r
+static\r
+VOID\r
+RestoreCommandRegister (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ UINTN Index;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
+\r
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
+\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
+}\r
+\r
+EFI_STATUS\r
+ScanPciRootBridgeForRoms(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
+ )\r
+ \r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; \r
+ UINT16 MinBus;\r
+ UINT16 MaxBus;\r
+ UINT64 RootWindowBase;\r
+ UINT64 RootWindowLimit;\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;\r
+\r
+ if (mPciOptionRomTableInstalled == FALSE) {\r
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);\r
+ mPciOptionRomTableInstalled = TRUE;\r
+ }\r
+\r
+ Status = IoDev->Configuration(IoDev, &Descriptors);\r
+ if (EFI_ERROR (Status) || Descriptors == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ MinBus = 0xffff;\r
+ MaxBus = 0xffff;\r
+ RootWindowBase = 0;\r
+ RootWindowLimit = 0;\r
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ //\r
+ // Find bus range\r
+ //\r
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+ MinBus = (UINT16)Descriptors->AddrRangeMin;\r
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;\r
+ }\r
+ //\r
+ // Find memory descriptors that are not prefetchable\r
+ //\r
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {\r
+ //\r
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices\r
+ //\r
+ if (Descriptors->AddrRangeMax < 0x100000000) {\r
+ //\r
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB\r
+ //\r
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {\r
+ RootWindowBase = Descriptors->AddrRangeMin;\r
+ RootWindowLimit = Descriptors->AddrRangeMax;\r
+ }\r
+ }\r
+ }\r
+ Descriptors ++;\r
+ }\r
+\r
+ //\r
+ // Make sure a bus range was found\r
+ //\r
+ if (MinBus == 0xffff || MaxBus == 0xffff) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Make sure a non-prefetchable memory region was found\r
+ //\r
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Round the Base and Limit values to 1 MB boudaries\r
+ //\r
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;\r
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;\r
+\r
+ //\r
+ // Make sure that the size of the rounded window is greater than zero\r
+ //\r
+ if (RootWindowLimit <= RootWindowBase) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer to save the Command register from all the PCI devices\r
+ //\r
+ Context.CommandRegisterBuffer = NULL;\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),\r
+ &Context.CommandRegisterBuffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);\r
+\r
+ //\r
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MaxBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ SaveCommandRegister, &Context\r
+ );\r
+\r
+ //\r
+ // Recursively scan all the busses for PCI Option ROMs\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MinBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ CheckForRom, &Context\r
+ );\r
+\r
+ //\r
+ // Restore the Command register in all the PCI devices\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MaxBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ RestoreCommandRegister, &Context\r
+ );\r
+\r
+ //\r
+ // Free the buffer used to save all the Command register values\r
+ //\r
+ gBS->FreePool(Context.CommandRegisterBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005, 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
+Module Name:\r
+ PcatPciRootBridgeIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC AT PCI Root Bridge Io Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+#include "pci22.h"\r
+#include "SalProc.h"\r
+\r
+#include EFI_GUID_DEFINITION (SalSystemTable)\r
+\r
+//\r
+// Might be good to put this in an include file, but people may start\r
+// using it! They should always access the EFI abstraction that is\r
+// contained in this file. Just a little information hiding.\r
+//\r
+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )\r
+ \r
+// \r
+// Macro's with casts make this much easier to use and read.\r
+//\r
+#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))\r
+#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))\r
+#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))\r
+\r
+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \\r
+ ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )\r
+\r
+//\r
+// Local variables for performing SAL Proc calls\r
+//\r
+static PLABEL mSalProcPlabel;\r
+static CALL_SAL_PROC mGlobalSalProc;\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+ UINTN AlignMask;\r
+ UINTN Address;\r
+ PTR Buffer;\r
+ UINT16 Data16;\r
+ UINT32 Data32;\r
+ \r
+ \r
+ if ( UserBuffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ Address = (UINTN) UserAddress;\r
+ Buffer.buf = (UINT8 *)UserBuffer;\r
+\r
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Width & 0x03) == EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if ( Address & AlignMask ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ InStride = 1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+ Width = Width & 0x03;\r
+\r
+ Address += PrivateData->PhysicalIoBase;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+\r
+ switch (Width) {\r
+ case EfiPciWidthUint8:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ *Buffer.ui8 = PORT_TO_MEM8(Address);\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+\r
+ case EfiPciWidthUint16:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ if (Buffer.ui & 0x1) {\r
+ Data16 = PORT_TO_MEM16(Address);\r
+ *Buffer.ui8 = (UINT8)(Data16 & 0xff);\r
+ *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);\r
+ } else {\r
+ *Buffer.ui16 = PORT_TO_MEM16(Address);\r
+ }\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+\r
+ case EfiPciWidthUint32:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ if (Buffer.ui & 0x3) {\r
+ Data32 = PORT_TO_MEM32(Address);\r
+ *Buffer.ui8 = (UINT8)(Data32 & 0xff);\r
+ *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);\r
+ *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);\r
+ *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);\r
+ } else {\r
+ *Buffer.ui32 = PORT_TO_MEM32(Address);\r
+ }\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+ UINTN AlignMask;\r
+ UINTN Address;\r
+ PTR Buffer;\r
+ UINT16 Data16;\r
+ UINT32 Data32;\r
+\r
+ if ( UserBuffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ Address = (UINTN) UserAddress;\r
+ Buffer.buf = (UINT8 *)UserBuffer;\r
+\r
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Width & 0x03) == EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if ( Address & AlignMask ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ InStride = 1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+ Width = Width & 0x03;\r
+\r
+ Address += PrivateData->PhysicalIoBase;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+\r
+ switch (Width) {\r
+ case EfiPciWidthUint8:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ PORT_TO_MEM8(Address) = *Buffer.ui8;\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+\r
+ case EfiPciWidthUint16:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ if (Buffer.ui & 0x1) {\r
+ Data16 = *Buffer.ui8;\r
+ Data16 = Data16 | (*(Buffer.ui8+1) << 8);\r
+ PORT_TO_MEM16(Address) = Data16;\r
+ } else {\r
+ PORT_TO_MEM16(Address) = *Buffer.ui16;\r
+ }\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+ case EfiPciWidthUint32:\r
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {\r
+ MEMORY_FENCE();\r
+ if (Buffer.ui & 0x3) {\r
+ Data32 = *Buffer.ui8;\r
+ Data32 = Data32 | (*(Buffer.ui8+1) << 8);\r
+ Data32 = Data32 | (*(Buffer.ui8+2) << 16);\r
+ Data32 = Data32 | (*(Buffer.ui8+3) << 24);\r
+ PORT_TO_MEM32(Address) = Data32;\r
+ } else {\r
+ PORT_TO_MEM32(Address) = *Buffer.ui32;\r
+ }\r
+ MEMORY_FENCE();\r
+ }\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoGetIoPortMapping (\r
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
+ )\r
+/*++\r
+\r
+ Get the IO Port Map from the SAL System Table.\r
+ \r
+--*/\r
+{\r
+ SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;\r
+ SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations\r
+ //\r
+ *MemoryPortMapping = 0x8000000000000000;\r
+\r
+ Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // BugBug: Add code to test checksum on the Sal System Table\r
+ //\r
+ if (SalSystemTable->Entry0.Type != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry; \r
+ mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;\r
+ mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;\r
+\r
+ //\r
+ // The SalSystemTable pointer includes the Type 0 entry.\r
+ // The SalMemDesc is Type 1 so it comes next.\r
+ //\r
+ SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);\r
+ while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {\r
+ if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {\r
+ *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;\r
+ *IoPortMapping |= 0x8000000000000000;\r
+ return EFI_SUCCESS;\r
+ }\r
+ SalMemDesc++;\r
+ }\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoPciRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Write,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT UINT8 *UserBuffer\r
+ )\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN AlignMask;\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+ UINT64 Address;\r
+ DEFIO_PCI_ADDR *Defio;\r
+ PTR Buffer;\r
+ UINT32 Data32;\r
+ UINT16 Data16;\r
+ rArg Return;\r
+\r
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Width & 0x03) == EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if ( UserAddress & AlignMask ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ InStride = 1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+ Width = Width & 0x03;\r
+\r
+ Defio = (DEFIO_PCI_ADDR *)&UserAddress;\r
+\r
+ if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ Buffer.buf = (UINT8 *)UserBuffer;\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ Address = EFI_PCI_ADDRESS_IA64(\r
+ This->SegmentNumber, \r
+ Defio->Bus, \r
+ Defio->Device, \r
+ Defio->Function, \r
+ Defio->Register\r
+ );\r
+\r
+ //\r
+ // PCI Config access are all 32-bit alligned, but by accessing the\r
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
+ // are possible on PCI.\r
+ //\r
+ // SalProc takes care of reading the proper register depending on stride\r
+ //\r
+\r
+ EfiAcquireLock(&PrivateData->PciLock);\r
+\r
+ while (Count) {\r
+\r
+ if(Write) {\r
+\r
+ if (Buffer.ui & 0x3) {\r
+ Data32 = (*(Buffer.ui8+0) << 0);\r
+ Data32 |= (*(Buffer.ui8+1) << 8);\r
+ Data32 |= (*(Buffer.ui8+2) << 16);\r
+ Data32 |= (*(Buffer.ui8+3) << 24);\r
+ } else {\r
+ Data32 = *Buffer.ui32;\r
+ }\r
+\r
+ Return.p0 = -3;\r
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,\r
+ Address, 1 << Width, Data32, 0, 0, 0, 0);\r
+ \r
+ if(Return.p0) {\r
+ EfiReleaseLock(&PrivateData->PciLock);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ } else {\r
+\r
+ Return.p0 = -3;\r
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,\r
+ Address, 1 << Width, 0, 0, 0, 0, 0);\r
+\r
+ if(Return.p0) {\r
+ EfiReleaseLock(&PrivateData->PciLock);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ switch (Width) {\r
+ case EfiPciWidthUint8:\r
+ *Buffer.ui8 = (UINT8)Return.p1;\r
+ break;\r
+ case EfiPciWidthUint16:\r
+ if (Buffer.ui & 0x1) {\r
+ Data16 = (UINT16)Return.p1;\r
+ *(Buffer.ui8 + 0) = Data16 & 0xff;\r
+ *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;\r
+ } else {\r
+ *Buffer.ui16 = (UINT16)Return.p1;\r
+ }\r
+ break;\r
+ case EfiPciWidthUint32:\r
+ if (Buffer.ui & 0x3) {\r
+ Data32 = (UINT32)Return.p1;\r
+ *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);\r
+ *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);\r
+ *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);\r
+ *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);\r
+ } else {\r
+ *Buffer.ui32 = (UINT32)Return.p1;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ Address += InStride;\r
+ Buffer.buf += OutStride;\r
+ Count -= 1;\r
+ }\r
+ \r
+ EfiReleaseLock(&PrivateData->PciLock);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ScanPciRootBridgeForRoms(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
+ )\r
+ \r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridge.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC-AT PCI Root Bridge Controller\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+#include "DeviceIo.h"\r
+\r
+EFI_CPU_IO_PROTOCOL *gCpuIo;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcatPciRootBridge (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initializes the PCI Root Bridge Controller\r
+\r
+Arguments:\r
+ ImageHandle -\r
+ SystemTable -\r
+ \r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN PciSegmentIndex;\r
+ UINTN PciRootBridgeIndex;\r
+ UINTN PrimaryBusIndex;\r
+ UINTN NumberOfPciRootBridges;\r
+ UINTN NumberOfPciDevices;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ UINT16 VendorId;\r
+ PCI_TYPE01 PciConfigurationHeader;\r
+ UINT64 Address;\r
+ UINT64 Value;\r
+ UINT64 Base;\r
+ UINT64 Limit;\r
+\r
+ //\r
+ // Initialize gCpuIo now since the chipset init code requires it.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &gCpuIo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Initialize variables required to search all PCI segments for PCI devices\r
+ //\r
+ PciSegmentIndex = 0;\r
+ PciRootBridgeIndex = 0;\r
+ NumberOfPciRootBridges = 0;\r
+ PrimaryBusIndex = 0;\r
+\r
+ while (PciSegmentIndex <= PCI_MAX_SEGMENT) {\r
+\r
+ PrivateData = NULL;\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),\r
+ &PrivateData\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));\r
+\r
+ //\r
+ // Initialize the signature of the private data structure\r
+ //\r
+ PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;\r
+ PrivateData->Handle = NULL;\r
+ PrivateData->DevicePath = NULL;\r
+ InitializeListHead (&PrivateData->MapInfo);\r
+\r
+ //\r
+ // Initialize the PCI root bridge number and the bus range for that root bridge\r
+ //\r
+ PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;\r
+ PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex;\r
+ PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex;\r
+\r
+ PrivateData->IoBase = 0xffffffff;\r
+ PrivateData->MemBase = 0xffffffff;\r
+ PrivateData->Mem32Base = 0xffffffffffffffff;\r
+ PrivateData->Pmem32Base = 0xffffffffffffffff;\r
+ PrivateData->Mem64Base = 0xffffffffffffffff;\r
+ PrivateData->Pmem64Base = 0xffffffffffffffff;\r
+\r
+ //\r
+ // The default mechanism for performing PCI Configuration cycles is to \r
+ // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.\r
+ // IPF uses SAL calls to perform PCI COnfiguration cycles\r
+ //\r
+ PrivateData->PciAddress = 0xCF8;\r
+ PrivateData->PciData = 0xCFC;\r
+\r
+ //\r
+ // Get the physical I/O base for performing PCI I/O cycles\r
+ // For IA-32, this is always 0, because IA-32 has IN and OUT instructions\r
+ // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles\r
+ //\r
+ Status = PcatRootBridgeIoGetIoPortMapping (\r
+ &PrivateData->PhysicalIoBase, \r
+ &PrivateData->PhysicalMemoryBase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get PCI Express Base Address\r
+ //\r
+ PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);\r
+ if (PrivateData->PciExpressBaseAddress != 0) {\r
+ DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));\r
+ }\r
+\r
+ //\r
+ // Create a lock for performing PCI Configuration cycles\r
+ //\r
+ EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);\r
+\r
+ //\r
+ // Initialize the attributes for this PCI root bridge\r
+ //\r
+ PrivateData->Attributes = 0;\r
+\r
+ //\r
+ // Build the EFI Device Path Protocol instance for this PCI Root Bridge\r
+ //\r
+ Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge\r
+ //\r
+ Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Scan all the PCI devices on the primary bus of the PCI root bridge\r
+ //\r
+ for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+ \r
+ for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {\r
+\r
+ //\r
+ // Compute the PCI configuration address of the PCI device to probe\r
+ //\r
+ Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);\r
+\r
+ //\r
+ // Read the Vendor ID from the PCI Configuration Header\r
+ //\r
+ Status = PrivateData->Io.Pci.Read (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint16, \r
+ Address, \r
+ sizeof (VendorId), \r
+ &VendorId\r
+ );\r
+ if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {\r
+ //\r
+ // If the PCI Configuration Read fails, or a PCI device does not exist, then \r
+ // skip this entire PCI device\r
+ //\r
+ break;\r
+ }\r
+ if (VendorId == 0xffff) {\r
+ //\r
+ // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Read the entire PCI Configuration Header\r
+ //\r
+ Status = PrivateData->Io.Pci.Read (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint32, \r
+ Address, \r
+ sizeof (PciConfigurationHeader) / sizeof (UINT32), \r
+ &PciConfigurationHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If the entire PCI Configuration Header can not be read, then skip this entire PCI device\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Increment the number of PCI device found on the primary bus of the PCI root bridge\r
+ //\r
+ NumberOfPciDevices++;\r
+\r
+ //\r
+ // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header\r
+ //\r
+ if (PciConfigurationHeader.Hdr.Command & 0x20) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
+ }\r
+\r
+ //\r
+ // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number\r
+ //\r
+ if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {\r
+ //\r
+ // Get the Bus range that the PPB is decoding\r
+ //\r
+ if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {\r
+ //\r
+ // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's\r
+ // current subordinate bus number, then update the PCI root bridge's subordinate bus number \r
+ //\r
+ PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;\r
+ }\r
+\r
+ //\r
+ // Get the I/O range that the PPB is decoding\r
+ //\r
+ Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;\r
+ Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;\r
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r
+ if (Value == 0x01) {\r
+ Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);\r
+ Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);\r
+ }\r
+ if (Base < Limit) {\r
+ if (PrivateData->IoBase > Base) {\r
+ PrivateData->IoBase = Base;\r
+ }\r
+ if (PrivateData->IoLimit < Limit) {\r
+ PrivateData->IoLimit = Limit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the Memory range that the PPB is decoding\r
+ //\r
+ Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;\r
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r
+ if (Base < Limit) {\r
+ if (PrivateData->MemBase > Base) {\r
+ PrivateData->MemBase = Base;\r
+ }\r
+ if (PrivateData->MemLimit < Limit) {\r
+ PrivateData->MemLimit = Limit;\r
+ }\r
+ if (PrivateData->Mem32Base > Base) {\r
+ PrivateData->Mem32Base = Base;\r
+ }\r
+ if (PrivateData->Mem32Limit < Limit) {\r
+ PrivateData->Mem32Limit = Limit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the Prefetchable Memory range that the PPB is decoding\r
+ //\r
+ Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;\r
+ Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;\r
+ if (Value == 0x01) {\r
+ Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);\r
+ Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);\r
+ }\r
+ if (Base < Limit) {\r
+ if (PrivateData->MemBase > Base) {\r
+ PrivateData->MemBase = Base;\r
+ }\r
+ if (PrivateData->MemLimit < Limit) {\r
+ PrivateData->MemLimit = Limit;\r
+ }\r
+ if (Value == 0x00) {\r
+ if (PrivateData->Pmem32Base > Base) {\r
+ PrivateData->Pmem32Base = Base;\r
+ }\r
+ if (PrivateData->Pmem32Limit < Limit) {\r
+ PrivateData->Pmem32Limit = Limit;\r
+ }\r
+ }\r
+ if (Value == 0x01) {\r
+ if (PrivateData->Pmem64Base > Base) {\r
+ PrivateData->Pmem64Base = Base;\r
+ }\r
+ if (PrivateData->Pmem64Limit < Limit) {\r
+ PrivateData->Pmem64Limit = Limit;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Look at the PPB Configuration for legacy decoding attributes\r
+ //\r
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+ }\r
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Parse the BARs of the PCI device to determine what I/O Ranges,\r
+ // Memory Ranges, and Prefetchable Memory Ranges the device is decoding\r
+ //\r
+ if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r
+ Status = PcatPciRootBridgeParseBars (\r
+ PrivateData, \r
+ PciConfigurationHeader.Hdr.Command,\r
+ PrimaryBusIndex, \r
+ Device, \r
+ Function\r
+ );\r
+ }\r
+\r
+ //\r
+ // See if the PCI device is an IDE controller\r
+ //\r
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&\r
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
+ }\r
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
+ }\r
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
+ }\r
+ }\r
+\r
+ //\r
+ // See if the PCI device is a legacy VGA controller\r
+ //\r
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&\r
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
+ }\r
+\r
+ //\r
+ // See if the PCI device is a standard VGA controller\r
+ //\r
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&\r
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
+ }\r
+\r
+ //\r
+ // See if the PCI Device is a PCI - ISA or PCI - EISA \r
+ // or ISA_POSITIVIE_DECODE Bridge device\r
+ //\r
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {\r
+ if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||\r
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || \r
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+\r
+ if (PrivateData->MemBase > 0xa0000) {\r
+ PrivateData->MemBase = 0xa0000;\r
+ }\r
+ if (PrivateData->MemLimit < 0xbffff) {\r
+ PrivateData->MemLimit = 0xbffff;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // If this device is not a multi function device, then skip the rest of this PCI device\r
+ //\r
+ if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // After scanning all the PCI devices on the PCI root bridge's primary bus, update the \r
+ // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate\r
+ // bus number + 1.\r
+ //\r
+ PrimaryBusIndex = PrivateData->SubordinateBus + 1;\r
+\r
+ //\r
+ // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge\r
+ // exists.\r
+ //\r
+ if (NumberOfPciDevices > 0) {\r
+\r
+ //\r
+ // Adjust the I/O range used for bounds checking for the legacy decoding attributed\r
+ //\r
+ if (PrivateData->Attributes & 0x7f) {\r
+ PrivateData->IoBase = 0;\r
+ if (PrivateData->IoLimit < 0xffff) {\r
+ PrivateData->IoLimit = 0xffff;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Adjust the Memory range used for bounds checking for the legacy decoding attributed\r
+ //\r
+ if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {\r
+ if (PrivateData->MemBase > 0xa0000) {\r
+ PrivateData->MemBase = 0xa0000;\r
+ }\r
+ if (PrivateData->MemLimit < 0xbffff) {\r
+ PrivateData->MemLimit = 0xbffff;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Build ACPI descriptors for the resources on the PCI Root Bridge\r
+ //\r
+ Status = ConstructConfiguration(PrivateData);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Create the handle for this PCI Root Bridge \r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &PrivateData->Handle, \r
+ &gEfiDevicePathProtocolGuid,\r
+ PrivateData->DevicePath,\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ &PrivateData->Io,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Contruct DeviceIoProtocol\r
+ //\r
+ Status = DeviceIoConstructor (\r
+ PrivateData->Handle,\r
+ &PrivateData->Io,\r
+ PrivateData->DevicePath,\r
+ (UINT16)PrivateData->PrimaryBus,\r
+ (UINT16)PrivateData->SubordinateBus\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table\r
+ //\r
+ Status = ScanPciRootBridgeForRoms(&PrivateData->Io);\r
+\r
+ //\r
+ // Increment the index for the next PCI Root Bridge\r
+ //\r
+ PciRootBridgeIndex++;\r
+\r
+ } else {\r
+\r
+ //\r
+ // If no PCI Root Bridges were found on the current PCI segment, then exit\r
+ //\r
+ if (NumberOfPciRootBridges == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then\r
+ // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0\r
+ // Otherwise, the search is continued on the next PCI Root Bridge\r
+ //\r
+ if (PrimaryBusIndex > PCI_MAX_BUS) {\r
+ PciSegmentIndex++;\r
+ NumberOfPciRootBridges = 0;\r
+ PrimaryBusIndex = 0;\r
+ } else {\r
+ NumberOfPciRootBridges++;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Done:\r
+ //\r
+ // Clean up memory allocated for the PCI Root Bridge that was searched but not created.\r
+ //\r
+ if (PrivateData) {\r
+ if (PrivateData->DevicePath) {\r
+ gBS->FreePool(PrivateData->DevicePath);\r
+ }\r
+ gBS->FreePool (PrivateData);\r
+ }\r
+\r
+ //\r
+ // If no PCI Root Bridges were discovered, then return the error condition from scanning the\r
+ // first PCI Root Bridge\r
+ //\r
+ if (PciRootBridgeIndex == 0) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS \r
+ConstructConfiguration(\r
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+ \r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 NumConfig;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+ EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;\r
+\r
+ NumConfig = 0;\r
+ PrivateData->Configuration = NULL;\r
+\r
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
+ NumConfig++;\r
+ }\r
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
+ NumConfig++;\r
+ }\r
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
+ NumConfig++;\r
+ }\r
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
+ NumConfig++;\r
+ }\r
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
+ NumConfig++;\r
+ }\r
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
+ NumConfig++;\r
+ }\r
+\r
+ if ( NumConfig == 0 ) {\r
+\r
+ //\r
+ // If there is no resource request\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status )) {\r
+ return Status;\r
+ }\r
+\r
+ Configuration = PrivateData->Configuration;\r
+ \r
+ ZeroMem (\r
+ Configuration, \r
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) \r
+ );\r
+ \r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration++;\r
+\r
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ ConfigurationEnd->Checksum = 0;\r
+ }\r
+\r
+ //\r
+ // If there is at least one type of resource request,\r
+ // allocate a acpi resource node \r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status )) {\r
+ return Status;\r
+ }\r
+ \r
+ Configuration = PrivateData->Configuration;\r
+\r
+ ZeroMem (\r
+ Configuration, \r
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+ );\r
+\r
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
+ Configuration->SpecificFlag = 0; \r
+ Configuration->AddrRangeMin = PrivateData->PrimaryBus;\r
+ Configuration->AddrRangeMax = PrivateData->SubordinateBus;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ }\r
+ //\r
+ // Deal with io aperture\r
+ //\r
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+ Configuration->SpecificFlag = 1; //non ISA range\r
+ Configuration->AddrRangeMin = PrivateData->IoBase;\r
+ Configuration->AddrRangeMax = PrivateData->IoLimit;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // Deal with mem32 aperture\r
+ //\r
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Configuration->SpecificFlag = 0; //Nonprefechable\r
+ Configuration->AddrSpaceGranularity = 32; //32 bit\r
+ Configuration->AddrRangeMin = PrivateData->Mem32Base;\r
+ Configuration->AddrRangeMax = PrivateData->Mem32Limit;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ } \r
+\r
+ //\r
+ // Deal with Pmem32 aperture\r
+ //\r
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Configuration->SpecificFlag = 0x6; //prefechable\r
+ Configuration->AddrSpaceGranularity = 32; //32 bit\r
+ Configuration->AddrRangeMin = PrivateData->Pmem32Base;\r
+ Configuration->AddrRangeMax = PrivateData->Pmem32Limit;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // Deal with mem64 aperture\r
+ //\r
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Configuration->SpecificFlag = 0; //nonprefechable\r
+ Configuration->AddrSpaceGranularity = 64; //32 bit\r
+ Configuration->AddrRangeMin = PrivateData->Mem64Base;\r
+ Configuration->AddrRangeMax = PrivateData->Mem64Limit;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // Deal with Pmem64 aperture\r
+ //\r
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+ Configuration->SpecificFlag = 0x06; //prefechable\r
+ Configuration->AddrSpaceGranularity = 64; //32 bit\r
+ Configuration->AddrRangeMin = PrivateData->Pmem64Base;\r
+ Configuration->AddrRangeMax = PrivateData->Pmem64Limit;\r
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
+ Configuration++;\r
+ }\r
+\r
+ //\r
+ // put the checksum\r
+ //\r
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
+ ConfigurationEnd->Checksum = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS \r
+PcatPciRootBridgeBarExisted (\r
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
+ IN UINT64 Address,\r
+ OUT UINT32 *OriginalValue,\r
+ OUT UINT32 *Value\r
+ ) \r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 AllOnes;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // Preserve the original value\r
+ //\r
+ Status = PrivateData->Io.Pci.Read (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint32, \r
+ Address, \r
+ 1, \r
+ OriginalValue\r
+ );\r
+\r
+ //\r
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+ AllOnes = 0xffffffff;\r
+\r
+ Status = PrivateData->Io.Pci.Write (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint32, \r
+ Address, \r
+ 1, \r
+ &AllOnes\r
+ );\r
+ Status = PrivateData->Io.Pci.Read (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint32, \r
+ Address, \r
+ 1, \r
+ Value\r
+ );\r
+\r
+ //\r
+ //Write back the original value\r
+ //\r
+ Status = PrivateData->Io.Pci.Write (\r
+ &PrivateData->Io, \r
+ EfiPciWidthUint32, \r
+ Address, \r
+ 1, \r
+ OriginalValue\r
+ );\r
+\r
+ //\r
+ // Restore TPL to its original level\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ if ( *Value == 0 ) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcatPciRootBridgeParseBars (\r
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
+ IN UINT16 Command,\r
+ IN UINTN Bus,\r
+ IN UINTN Device,\r
+ IN UINTN Function\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 Address;\r
+ UINT32 OriginalValue;\r
+ UINT32 Value;\r
+ UINT32 OriginalUpperValue;\r
+ UINT32 UpperValue;\r
+ UINT64 Mask;\r
+ UINTN Offset;\r
+ UINT64 Base;\r
+ UINT64 Length;\r
+ UINT64 Limit;\r
+\r
+ for (Offset = 0x10; Offset < 0x28; Offset += 4) {\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
+ Status = PcatPciRootBridgeBarExisted (\r
+ PrivateData,\r
+ Address,\r
+ &OriginalValue,\r
+ &Value\r
+ );\r
+\r
+ if (!EFI_ERROR (Status )) {\r
+ if ( Value & 0x01 ) { \r
+ if (Command & 0x0001) {\r
+ //\r
+ //Device I/Os\r
+ //\r
+ Mask = 0xfffffffc;\r
+ Base = OriginalValue & Mask;\r
+ Length = ((~(Value & Mask)) & Mask) + 0x04;\r
+ if (!(Value & 0xFFFF0000)){\r
+ Length &= 0x0000FFFF;\r
+ }\r
+ Limit = Base + Length - 1;\r
+\r
+ if (Base < Limit) {\r
+ if (PrivateData->IoBase > Base) {\r
+ PrivateData->IoBase = (UINT32)Base;\r
+ }\r
+ if (PrivateData->IoLimit < Limit) {\r
+ PrivateData->IoLimit = (UINT32)Limit;\r
+ }\r
+ }\r
+ }\r
+ \r
+ } else {\r
+\r
+ if (Command & 0x0002) {\r
+\r
+ Mask = 0xfffffff0;\r
+ Base = OriginalValue & Mask;\r
+ Length = Value & Mask;\r
+ \r
+ if ((Value & 0x07) != 0x04) {\r
+ Length = ((~Length) + 1) & 0xffffffff;\r
+ } else {\r
+ Offset += 4; \r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
+\r
+ Status = PcatPciRootBridgeBarExisted (\r
+ PrivateData,\r
+ Address,\r
+ &OriginalUpperValue,\r
+ &UpperValue\r
+ );\r
+\r
+ Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);\r
+ Length = Length | LShiftU64((UINT64)UpperValue,32);\r
+ Length = (~Length) + 1;\r
+ }\r
+\r
+ Limit = Base + Length - 1;\r
+\r
+ if (Base < Limit) {\r
+ if (PrivateData->MemBase > Base) {\r
+ PrivateData->MemBase = Base;\r
+ }\r
+ if (PrivateData->MemLimit < Limit) {\r
+ PrivateData->MemLimit = Limit;\r
+ }\r
+\r
+ switch (Value &0x07) {\r
+ case 0x00: ////memory space; anywhere in 32 bit address space\r
+ if (Value & 0x08) {\r
+ if (PrivateData->Pmem32Base > Base) {\r
+ PrivateData->Pmem32Base = Base;\r
+ }\r
+ if (PrivateData->Pmem32Limit < Limit) {\r
+ PrivateData->Pmem32Limit = Limit;\r
+ }\r
+ } else {\r
+ if (PrivateData->Mem32Base > Base) {\r
+ PrivateData->Mem32Base = Base;\r
+ }\r
+ if (PrivateData->Mem32Limit < Limit) {\r
+ PrivateData->Mem32Limit = Limit;\r
+ }\r
+ }\r
+ break;\r
+ case 0x04: //memory space; anywhere in 64 bit address space\r
+ if (Value & 0x08) {\r
+ if (PrivateData->Pmem64Base > Base) {\r
+ PrivateData->Pmem64Base = Base;\r
+ }\r
+ if (PrivateData->Pmem64Limit < Limit) {\r
+ PrivateData->Pmem64Limit = Limit;\r
+ }\r
+ } else {\r
+ if (PrivateData->Mem64Base > Base) {\r
+ PrivateData->Mem64Base = Base;\r
+ }\r
+ if (PrivateData->Mem64Limit < Limit) {\r
+ PrivateData->Mem64Limit = Limit;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINT64\r
+GetPciExpressBaseAddressForRootBridge (\r
+ IN UINTN HostBridgeNumber,\r
+ IN UINTN RootBridgeNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This routine is to get PciExpress Base Address for this RootBridge\r
+\r
+Arguments:\r
+ HostBridgeNumber - The number of HostBridge\r
+ RootBridgeNumber - The number of RootBridge\r
+ \r
+Returns:\r
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge\r
+\r
+--*/\r
+{\r
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;\r
+ UINTN BufferSize;\r
+ UINT32 Index;\r
+ UINT32 Number;\r
+ VOID *HobList;\r
+ EFI_STATUS Status;\r
+ EFI_PEI_HOB_POINTERS GuidHob;\r
+\r
+ //\r
+ // Get Hob List from configuration table\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
+ if (EFI_ERROR (Status)) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Get PciExpressAddressInfo Hob\r
+ //\r
+ PciExpressBaseAddressInfo = NULL;\r
+ BufferSize = 0;\r
+ GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);\r
+ if (GuidHob.Raw != NULL) {\r
+ PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);\r
+ BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);\r
+ } else {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Search the PciExpress Base Address in the Hob for current RootBridge\r
+ //\r
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));\r
+ for (Index = 0; Index < Number; Index++) {\r
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&\r
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {\r
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do not find the PciExpress Base Address in the Hob\r
+ //\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridge.h\r
+\r
+Abstract:\r
+\r
+ The driver for the host to pci bridge (root bridge).\r
+\r
+--*/\r
+\r
+#ifndef _PCAT_PCI_ROOT_BRIDGE_H_\r
+#define _PCAT_PCI_ROOT_BRIDGE_H_\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/DeviceIo.h>\r
+#include <Protocol/CpuIo.h>\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/HobLib.h>\r
+\r
+#include <Guid/PciOptionRomTable.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/PciExpressBaseAddress.h>\r
+\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/Pci.h>\r
+//\r
+// Driver Instance Data Prototypes\r
+//\r
+#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE EFI_SIGNATURE_32('p', 'c', 'r', 'b')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ EFI_HANDLE Handle;\r
+ \r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;\r
+ EFI_CPU_IO_PROTOCOL *CpuIo;\r
+\r
+ UINT32 RootBridgeNumber;\r
+ UINT32 PrimaryBus;\r
+ UINT32 SubordinateBus;\r
+ \r
+ UINT64 MemBase; // Offsets host to bus memory addr.\r
+ UINT64 MemLimit; // Max allowable memory access\r
+ \r
+ UINT64 IoBase; // Offsets host to bus io addr.\r
+ UINT64 IoLimit; // Max allowable io access\r
+ \r
+ UINT64 PciAddress;\r
+ UINT64 PciData;\r
+ \r
+ UINT64 PhysicalMemoryBase;\r
+ UINT64 PhysicalIoBase;\r
+ \r
+ EFI_LOCK PciLock;\r
+ \r
+ UINT64 Attributes;\r
+ \r
+ UINT64 Mem32Base;\r
+ UINT64 Mem32Limit;\r
+ UINT64 Pmem32Base;\r
+ UINT64 Pmem32Limit;\r
+ UINT64 Mem64Base;\r
+ UINT64 Mem64Limit;\r
+ UINT64 Pmem64Base;\r
+ UINT64 Pmem64Limit;\r
+\r
+ UINT64 PciExpressBaseAddress;\r
+\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
+\r
+ LIST_ENTRY MapInfo;\r
+} PCAT_PCI_ROOT_BRIDGE_INSTANCE;\r
+\r
+//\r
+// Driver Instance Data Macros\r
+//\r
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \\r
+ CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)\r
+\r
+#define VOLATILE volatile\r
+//\r
+// Private data types\r
+//\r
+typedef union {\r
+ UINT8 VOLATILE *buf;\r
+ UINT8 VOLATILE *ui8;\r
+ UINT16 VOLATILE *ui16;\r
+ UINT32 VOLATILE *ui32;\r
+ UINT64 VOLATILE *ui64;\r
+ UINTN VOLATILE ui;\r
+} PTR;\r
+\r
+typedef struct {\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;\r
+ UINTN NumberOfBytes;\r
+ UINTN NumberOfPages;\r
+ EFI_PHYSICAL_ADDRESS HostAddress;\r
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;\r
+} MAP_INFO;\r
+\r
+typedef struct {\r
+ LIST_ENTRY Link;\r
+ MAP_INFO * Map; \r
+} MAP_INFO_INSTANCE;\r
+\r
+typedef\r
+VOID\r
+(*EFI_PCI_BUS_SCAN_CALLBACK) (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *Context\r
+ );\r
+\r
+typedef struct {\r
+ UINT16 *CommandRegisterBuffer;\r
+ UINT32 PpbMemoryWindow; \r
+} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;\r
+\r
+//\r
+// Driver Protocol Constructor Prototypes\r
+//\r
+EFI_STATUS \r
+ConstructConfiguration(\r
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData\r
+ );\r
+\r
+EFI_STATUS\r
+PcatPciRootBridgeParseBars (\r
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
+ IN UINT16 Command,\r
+ IN UINTN Bus,\r
+ IN UINTN Device,\r
+ IN UINTN Function\r
+ );\r
+\r
+EFI_STATUS\r
+ScanPciRootBridgeForRoms(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeDevicePathConstructor (\r
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,\r
+ IN UINTN RootBridgeNumber,\r
+ IN BOOLEAN IsPciExpress\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoConstructor (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,\r
+ IN UINTN SegmentNumber\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoGetIoPortMapping (\r
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoPciRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Write,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ );\r
+\r
+UINT64\r
+GetPciExpressBaseAddressForRootBridge (\r
+ IN UINTN HostBridgeNumber,\r
+ IN UINTN RootBridgeNumber\r
+ );\r
+\r
+//\r
+// Driver entry point prototype\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcatPciRootBridge (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+extern EFI_CPU_IO_PROTOCOL *gCpuIo;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridgeDevicePath.c\r
+ \r
+Abstract:\r
+\r
+ EFI PCAT PCI Root Bridge Device Path Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+\r
+//\r
+// Static device path declarations for this driver.\r
+//\r
+\r
+typedef struct {\r
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
+\r
+static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {\r
+ {\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_DP,\r
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),\r
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),\r
+ EISA_PNP_ID(0x0A03),\r
+ 0\r
+ },\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ END_DEVICE_PATH_LENGTH,\r
+ 0\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+PcatRootBridgeDevicePathConstructor (\r
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,\r
+ IN UINTN RootBridgeNumber,\r
+ IN BOOLEAN IsPciExpress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Construct the device path protocol\r
+\r
+Arguments:\r
+\r
+ Protocol - protocol to initialize\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ ACPI_HID_DEVICE_PATH *AcpiDevicePath;\r
+ \r
+ *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));\r
+\r
+ AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);\r
+ \r
+ AcpiDevicePath->UID = (UINT32)RootBridgeNumber;\r
+\r
+ if (IsPciExpress) {\r
+ AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridgeIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC AT PCI Root Bridge Io Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+\r
+//\r
+// Protocol Member Function Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollMem ( \r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollIo ( \r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoCopyMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 DestAddress,\r
+ IN UINT64 SrcAddress,\r
+ IN UINTN Count\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported,\r
+ OUT UINT64 *Attributes\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength \r
+ ); \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ );\r
+\r
+//\r
+// Private Function Prototypes\r
+//\r
+STATIC \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN BOOLEAN InStrideFlag,\r
+ IN PTR In,\r
+ IN BOOLEAN OutStrideFlag,\r
+ OUT PTR Out\r
+ );\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoConstructor (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,\r
+ IN UINTN SegmentNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Contruct the Pci Root Bridge Io protocol\r
+\r
+Arguments:\r
+\r
+ Protocol - protocol to initialize\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ Protocol->ParentHandle = NULL;\r
+\r
+ Protocol->PollMem = PcatRootBridgeIoPollMem;\r
+ Protocol->PollIo = PcatRootBridgeIoPollIo;\r
+\r
+ Protocol->Mem.Read = PcatRootBridgeIoMemRead;\r
+ Protocol->Mem.Write = PcatRootBridgeIoMemWrite;\r
+\r
+ Protocol->Io.Read = PcatRootBridgeIoIoRead;\r
+ Protocol->Io.Write = PcatRootBridgeIoIoWrite;\r
+\r
+ Protocol->CopyMem = PcatRootBridgeIoCopyMem;\r
+\r
+ Protocol->Pci.Read = PcatRootBridgeIoPciRead;\r
+ Protocol->Pci.Write = PcatRootBridgeIoPciWrite;\r
+\r
+ Protocol->Map = PcatRootBridgeIoMap;\r
+ Protocol->Unmap = PcatRootBridgeIoUnmap;\r
+\r
+ Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;\r
+ Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer;\r
+\r
+ Protocol->Flush = PcatRootBridgeIoFlush;\r
+\r
+ Protocol->GetAttributes = PcatRootBridgeIoGetAttributes;\r
+ Protocol->SetAttributes = PcatRootBridgeIoSetAttributes;\r
+\r
+ Protocol->Configuration = PcatRootBridgeIoConfiguration;\r
+\r
+ Protocol->SegmentNumber = (UINT32)SegmentNumber;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollMem ( \r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINTN Remainder;\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ } \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ( Delay != 0 ) {\r
+\r
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);\r
+ if ( Remainder !=0 ) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+ \r
+ while ( NumberOfTicks ) {\r
+\r
+ gBS->Stall (10);\r
+\r
+ Status = This->Mem.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ }\r
+ \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPollIo ( \r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINT64 Mask,\r
+ IN UINT64 Value,\r
+ IN UINT64 Delay,\r
+ OUT UINT64 *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 NumberOfTicks;\r
+ UINTN Remainder;\r
+\r
+ if (Result == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // No matter what, always do a single poll.\r
+ //\r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ } \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Delay != 0) {\r
+\r
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);\r
+ if ( Remainder !=0 ) {\r
+ NumberOfTicks += 1;\r
+ }\r
+ NumberOfTicks += 1;\r
+ \r
+ while ( NumberOfTicks ) {\r
+\r
+ gBS->Stall(10);\r
+ \r
+ Status = This->Io.Read (This, Width, Address, 1, Result);\r
+ if ( EFI_ERROR(Status) ) {\r
+ return Status;\r
+ }\r
+ \r
+ if ( (*Result & Mask) == Value ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NumberOfTicks -= 1;\r
+ }\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+BOOLEAN\r
+PcatRootBridgeMemAddressValid (\r
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
+ IN UINT64 Address\r
+ )\r
+{\r
+ if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {\r
+ return TRUE;\r
+ }\r
+ if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN AlignMask;\r
+ PTR In;\r
+ PTR Out;\r
+\r
+ if ( Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if (Address & AlignMask) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Address += PrivateData->PhysicalMemoryBase;\r
+\r
+ In.buf = Buffer;\r
+ Out.buf = (VOID *)(UINTN) Address;\r
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ UINTN AlignMask;\r
+ PTR In;\r
+ PTR Out;\r
+\r
+ if ( Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AlignMask = (1 << (Width & 0x03)) - 1;\r
+ if (Address & AlignMask) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Address += PrivateData->PhysicalMemoryBase;\r
+\r
+ In.buf = (VOID *)(UINTN) Address;\r
+ Out.buf = Buffer;\r
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);\r
+ }\r
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoCopyMem (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 DestAddress,\r
+ IN UINT64 SrcAddress,\r
+ IN UINTN Count\r
+ )\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Direction;\r
+ UINTN Stride;\r
+ UINTN Index;\r
+ UINT64 Result;\r
+\r
+ if (Width < 0 || Width > EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+\r
+ if (DestAddress == SrcAddress) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Stride = (UINTN)1 << Width;\r
+\r
+ Direction = TRUE;\r
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {\r
+ Direction = FALSE;\r
+ SrcAddress = SrcAddress + (Count-1) * Stride;\r
+ DestAddress = DestAddress + (Count-1) * Stride;\r
+ }\r
+\r
+ for (Index = 0;Index < Count;Index++) {\r
+ Status = PcatRootBridgeIoMemRead (\r
+ This,\r
+ Width,\r
+ SrcAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = PcatRootBridgeIoMemWrite (\r
+ This,\r
+ Width,\r
+ DestAddress,\r
+ 1,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Direction) {\r
+ SrcAddress += Stride;\r
+ DestAddress += Stride;\r
+ } else {\r
+ SrcAddress -= Stride;\r
+ DestAddress -= Stride;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoPciWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,\r
+ IN VOID *HostAddress,\r
+ IN OUT UINTN *NumberOfBytes,\r
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
+ OUT VOID **Mapping\r
+ )\r
+\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ MAP_INFO *MapInfo;\r
+ MAP_INFO_INSTANCE *MapInstance;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+\r
+ if ( HostAddress == NULL || NumberOfBytes == NULL || \r
+ DeviceAddress == NULL || Mapping == NULL ) {\r
+ \r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ //\r
+ // Initialize the return values to their defaults\r
+ //\r
+ *Mapping = NULL;\r
+\r
+ //\r
+ // Make sure that Operation is valid\r
+ //\r
+ if (Operation < 0 || Operation >= EfiPciOperationMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Most PCAT like chipsets can not handle performing DMA above 4GB.\r
+ // If any part of the DMA transfer being mapped is above 4GB, then\r
+ // map the DMA transfer to a buffer below 4GB.\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
+ if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {\r
+\r
+ //\r
+ // Common Buffer operations can not be remapped. If the common buffer\r
+ // if above 4GB, then it is not possible to generate a mapping, so return \r
+ // an error.\r
+ //\r
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
+ // called later.\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof(MAP_INFO), \r
+ &MapInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Return a pointer to the MAP_INFO structure in Mapping\r
+ //\r
+ *Mapping = MapInfo;\r
+\r
+ //\r
+ // Initialize the MAP_INFO structure\r
+ //\r
+ MapInfo->Operation = Operation;\r
+ MapInfo->NumberOfBytes = *NumberOfBytes;\r
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);\r
+ MapInfo->HostAddress = PhysicalAddress;\r
+ MapInfo->MappedHostAddress = 0x00000000ffffffff;\r
+\r
+ //\r
+ // Allocate a buffer below 4GB to map the transfer to.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress, \r
+ EfiBootServicesData, \r
+ MapInfo->NumberOfPages,\r
+ &MapInfo->MappedHostAddress\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ gBS->FreePool (MapInfo);\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If this is a read operation from the Bus Master's point of view,\r
+ // then copy the contents of the real buffer into the mapped buffer\r
+ // so the Bus Master can read the contents of the real buffer.\r
+ //\r
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {\r
+ CopyMem (\r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress, \r
+ (VOID *)(UINTN)MapInfo->HostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+\r
+ Status =gBS->AllocatePool (\r
+ EfiBootServicesData, \r
+ sizeof(MAP_INFO_INSTANCE), \r
+ &MapInstance\r
+ ); \r
+ if (EFI_ERROR(Status)) {\r
+ gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);\r
+ gBS->FreePool (MapInfo);\r
+ *NumberOfBytes = 0;\r
+ return Status;\r
+ }\r
+\r
+ MapInstance->Map=MapInfo;\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+ InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);\r
+ \r
+ //\r
+ // The DeviceAddress is the address of the maped buffer below 4GB\r
+ //\r
+ *DeviceAddress = MapInfo->MappedHostAddress;\r
+ } else {\r
+ //\r
+ // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress\r
+ //\r
+ *DeviceAddress = PhysicalAddress;\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoUnmap (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+\r
+{\r
+ MAP_INFO *MapInfo;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ LIST_ENTRY *Link;\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+ //\r
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.\r
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.\r
+ //\r
+ if (Mapping != NULL) {\r
+ //\r
+ // Get the MAP_INFO structure from Mapping\r
+ //\r
+ MapInfo = (MAP_INFO *)Mapping;\r
+\r
+ for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {\r
+ if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)\r
+ break;\r
+ }\r
+\r
+ if (Link == &PrivateData->MapInfo) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ RemoveEntryList(Link);\r
+ ((MAP_INFO_INSTANCE*)Link)->Map = NULL;\r
+ gBS->FreePool((MAP_INFO_INSTANCE*)Link);\r
+\r
+ //\r
+ // If this is a write operation from the Bus Master's point of view,\r
+ // then copy the contents of the mapped buffer into the real buffer\r
+ // so the processor can read the contents of the real buffer.\r
+ //\r
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {\r
+ CopyMem (\r
+ (VOID *)(UINTN)MapInfo->HostAddress, \r
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ }\r
+\r
+ //\r
+ // Free the mapped buffer and the MAP_INFO structure.\r
+ //\r
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);\r
+ gBS->FreePool (Mapping);\r
+ }\r
+\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoAllocateBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN Pages,\r
+ OUT VOID **HostAddress,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+\r
+ //\r
+ // Validate Attributes\r
+ //\r
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check for invalid inputs\r
+ //\r
+ if (HostAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData\r
+ //\r
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Limit allocations to memory below 4GB\r
+ //\r
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);\r
+\r
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFreeBuffer (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINTN Pages,\r
+ OUT VOID *HostAddress\r
+ )\r
+\r
+{\r
+\r
+ if( HostAddress == NULL ){\r
+ return EFI_INVALID_PARAMETER;\r
+ } \r
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoFlush (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This\r
+ )\r
+\r
+{\r
+ //\r
+ // Perform a fence operation to make sure all memory operations are flushed\r
+ //\r
+ MemoryFence();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoGetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT UINT64 *Supported, OPTIONAL\r
+ OUT UINT64 *Attributes\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+\r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ if (Attributes == NULL && Supported == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Supported is an OPTIONAL parameter. See if it is NULL\r
+ //\r
+ if (Supported) {\r
+ //\r
+ // This is a generic driver for a PC-AT class system. It does not have any\r
+ // chipset specific knowlegde, so none of the attributes can be set or \r
+ // cleared. Any attempt to set attribute that are already set will succeed, \r
+ // and any attempt to set an attribute that is not supported will fail.\r
+ //\r
+ *Supported = PrivateData->Attributes;\r
+ }\r
+\r
+ //\r
+ // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized\r
+ //\r
+ \r
+ if (Attributes) {\r
+ *Attributes = PrivateData->Attributes;\r
+ }\r
+ \r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoSetAttributes (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN UINT64 Attributes,\r
+ IN OUT UINT64 *ResourceBase,\r
+ IN OUT UINT64 *ResourceLength \r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ //\r
+ // This is a generic driver for a PC-AT class system. It does not have any\r
+ // chipset specific knowlegde, so none of the attributes can be set or \r
+ // cleared. Any attempt to set attribute that are already set will succeed, \r
+ // and any attempt to set an attribute that is not supported will fail.\r
+ //\r
+ if (Attributes & (~PrivateData->Attributes)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoConfiguration (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ OUT VOID **Resources\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ *Resources = PrivateData->Configuration;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Internal function\r
+//\r
+\r
+STATIC \r
+EFI_STATUS\r
+EFIAPI\r
+PcatRootBridgeIoMemRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINTN Count,\r
+ IN BOOLEAN InStrideFlag,\r
+ IN PTR In,\r
+ IN BOOLEAN OutStrideFlag,\r
+ OUT PTR Out\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Private service to provide the memory read/write\r
+\r
+Arguments:\r
+\r
+ Width of the Memory Access\r
+ Count of the number of accesses to perform\r
+\r
+Returns:\r
+\r
+ Status\r
+\r
+ EFI_SUCCESS - Successful transaction\r
+ EFI_INVALID_PARAMETER - Unsupported width and address combination\r
+\r
+--*/\r
+{\r
+ UINTN Stride;\r
+ UINTN InStride;\r
+ UINTN OutStride;\r
+\r
+\r
+ Width = Width & 0x03;\r
+ Stride = (UINTN)1 << Width;\r
+ InStride = InStrideFlag ? Stride : 0;\r
+ OutStride = OutStrideFlag ? Stride : 0;\r
+\r
+ //\r
+ // Loop for each iteration and move the data\r
+ //\r
+ switch (Width) {\r
+ case EfiPciWidthUint8:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui8 = *Out.ui8;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ case EfiPciWidthUint16:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui16 = *Out.ui16;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ case EfiPciWidthUint32:\r
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {\r
+ MemoryFence();\r
+ *In.ui32 = *Out.ui32;\r
+ MemoryFence();\r
+ }\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2005 - 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
+# Module Name:\r
+#\r
+# Abstract:\r
+#\r
+#--*/\r
+\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PcatPciRootBridge\r
+ FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = InitializePcatPciRootBridge\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ DuetPkg/DuetPkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiLib\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ DebugLib\r
+ BaseMemoryLib\r
+ DevicePathLib\r
+ HobLib\r
+\r
+[Sources.common]\r
+ PcatPciRootBridge.h\r
+ PcatPciRootBridge.c\r
+ PcatPciRootBridgeDevicePath.c\r
+ PcatPciRootBridgeIo.c\r
+ DeviceIo.h\r
+ DeviceIo.c\r
+\r
+[Sources.ia32]\r
+ ia32\PcatIo.c\r
+ \r
+[Sources.x64]\r
+ x64\PcatIo.c\r
+\r
+[Sources.ipf]\r
+ Ipf\PcatIo.c\r
+\r
+[Protocols]\r
+ gEfiPciRootBridgeIoProtocolGuid\r
+ gEfiDeviceIoProtocolGuid\r
+ gEfiPciExpressBaseAddressGuid\r
+ gEfiCpuIoProtocolGuid\r
+\r
+[Guids]\r
+ gEfiPciOptionRomTableGuid
\ No newline at end of file
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 - 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
+Module Name:\r
+ PcatPciRootBridgeIo.c\r
+ \r
+Abstract:\r
+\r
+ EFI PC AT PCI Root Bridge Io Protocol\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "PcatPciRootBridge.h"\r
+\r
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;\r
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoIoRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ return gCpuIo->Io.Read (\r
+ gCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
+ UserAddress,\r
+ Count,\r
+ UserBuffer\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoIoWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ return gCpuIo->Io.Write (\r
+ gCpuIo,\r
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
+ UserAddress,\r
+ Count,\r
+ UserBuffer\r
+ );\r
+\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoGetIoPortMapping (\r
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
+ )\r
+/*++\r
+\r
+ Get the IO Port Mapping. For IA-32 it is always 0.\r
+ \r
+--*/\r
+{\r
+ *IoPortMapping = 0;\r
+ *MemoryPortMapping = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PcatRootBridgeIoPciRW (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
+ IN BOOLEAN Write,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 UserAddress,\r
+ IN UINTN Count,\r
+ IN OUT VOID *UserBuffer\r
+ )\r
+{\r
+ PCI_CONFIG_ACCESS_CF8 Pci;\r
+ PCI_CONFIG_ACCESS_CF8 PciAligned;\r
+ UINT32 InStride;\r
+ UINT32 OutStride;\r
+ UINTN PciData;\r
+ UINTN PciDataStride;\r
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
+ UINT64 PciExpressRegAddr;\r
+ BOOLEAN UsePciExpressAccess;\r
+\r
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ if ((Width & 0x03) >= EfiPciWidthUint64) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
+\r
+ InStride = 1 << (Width & 0x03);\r
+ OutStride = InStride;\r
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
+ InStride = 0;\r
+ }\r
+\r
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {\r
+ OutStride = 0;\r
+ }\r
+\r
+ UsePciExpressAccess = FALSE;\r
+\r
+ EfiCopyMem (&PciAddress, &UserAddress, sizeof(UINT64));\r
+\r
+ if (PciAddress.ExtendedRegister > 0xFF) {\r
+ //\r
+ // Check PciExpressBaseAddress\r
+ //\r
+ if ((PrivateData->PciExpressBaseAddress == 0) ||\r
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {\r
+ return EFI_UNSUPPORTED;\r
+ } else {\r
+ UsePciExpressAccess = TRUE;\r
+ }\r
+ } else {\r
+ if (PciAddress.ExtendedRegister != 0) {\r
+ Pci.Reg = PciAddress.ExtendedRegister & 0xFF;\r
+ } else {\r
+ Pci.Reg = PciAddress.Register;\r
+ }\r
+ //\r
+ // Note: We can also use PciExpress access here, if wanted.\r
+ //\r
+ }\r
+\r
+ if (!UsePciExpressAccess) {\r
+ Pci.Func = PciAddress.Function;\r
+ Pci.Dev = PciAddress.Device;\r
+ Pci.Bus = PciAddress.Bus;\r
+ Pci.Reserved = 0;\r
+ Pci.Enable = 1;\r
+\r
+ //\r
+ // PCI Config access are all 32-bit alligned, but by accessing the\r
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
+ // are possible on PCI.\r
+ //\r
+ // To read a byte of PCI config space you load 0xcf8 and \r
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff\r
+ //\r
+ PciDataStride = Pci.Reg & 0x03;\r
+\r
+ while (Count) {\r
+ PciAligned = Pci;\r
+ PciAligned.Reg &= 0xfc;\r
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;\r
+ EfiAcquireLock(&PrivateData->PciLock);\r
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);\r
+ if (Write) {\r
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);\r
+ } else {\r
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);\r
+ }\r
+ EfiReleaseLock(&PrivateData->PciLock);\r
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;\r
+ PciDataStride = (PciDataStride + InStride) % 4;\r
+ Pci.Reg += InStride;\r
+ Count -= 1;\r
+ }\r
+ } else {\r
+ //\r
+ // Access PCI-Express space by using memory mapped method.\r
+ //\r
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |\r
+ (PciAddress.Bus << 20) |\r
+ (PciAddress.Device << 15) |\r
+ (PciAddress.Function << 12);\r
+ if (PciAddress.ExtendedRegister != 0) {\r
+ PciExpressRegAddr += PciAddress.ExtendedRegister;\r
+ } else {\r
+ PciExpressRegAddr += PciAddress.Register;\r
+ }\r
+ while (Count) {\r
+ if (Write) {\r
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
+ } else {\r
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
+ }\r
+\r
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;\r
+ PciExpressRegAddr += InStride;\r
+ Count -= 1;\r
+ }\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+static\r
+VOID\r
+ScanPciBus(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,\r
+ VOID *Context\r
+ )\r
+ \r
+{\r
+ UINT16 Bus;\r
+ UINT16 Device;\r
+ UINT16 Func;\r
+ UINT64 Address;\r
+ PCI_TYPE00 PciHeader;\r
+\r
+ //\r
+ // Loop through all busses\r
+ //\r
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {\r
+ // \r
+ // Loop 32 devices per bus\r
+ //\r
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {\r
+ //\r
+ // Loop through 8 functions per device\r
+ //\r
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {\r
+\r
+ //\r
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device\r
+ //\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+ //\r
+ // Read the VendorID from this PCI Device's Confioguration Header\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);\r
+ \r
+ //\r
+ // If VendorId = 0xffff, there does not exist a device at this \r
+ // location. For each device, if there is any function on it, \r
+ // there must be 1 function at Function 0. So if Func = 0, there\r
+ // will be no more functions in the same device, so we can break\r
+ // loop to deal with the next device.\r
+ // \r
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {\r
+ break;\r
+ }\r
+ \r
+ if (PciHeader.Hdr.VendorId != 0xffff) {\r
+\r
+ //\r
+ // Read the HeaderType to determine if this is a multi-function device\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);\r
+\r
+ //\r
+ // Call the callback function for the device that was found\r
+ //\r
+ Callback(\r
+ IoDev, \r
+ MinBus, MaxBus,\r
+ MinDevice, MaxDevice,\r
+ MinFunc, MaxFunc,\r
+ Bus,\r
+ Device,\r
+ Func,\r
+ Context\r
+ );\r
+\r
+ //\r
+ // If this is not a multi-function device, we can leave the loop \r
+ // to deal with the next device.\r
+ //\r
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {\r
+ break;\r
+ }\r
+ } \r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static\r
+VOID\r
+CheckForRom (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ PCI_TYPE00 PciHeader;\r
+ PCI_TYPE01 *PciBridgeHeader;\r
+ UINT32 Register;\r
+ UINT32 RomBar;\r
+ UINT32 RomBarSize;\r
+ EFI_PHYSICAL_ADDRESS RomBuffer;\r
+ UINT32 MaxRomSize;\r
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;\r
+ PCI_DATA_STRUCTURE Pcir;\r
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;\r
+ BOOLEAN LastImage;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+ //\r
+ // Save the contents of the PCI Configuration Header\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
+\r
+ if (IS_PCI_BRIDGE(&PciHeader)) {\r
+\r
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);\r
+\r
+ //\r
+ // See if the PCI-PCI Bridge has its secondary interface enabled.\r
+ //\r
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {\r
+\r
+ //\r
+ // Disable the Prefetchable Memory Window\r
+ //\r
+ Register = 0x00000000;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);\r
+ Register = 0xffffffff;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);\r
+\r
+ //\r
+ // Program Memory Window to the PCI Root Bridge Memory Window\r
+ //\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);\r
+\r
+ //\r
+ // Enable the Memory decode for the PCI-PCI Bridge\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register |= 0x02;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+\r
+ //\r
+ // Recurse on the Secondary Bus Number\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ CheckForRom, Context\r
+ );\r
+ }\r
+ } else {\r
+\r
+ //\r
+ // Check if an Option ROM Register is present and save the Option ROM Window Register\r
+ //\r
+ RomBar = 0xffffffff;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+\r
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;\r
+\r
+ //\r
+ // Make sure the size of the ROM is between 0 and 16 MB\r
+ //\r
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {\r
+\r
+ //\r
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window\r
+ //\r
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;\r
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;\r
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {\r
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;\r
+ RomBar = RomBar + 1;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
+ RomBar = RomBar - 1;\r
+\r
+ //\r
+ // Enable the Memory decode for the PCI Device\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register |= 0x02;\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+\r
+ //\r
+ // Follow the chain of images to determine the size of the Option ROM present\r
+ // Keep going until the last image is found by looking at the Indicator field\r
+ // or the size of an image is 0, or the size of all the images is bigger than the\r
+ // size of the window programmed into the PPB.\r
+ //\r
+ RomBarSize = 0;\r
+ do {\r
+\r
+ LastImage = TRUE;\r
+\r
+ EfiZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));\r
+ IoDev->Mem.Read (\r
+ IoDev, \r
+ EfiPciWidthUint8, \r
+ RomBar + RomBarSize, \r
+ sizeof(EfiRomHeader),\r
+ &EfiRomHeader\r
+ );\r
+\r
+ Pcir.ImageLength = 0;\r
+\r
+ if (EfiRomHeader.Signature == 0xaa55) {\r
+\r
+ EfiZeroMem (&Pcir, sizeof(Pcir));\r
+ IoDev->Mem.Read (\r
+ IoDev, \r
+ EfiPciWidthUint8, \r
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset, \r
+ sizeof(Pcir),\r
+ &Pcir\r
+ );\r
+\r
+ if ((Pcir.Indicator & 0x80) == 0x00) {\r
+ LastImage = FALSE;\r
+ }\r
+\r
+ RomBarSize += Pcir.ImageLength * 512;\r
+ }\r
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);\r
+\r
+ if (RomBarSize > 0) {\r
+\r
+ //\r
+ // Allocate a memory buffer for the Option ROM contents.\r
+ //\r
+ Status = gBS->AllocatePages(\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ EFI_SIZE_TO_PAGES(RomBarSize),\r
+ &RomBuffer\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ //\r
+ // Copy the contents of the Option ROM to the memory buffer\r
+ //\r
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);\r
+\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),\r
+ &TempPciOptionRomDescriptors\r
+ );\r
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {\r
+ EfiCopyMem(\r
+ TempPciOptionRomDescriptors, \r
+ mPciOptionRomTable.PciOptionRomDescriptors, \r
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)\r
+ );\r
+\r
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);\r
+ }\r
+\r
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; \r
+\r
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);\r
+\r
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;\r
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;\r
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;\r
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;\r
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;\r
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;\r
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;\r
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;\r
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;\r
+\r
+ mPciOptionRomTable.PciOptionRomCount++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Disable the Memory decode for the PCI-PCI Bridge\r
+ //\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ Register &= (~0x02);\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Restore the PCI Configuration Header \r
+ //\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
+}\r
+\r
+static\r
+VOID\r
+SaveCommandRegister (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ UINTN Index;\r
+ UINT16 Command;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
+\r
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
+\r
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
+\r
+ //\r
+ // Clear the memory enable bit\r
+ //\r
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);\r
+\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);\r
+}\r
+\r
+static\r
+VOID\r
+RestoreCommandRegister (\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
+ UINT16 MinBus,\r
+ UINT16 MaxBus,\r
+ UINT16 MinDevice,\r
+ UINT16 MaxDevice,\r
+ UINT16 MinFunc,\r
+ UINT16 MaxFunc,\r
+ UINT16 Bus,\r
+ UINT16 Device,\r
+ UINT16 Func,\r
+ IN VOID *VoidContext\r
+ )\r
+\r
+{\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
+ UINT64 Address;\r
+ UINTN Index;\r
+\r
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
+\r
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
+\r
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
+\r
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
+}\r
+\r
+EFI_STATUS\r
+ScanPciRootBridgeForRoms(\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
+ )\r
+ \r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; \r
+ UINT16 MinBus;\r
+ UINT16 MaxBus;\r
+ UINT64 RootWindowBase;\r
+ UINT64 RootWindowLimit;\r
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;\r
+\r
+ if (mPciOptionRomTableInstalled == FALSE) {\r
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);\r
+ mPciOptionRomTableInstalled = TRUE;\r
+ }\r
+\r
+ Status = IoDev->Configuration(IoDev, &Descriptors);\r
+ if (EFI_ERROR (Status) || Descriptors == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ MinBus = 0xffff;\r
+ MaxBus = 0xffff;\r
+ RootWindowBase = 0;\r
+ RootWindowLimit = 0;\r
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+ //\r
+ // Find bus range\r
+ //\r
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+ MinBus = (UINT16)Descriptors->AddrRangeMin;\r
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;\r
+ }\r
+ //\r
+ // Find memory descriptors that are not prefetchable\r
+ //\r
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {\r
+ //\r
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices\r
+ //\r
+ if (Descriptors->AddrRangeMax < 0x100000000) {\r
+ //\r
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB\r
+ //\r
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {\r
+ RootWindowBase = Descriptors->AddrRangeMin;\r
+ RootWindowLimit = Descriptors->AddrRangeMax;\r
+ }\r
+ }\r
+ }\r
+ Descriptors ++;\r
+ }\r
+\r
+ //\r
+ // Make sure a bus range was found\r
+ //\r
+ if (MinBus == 0xffff || MaxBus == 0xffff) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Make sure a non-prefetchable memory region was found\r
+ //\r
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Round the Base and Limit values to 1 MB boudaries\r
+ //\r
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;\r
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;\r
+\r
+ //\r
+ // Make sure that the size of the rounded window is greater than zero\r
+ //\r
+ if (RootWindowLimit <= RootWindowBase) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer to save the Command register from all the PCI devices\r
+ //\r
+ Context.CommandRegisterBuffer = NULL;\r
+ Status = gBS->AllocatePool(\r
+ EfiBootServicesData,\r
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),\r
+ &Context.CommandRegisterBuffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);\r
+\r
+ //\r
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MaxBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ SaveCommandRegister, &Context\r
+ );\r
+\r
+ //\r
+ // Recursively scan all the busses for PCI Option ROMs\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MinBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ CheckForRom, &Context\r
+ );\r
+\r
+ //\r
+ // Restore the Command register in all the PCI devices\r
+ //\r
+ ScanPciBus(\r
+ IoDev,\r
+ MinBus, MaxBus, \r
+ 0, PCI_MAX_DEVICE, \r
+ 0, PCI_MAX_FUNC, \r
+ RestoreCommandRegister, &Context\r
+ );\r
+\r
+ //\r
+ // Free the buffer used to save all the Command register values\r
+ //\r
+ gBS->FreePool(Context.CommandRegisterBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 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
+Module Name:\r
+\r
+ RtPlatformStatusCode.c \r
+ \r
+Abstract:\r
+\r
+ Contains NT32 specific implementations required to use status codes.\r
+\r
+--*/\r
+\r
+//\r
+// Statements that include other files.\r
+//\r
+#include "Tiano.h"\r
+#include "EfiCommonLib.h"\r
+#include "EfiRuntimeLib.h"\r
+#include "EfiStatusCode.h"\r
+#include "EfiHobLib.h"\r
+#include "RtMemoryStatusCodeLib.h"\r
+#include "BsDataHubStatusCodeLib.h"\r
+\r
+//\r
+// Consumed protocols\r
+//\r
+#include EFI_ARCH_PROTOCOL_CONSUMER (StatusCode)\r
+\r
+//\r
+// GUID definitions\r
+//\r
+#include EFI_GUID_DEFINITION (Hob)\r
+\r
+//\r
+// Globals only work at BootService Time. NOT at Runtime!\r
+//\r
+EFI_REPORT_STATUS_CODE mPeiReportStatusCode;\r
+\r
+//\r
+// Function implementations\r
+//\r
+EFI_RUNTIMESERVICE\r
+EFI_STATUS\r
+EFIAPI\r
+RtPlatformReportStatusCode (\r
+ IN EFI_STATUS_CODE_TYPE CodeType,\r
+ IN EFI_STATUS_CODE_VALUE Value,\r
+ IN UINT32 Instance,\r
+ IN EFI_GUID * CallerId,\r
+ IN EFI_STATUS_CODE_DATA * Data OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Call all status code listeners in the MonoStatusCode.\r
+\r
+Arguments:\r
+\r
+ Same as ReportStatusCode service\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS Always returns success.\r
+\r
+--*/\r
+{\r
+ RtMemoryReportStatusCode (CodeType, Value, Instance, CallerId, Data);\r
+ if (EfiAtRuntime ()) {\r
+ //\r
+ // For now all we do is post code at runtime\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BsDataHubReportStatusCode (CodeType, Value, Instance, CallerId, Data);\r
+\r
+ //\r
+ // Call back into PEI to get status codes. This is because SecMain contains\r
+ // status code that reports to Win32.\r
+ //\r
+ if (mPeiReportStatusCode != NULL) {\r
+ return mPeiReportStatusCode (CodeType, Value, Instance, CallerId, Data);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_BOOTSERVICE\r
+VOID\r
+EFIAPI\r
+RtPlatformInitializeStatusCode (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize the status code listeners.\r
+\r
+Arguments:\r
+\r
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *HobList;\r
+ VOID *Pointer;\r
+\r
+ RtMemoryInitializeStatusCode (ImageHandle, SystemTable);\r
+ BsDataHubInitializeStatusCode (ImageHandle, SystemTable);\r
+\r
+ //\r
+ // Play any prior status codes to the data hub.\r
+ //\r
+ PlaybackStatusCodes (BsDataHubReportStatusCode);\r
+\r
+ //\r
+ // If PEI has a ReportStatusCode callback find it and use it before StdErr\r
+ // is connected.\r
+ //\r
+ mPeiReportStatusCode = NULL;\r
+\r
+ Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = GetNextGuidHob (&HobList, &gEfiStatusCodeRuntimeProtocolGuid, &Pointer, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ mPeiReportStatusCode = (EFI_REPORT_STATUS_CODE) (*(UINTN *) Pointer);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+#/*++\r
+#\r
+# Copyright (c) 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
+# Module Name:\r
+#\r
+# RtPlatformStatusCode.inf\r
+#\r
+# Abstract:\r
+#\r
+# Library selecting the listeners for the platform\r
+#\r
+#--*/\r
+\r
+[defines]\r
+BASE_NAME = RtPlatformStatusCodeLib\r
+COMPONENT_TYPE = LIBRARY\r
+\r
+[sources.common]\r
+ RtPlatformStatusCode.c\r
+\r
+[includes.common]\r
+ $(EDK_SOURCE)\Foundation\Framework\r
+ $(EDK_SOURCE)\Foundation\r
+ $(EDK_SOURCE)\Foundation\Efi\r
+ .\r
+ $(EDK_SOURCE)\Sample\Platform\Generic\RuntimeDxe\StatusCode\Lib\Include\r
+ $(EDK_SOURCE)\Foundation\Include\r
+ $(EDK_SOURCE)\Foundation\Efi\Include\r
+ $(EDK_SOURCE)\Foundation\Framework\Include\r
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard\r
+ $(EDK_SOURCE)\Foundation\Core\Dxe\r
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include\r
+\r
+[libraries.common]\r
+ HobLib\r
+ RtMemoryStatusCodeLib\r
+ BsDataHubStatusCodeLib\r
+\r
+[nmake.common]\r