diff options
author | klu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524> | 2008-04-17 05:48:13 +0000 |
---|---|---|
committer | klu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524> | 2008-04-17 05:48:13 +0000 |
commit | c69dd9dfad3eb97d5e21f520f3ba35d102ec4cfa (patch) | |
tree | e6065a748931519b3cf11d9811c0beef9c80d58e | |
parent | fcf03596d10de53e45292bd9eb4767a8ddc344ed (diff) | |
download | edk2-platforms-c69dd9dfad3eb97d5e21f520f3ba35d102ec4cfa.tar.xz |
Porting Duet module from EDKI to EDKII
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5076 6f19259b-4bc3-4df7-8a09-765794883524
77 files changed, 26415 insertions, 13 deletions
diff --git a/DuetPkg/BootSector/BootSector.inf b/DuetPkg/BootSector/BootSector.inf new file mode 100644 index 0000000000..149d4e49f6 --- /dev/null +++ b/DuetPkg/BootSector/BootSector.inf @@ -0,0 +1,30 @@ +[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootSector
+ FILE_GUID = A36495C1-C205-414e-B71F-4BE3476D699C
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DuetPkg/DuetPkg.dec
+
+[Sources]
+ bootsect.asm
+ bs16.asm
+ bs32.asm
+ Gpt.asm
+ Mbr.asm
+ Start.asm
+ Start16.asm
+ Start32.asm
+ Efi32.asm
+
+[BuildOptions.common]
+ #MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
+ MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
+ MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
+ MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+ MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny
diff --git a/DuetPkg/BootSector/FILE.LST b/DuetPkg/BootSector/FILE.LST new file mode 100644 index 0000000000..f0f47a42a9 --- /dev/null +++ b/DuetPkg/BootSector/FILE.LST @@ -0,0 +1,26 @@ +IA32
+====
+FAT12 FAT16 FAT32
+bootsect.asm bs16.asm bs32.asm
+start.asm start16.asm start32.asm
+ \ | /
+ \ | /
+ efi32.asm
+
+X64
+===
+FAT12 FAT16 FAT32
+bootsect.asm bs16.asm bs32.asm
+start64.asm st16_64.asm st32_64.asm
+ \ | /
+ \ | /
+ efi64.asm
+
+MBR
+===
+Mbr.asm
+
+
+GPT
+===
+Gpt.asm
\ No newline at end of file diff --git a/DuetPkg/BootSector/Gpt.asm b/DuetPkg/BootSector/Gpt.asm new file mode 100644 index 0000000000..15f91f5f49 --- /dev/null +++ b/DuetPkg/BootSector/Gpt.asm @@ -0,0 +1,294 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* gpt.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+; .dosseg
+ .stack
+ .486p
+ .code
+
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+; ****************************************************************************
+; Code loaded by BIOS at 0x0000:0x7C00
+; ****************************************************************************
+
+ org 0h
+Start:
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ lea si, cs:[StartString]
+ mov cx, 10
+ mov di, 160
+ rep movsw
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+; ****************************************************************************
+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
+; ****************************************************************************
+ xor ax, ax ; AX = 0x0000
+ mov bx, 07c00h ; BX = 0x7C00
+ mov bp, 0600h ; BP = 0x0600
+ mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
+ mov cx, 0200h ; CX = 0x0200
+ sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
+ lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
+ lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
+ mov ss, ax ; SS = 0x0000
+ mov sp, bx ; SP = 0x7C00
+ mov es,ax ; ES = 0x0000
+ mov ds,ax ; DS = 0x0000
+ push ax ; PUSH 0x0000
+ push di ; PUSH 0x0600 + Offset(RelocatedStart)
+ cld ; Clear the direction flag
+ rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
+ retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
+
+; ****************************************************************************
+; Code relocated to 0x0000:0x0600
+; ****************************************************************************
+
+RelocatedStart:
+; ****************************************************************************
+; Get Driver Parameters to 0x0000:0x7BFC
+; ****************************************************************************
+ xor ax,ax ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+; ****************************************************************************
+; Read GPT Header from hard disk to 0x0000:0x0800
+; ****************************************************************************
+ xor ax, ax
+ mov es, ax ; Read to 0x0000:0x0800
+ mov di, 0800h ; Read to 0x0000:0x0800
+ mov eax, 1 ; Read LBA #1
+ mov edx, 0 ; Read LBA #1
+ mov bx, 1 ; Read 1 Block
+ push es
+ call ReadBlocks
+ pop es
+
+; ****************************************************************************
+; Read Target GPT Entry from hard disk to 0x0000:0x0A00
+; ****************************************************************************
+ cmp dword ptr es:[di], 020494645h ; Check for "EFI "
+ jne BadGpt
+ cmp dword ptr es:[di + 4], 054524150h ; Check for "PART"
+ jne BadGpt
+ cmp dword ptr es:[di + 8], 000010000h ; Check Revision - 0x10000
+ jne BadGpt
+
+ mov eax, dword ptr es:[di + 84] ; EAX = SizeOfPartitionEntry
+ mul byte ptr [bp+GptPartitionIndicator] ; EAX = SizeOfPartitionEntry * GptPartitionIndicator
+ mov edx, eax ; EDX = SizeOfPartitionEntry * GptPartitionIndicator
+ shr eax, BLOCK_SHIFT ; EAX = (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE
+ and edx, BLOCK_MASK ; EDX = Targer PartitionEntryLBA Offset
+ ; = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
+ push edx
+ mov ecx, dword ptr es:[di + 72] ; ECX = PartitionEntryLBA (Low)
+ mov ebx, dword ptr es:[di + 76] ; EBX = PartitionEntryLBA (High)
+ add eax, ecx ; EAX = Target PartitionEntryLBA (Low)
+ ; = (PartitionEntryLBA +
+ ; (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE)
+ adc edx, ebx ; EDX = Target PartitionEntryLBA (High)
+
+ mov di, 0A00h ; Read to 0x0000:0x0A00
+ mov bx, 1 ; Read 1 Block
+ push es
+ call ReadBlocks
+ pop es
+
+; ****************************************************************************
+; Read Target DBR from hard disk to 0x0000:0x7C00
+; ****************************************************************************
+ pop edx ; EDX = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE
+ add di, dx ; DI = Targer PartitionEntryLBA Offset
+ cmp dword ptr es:[di], 0C12A7328h ; Check for EFI System Partition "C12A7328-F81F-11d2-BA4B-00A0C93EC93B"
+ jne BadGpt
+ cmp dword ptr es:[di + 4], 011d2F81Fh ;
+ jne BadGpt
+ cmp dword ptr es:[di + 8], 0A0004BBAh ;
+ jne BadGpt
+ cmp dword ptr es:[di + 0ch], 03BC93EC9h ;
+ jne BadGpt
+
+ mov eax, dword ptr es:[di + 32] ; EAX = StartingLBA (Low)
+ mov edx, dword ptr es:[di + 36] ; EDX = StartingLBA (High)
+ mov di, 07C00h ; Read to 0x0000:0x7C00
+ mov bx, 1 ; Read 1 Block
+ call ReadBlocks
+
+; ****************************************************************************
+; Transfer control to BootSector - Jump to 0x0000:0x7C00
+; ****************************************************************************
+ xor ax, ax
+ push ax ; PUSH 0x0000
+ mov di, 07c00h
+ push di ; PUSH 0x7C00
+ retf ; JMP 0x0000:0x7C00
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; EDX:EAX = Start LBA
+; BX = Number of Blocks to Read (must < 127)
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; si = DiskAddressPacket
+
+ReadBlocks:
+ pushad
+ push ds
+ xor cx, cx
+ mov ds, cx
+ mov bp, 0600h ; bp = 0x600
+ lea si, [bp + OFFSET AddressPacket] ; DS:SI = Disk Address Packet
+ mov BYTE PTR ds:[si+2],bl ; 02 = Number Of Block transfered
+ mov WORD PTR ds:[si+4],di ; 04 = Transfer Buffer Offset
+ mov WORD PTR ds:[si+6],es ; 06 = Transfer Buffer Segment
+ mov DWORD PTR ds:[si+8],eax ; 08 = Starting LBA (Low)
+ mov DWORD PTR ds:[si+0ch],edx ; 0C = Starting LBA (High)
+ mov ah, 42h ; ah = Function 42
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ int 13h
+ jc BadGpt
+ pop ds
+ popad
+ ret
+
+; ****************************************************************************
+; Address Packet used by ReadBlocks
+; ****************************************************************************
+AddressPacket:
+ db 10h ; Size of address packet
+ db 00h ; Reserved. Must be 0
+ db 01h ; Read blocks at a time (To be fixed each times)
+ db 00h ; Reserved. Must be 0
+ dw 0000h ; Destination Address offset (To be fixed each times)
+ dw 0000h ; Destination Address segment (To be fixed each times)
+AddressPacketLba:
+ dd 0h, 0h ; Start LBA (To be fixed each times)
+AddressPacketEnd:
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+
+BadGpt:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 060h
+ mov ds, ax
+ lea si, cs:[ErrorString]
+ mov cx, 10
+ mov di, 320
+ rep movsw
+Halt:
+ jmp Halt
+
+StartString:
+ db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; PhysicalDrive - Used to indicate which disk to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B6h
+PhysicalDrive db 80h
+
+; ****************************************************************************
+; GptPartitionIndicator - Used to indicate which GPT partition to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B7h
+GptPartitionIndicator db 0
+
+; ****************************************************************************
+; Unique MBR signature
+; ****************************************************************************
+ org 01B8h
+ db 'DUET'
+
+; ****************************************************************************
+; Unknown
+; ****************************************************************************
+ org 01BCh
+ dw 0
+
+; ****************************************************************************
+; PMBR Entry - Can be patched by tool
+; ****************************************************************************
+ org 01BEh
+ db 0 ; Boot Indicator
+ db 0ffh ; Start Header
+ db 0ffh ; Start Sector
+ db 0ffh ; Start Track
+ db 0eeh ; OS Type
+ db 0ffh ; End Header
+ db 0ffh ; End Sector
+ db 0ffh ; End Track
+ dd 1 ; Starting LBA
+ dd 0FFFFFFFFh ; End LBA
+
+ org 01CEh
+ dd 0, 0, 0, 0
+ org 01DEh
+ dd 0, 0, 0, 0
+ org 01EEh
+ dd 0, 0, 0, 0
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01FEh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/Makefile b/DuetPkg/BootSector/Makefile new file mode 100644 index 0000000000..fc24f37677 --- /dev/null +++ b/DuetPkg/BootSector/Makefile @@ -0,0 +1,276 @@ +
+#
+# Platform Macro Definition
+#
+PLATFORM_NAME = DuetPkg
+PLATFORM_GUID = 199E24E0-0989-42aa-87F2-611A8C397E72
+PLATFORM_VERSION = 0.3
+PLATFORM_RELATIVE_DIR = DuetPkg
+PLATFORM_DIR = $(WORKSPACE)\DuetPkg
+PLATFORM_OUTPUT_DIR = Build\DuetPkg
+
+#
+# Module Macro Definition
+#
+MODULE_NAME = BootSector
+MODULE_GUID = 2410F0DF-D915-4137-BD04-AAB6BA4C50E0
+MODULE_VERSION = 1.0
+MODULE_TYPE = USER_DEFINED
+MODULE_FILE_BASE_NAME = BootSector
+BASE_NAME = $(MODULE_NAME)
+MODULE_RELATIVE_DIR = DuetPkg\BootSector
+MODULE_DIR = $(WORKSPACE)\DuetPkg\BootSector
+
+#
+# Build Configuration Macro Definition
+#
+ARCH = IA32
+TOOLCHAIN_TAG = MYTOOLS
+TARGET = DEBUG
+BASETOOLS_DIR=m:\tree\working\BaseTools\Bin\Win32
+
+#
+# Build Directory Macro Definition
+#
+# PLATFORM_BUILD_DIR = m:\tree\working\Build\DuetPkg\DEBUG_MYTOOLS
+BUILD_DIR = $(WORKSPACE)\Build\DuetPkg\DEBUG_MYTOOLS
+BIN_DIR = $(BUILD_DIR)\IA32
+LIB_DIR = $(BIN_DIR)
+MODULE_BUILD_DIR = $(BUILD_DIR)\IA32\DuetPkg\BootSector\BootSector
+OUTPUT_DIR = $(MODULE_BUILD_DIR)\OUTPUT
+DEBUG_DIR = $(MODULE_BUILD_DIR)\DEBUG
+DEST_DIR_OUTPUT = $(OUTPUT_DIR)
+DEST_DIR_DEBUG = $(DEBUG_DIR)
+
+#
+# Default Tools Flags Macro Definition (from tools_def.txt by default)
+#
+DEFAULT_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
+DEFAULT_SLINK_FLAGS = /nologo /LTCG
+DEFAULT_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs8192 /Gy /D UNICODE /O1ib2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm
+DEFAULT_APP_FLAGS = /nologo /E /TC
+DEFAULT_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FIAutoGen.h
+DEFAULT_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4086 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /MACHINE:I386 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:CONSOLE /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /PDB:$(DEBUG_DIR)/$(BASE_NAME).pdb
+DEFAULT_ASM_FLAGS = /nologo /c /WX /W3 /coff /Cx /Zd /Zi
+DEFAULT_TIANO_FLAGS =
+DEFAULT_MAKE_FLAGS = /nologo
+DEFAULT_ASMLINK_FLAGS = /nologo /tiny
+DEFAULT_ASL_FLAGS =
+
+
+#
+# Platform Tools Flags Macro Definition (from platform description file)
+#
+PLATFORM_PP_FLAGS =
+PLATFORM_SLINK_FLAGS =
+PLATFORM_CC_FLAGS =
+PLATFORM_APP_FLAGS =
+PLATFORM_VFRPP_FLAGS =
+PLATFORM_DLINK_FLAGS =
+PLATFORM_ASM_FLAGS =
+PLATFORM_TIANO_FLAGS =
+PLATFORM_MAKE_FLAGS =
+PLATFORM_ASMLINK_FLAGS =
+PLATFORM_ASL_FLAGS =
+
+
+#
+# Module Tools Flags Macro Definition (from platform/module description file)
+#
+MODULE_PP_FLAGS =
+MODULE_SLINK_FLAGS =
+MODULE_CC_FLAGS =
+MODULE_APP_FLAGS =
+MODULE_VFRPP_FLAGS =
+MODULE_DLINK_FLAGS =
+MODULE_ASM_FLAGS =
+MODULE_TIANO_FLAGS =
+MODULE_MAKE_FLAGS =
+MODULE_ASMLINK_FLAGS =
+MODULE_ASL_FLAGS =
+
+
+#
+# Tools Flag Macro
+#
+PP_FLAGS = $(DEFAULT_PP_FLAGS) $(PLATFORM_PP_FLAGS) $(MODULE_PP_FLAGS)
+SLINK_FLAGS = $(DEFAULT_SLINK_FLAGS) $(PLATFORM_SLINK_FLAGS) $(MODULE_SLINK_FLAGS)
+CC_FLAGS = $(DEFAULT_CC_FLAGS) $(PLATFORM_CC_FLAGS) $(MODULE_CC_FLAGS)
+APP_FLAGS = $(DEFAULT_APP_FLAGS) $(PLATFORM_APP_FLAGS) $(MODULE_APP_FLAGS)
+VFRPP_FLAGS = $(DEFAULT_VFRPP_FLAGS) $(PLATFORM_VFRPP_FLAGS) $(MODULE_VFRPP_FLAGS)
+DLINK_FLAGS = $(DEFAULT_DLINK_FLAGS) $(PLATFORM_DLINK_FLAGS) $(MODULE_DLINK_FLAGS)
+ASM_FLAGS = $(DEFAULT_ASM_FLAGS) $(PLATFORM_ASM_FLAGS) $(MODULE_ASM_FLAGS)
+TIANO_FLAGS = $(DEFAULT_TIANO_FLAGS) $(PLATFORM_TIANO_FLAGS) $(MODULE_TIANO_FLAGS)
+MAKE_FLAGS = $(DEFAULT_MAKE_FLAGS) $(PLATFORM_MAKE_FLAGS) $(MODULE_MAKE_FLAGS)
+ASMLINK_FLAGS = $(DEFAULT_ASMLINK_FLAGS) $(PLATFORM_ASMLINK_FLAGS) $(MODULE_ASMLINK_FLAGS)
+ASL_FLAGS = $(DEFAULT_ASL_FLAGS) $(PLATFORM_ASL_FLAGS) $(MODULE_ASL_FLAGS)
+
+
+#
+# Tools Path Macro
+#
+PP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+SLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\lib.exe
+CC = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+APP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+VFRPP = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\cl.exe
+DLINK = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\link.exe
+ASM = C:\WINDDK\3790.1830\bin\x86\ml.exe
+TIANO = TianoCompress.exe
+MAKE = C:\Program Files\Microsoft Visual Studio 8\Vc\bin\nmake.exe
+#ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link.exe
+ASMLINK = C:\WINDDK\3790.1830\bin\bin16\link16.exe
+ASL = C:\ASL\iasl.exe
+
+
+MAKE_FILE = $(MODULE_BUILD_DIR)\Makefile
+
+#
+# Shell Command Macro
+#
+RD = rmdir /s /q
+RM = del /f /q
+MD = mkdir
+CP = copy /y
+MV = move /y
+
+
+#
+# Build Macro
+#
+ASSEMBLY_CODE_FILE_LIST = $(MODULE_DIR)\bootsect.asm \
+ $(MODULE_DIR)\bs16.asm \
+ $(MODULE_DIR)\bs32.asm \
+ $(MODULE_DIR)\efi32.asm \
+ $(MODULE_DIR)\Gpt.asm \
+ $(MODULE_DIR)\Mbr.asm \
+ $(MODULE_DIR)\start.asm \
+ $(MODULE_DIR)\start16.asm \
+ $(MODULE_DIR)\start32.asm
+
+TARGET_FILES = $(OUTPUT_DIR)\bootsect.com \
+ $(OUTPUT_DIR)\bs16.com \
+ $(OUTPUT_DIR)\bs32.com \
+ $(OUTPUT_DIR)\Gpt.com \
+ $(OUTPUT_DIR)\Mbr.com \
+ $(OUTPUT_DIR)\Start.com \
+ $(OUTPUT_DIR)\Start16.com \
+ $(OUTPUT_DIR)\Start32.com \
+ $(OUTPUT_DIR)\efi32.com2
+
+INC =
+
+
+#OBJECTS =
+
+LIBS =
+
+COMMON_DEPS =
+
+all: init $(TARGET_FILES) loader
+
+init:
+ if not exist $(OUTPUT_DIR) mkdir $(OUTPUT_DIR)
+ if not exist $(DEBUG_DIR) mkdir $(DEBUG_DIR)
+
+#=============
+$(OUTPUT_DIR)\bootsect.obj:$(MODULE_DIR)\bootsect.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bootsect.obj" /FR"$(OUTPUT_DIR)\bootsect.txt" "$(MODULE_DIR)\bootsect.asm"
+
+$(OUTPUT_DIR)\bootsect.com:$(OUTPUT_DIR)\bootsect.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bootsect.obj,$(OUTPUT_DIR)\bootsect.com,$(OUTPUT_DIR)\bootsect.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\bs16.obj:$(MODULE_DIR)\bs16.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs16.obj" "$(MODULE_DIR)\bs16.asm"
+
+$(OUTPUT_DIR)\bs16.com:$(OUTPUT_DIR)\bs16.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs16.obj,$(OUTPUT_DIR)\bs16.com,$(OUTPUT_DIR)\bs16.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\bs32.obj:$(MODULE_DIR)\bs32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\bs32.obj" "$(MODULE_DIR)\bs32.asm"
+
+$(OUTPUT_DIR)\bs32.com:$(OUTPUT_DIR)\bs32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs32.obj,$(OUTPUT_DIR)\bs32.com,$(OUTPUT_DIR)\bs32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Gpt.obj:$(MODULE_DIR)\Gpt.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Gpt.obj" "$(MODULE_DIR)\Gpt.asm"
+
+$(OUTPUT_DIR)\Gpt.com:$(OUTPUT_DIR)\Gpt.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Gpt.obj,$(OUTPUT_DIR)\Gpt.com,$(OUTPUT_DIR)\Gpt.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Mbr.obj:$(MODULE_DIR)\Mbr.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Mbr.obj" "$(MODULE_DIR)\Mbr.asm"
+
+$(OUTPUT_DIR)\Mbr.com:$(OUTPUT_DIR)\Mbr.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Mbr.obj,$(OUTPUT_DIR)\Mbr.com,$(OUTPUT_DIR)\Mbr.map,,,
+
+#============
+
+$(OUTPUT_DIR)\Start.obj:$(MODULE_DIR)\Start.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start.obj" "$(MODULE_DIR)\Start.asm"
+
+$(OUTPUT_DIR)\Start.com:$(OUTPUT_DIR)\Start.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start.obj,$(OUTPUT_DIR)\Start.com,$(OUTPUT_DIR)\Start.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Start16.obj:$(MODULE_DIR)\Start16.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start16.obj" "$(MODULE_DIR)\Start16.asm"
+
+$(OUTPUT_DIR)\Start16.com:$(OUTPUT_DIR)\Start16.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start16.obj,$(OUTPUT_DIR)\Start16.com,$(OUTPUT_DIR)\Start16.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\Start32.obj:$(MODULE_DIR)\Start32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\Start32.obj" "$(MODULE_DIR)\Start32.asm"
+
+$(OUTPUT_DIR)\Start32.com:$(OUTPUT_DIR)\Start32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start32.obj,$(OUTPUT_DIR)\Start32.com,$(OUTPUT_DIR)\Start32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\efi32.obj:$(MODULE_DIR)\efi32.asm
+ $(ASM) /c /omf /Fo"$(OUTPUT_DIR)\efi32.obj" "$(MODULE_DIR)\efi32.asm"
+
+$(OUTPUT_DIR)\efi32.com:$(OUTPUT_DIR)\efi32.obj
+ "$(ASMLINK)" /tiny $(OUTPUT_DIR)\efi32.obj,$(OUTPUT_DIR)\efi32.com,$(OUTPUT_DIR)\efi32.map,,,
+
+#=============
+
+$(OUTPUT_DIR)\efi32.com2:$(OUTPUT_DIR)\efi32.com
+ $(BASETOOLS_DIR)\Split.exe -f $(OUTPUT_DIR)\efi32.com -t $(OUTPUT_DIR)\efi32.com2 -s 135168
+#
+# clean all generated files
+#
+
+loader:$(BUILD_DIR)\FV\Efildr
+
+$(BUILD_DIR)\FV\DUETEFIMAINFV.z:$(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DUETEFIMAINFV.z $(BUILD_DIR)\FV\DUETEFIMAINFV.Fv
+
+$(BUILD_DIR)\FV\DxeMain.z:$(BUILD_DIR)\IA32\DxeMain.efi
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeMain.z $(BUILD_DIR)\IA32\DxeMain.efi
+
+$(BUILD_DIR)\FV\DxeIpl.z:$(BUILD_DIR)\IA32\DxeIpl.efi
+ $(BASETOOLS_DIR)\TianoCompress -e -o $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\IA32\DxeIpl.efi
+
+$(BUILD_DIR)\FV\Efildr32:$(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
+ $(BASETOOLS_DIR)\EfiLdrImage.exe -o $(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\IA32\EfiLoader.efi $(BUILD_DIR)\FV\DxeIpl.z $(BUILD_DIR)\FV\DUETEFIMAINFV.z
+
+$(BUILD_DIR)\FV\Efildr:$(OUTPUT_DIR)\Start.com $(OUTPUT_DIR)\Efi32.com2 $(BUILD_DIR)\FV\Efildr32
+ copy /b $(OUTPUT_DIR)\BootSect.com+$(OUTPUT_DIR)\Efi32.com2+$(BUILD_DIR)\FV\Efildr32 $(BUILD_DIR)\FV\Efildr
+
+clean:
+ if exist $(DEBUG_DIR) rmdir /s /q $(DEBUG_DIR)
+ if exist $(OUTPUT_DIR) rmdir /s /q $(OUTPUT_DIR)
+
+
diff --git a/DuetPkg/BootSector/Mbr.asm b/DuetPkg/BootSector/Mbr.asm new file mode 100644 index 0000000000..03182a649a --- /dev/null +++ b/DuetPkg/BootSector/Mbr.asm @@ -0,0 +1,261 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* Mbr.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+; .dosseg
+ .stack
+ .486p
+ .code
+
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+; ****************************************************************************
+; Code loaded by BIOS at 0x0000:0x7C00
+; ****************************************************************************
+
+ org 0h
+Start:
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ lea si, cs:[StartString]
+ mov cx, 10
+ mov di, 160
+ rep movsw
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+; ****************************************************************************
+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600
+; ****************************************************************************
+ xor ax, ax ; AX = 0x0000
+ mov bx, 07c00h ; BX = 0x7C00
+ mov bp, 0600h ; BP = 0x0600
+ mov si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)
+ mov cx, 0200h ; CX = 0x0200
+ sub cx, si ; CS = 0x0200 - Offset(RelocatedStart)
+ lea di, [bp+si] ; DI = 0x0600 + Offset(RelocatedStart)
+ lea si, [bx+si] ; BX = 0x7C00 + Offset(RelocatedStart)
+ mov ss, ax ; SS = 0x0000
+ mov sp, bx ; SP = 0x7C00
+ mov es,ax ; ES = 0x0000
+ mov ds,ax ; DS = 0x0000
+ push ax ; PUSH 0x0000
+ push di ; PUSH 0x0600 + Offset(RelocatedStart)
+ cld ; Clear the direction flag
+ rep movsb ; Copy 0x0200 bytes from 0x7C00 to 0x0600
+ retf ; JMP 0x0000:0x0600 + Offset(RelocatedStart)
+
+; ****************************************************************************
+; Code relocated to 0x0000:0x0600
+; ****************************************************************************
+
+RelocatedStart:
+; ****************************************************************************
+; Get Driver Parameters to 0x0000:0x7BFC
+; ****************************************************************************
+
+ xor ax,ax ; AX = 0
+ mov ss,ax ; SS = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; SP = 0x7c00
+ mov bp,sp ; BP = 0x7c00
+
+ mov ah,8 ; AH = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; AX = 0
+ mov al,dh ; AL = DH
+ inc al ; MaxHead = AL + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; AL = CL
+ and al,03fh ; MaxSector = AL & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+; ****************************************************************************
+; Read Target DBR from hard disk to 0x0000:0x7C00
+; ****************************************************************************
+
+ xor ax, ax
+ mov al, byte ptr [bp+MbrPartitionIndicator] ; AX = MbrPartitionIndex
+ cmp al, 0ffh ; 0xFF means do legacy MBR boot
+ jnz EfiDbr
+LegacyMbr:
+ mov eax, 00000600h ; Assume LegacyMBR is backuped in Sector 6
+ jmp StartReadTo7C00 ; EAX = Header/Sector/Tracker/Zero
+
+EfiDbr:
+ cmp al, 4 ; MbrPartitionIndex should < 4
+ jae BadDbr
+ shl ax, 4 ; AX = MBREntrySize * Index
+ add ax, 1beh ; AX = MBREntryOffset
+ mov di, ax ; DI = MBREntryOffset
+
+ ; Here we don't use the C/H/S information provided by Partition table
+ ; but calculate C/H/S from LBA ourselves
+ ; Ci: Cylinder number
+ ; Hi: Header number
+ ; Si: Sector number
+ mov eax, dword ptr es:[bp + di + 8] ; Start LBA
+ mov edx, eax
+ shr edx, 16 ; DX:AX = Start LBA
+ ; = Ci * (H * S) + Hi * S + (Si - 1)
+
+ ; Calculate C/H/S according to LBA
+ mov bp, 7bfah
+ div word ptr [bp+2] ; AX = Hi + H*Ci
+ ; DX = Si - 1
+ inc dx ; DX = Si
+ push dx ; 0000:7bfa = Si <----
+ xor dx, dx ; DX:AX = Hi + H*Ci
+ div word ptr [bp+4] ; AX = Ci <----
+ ; DX = Hi <----
+
+StartReadTo7C00:
+
+ mov cl, byte ptr [bp] ; Si
+ mov ch, al ; Ci[0-7]
+ or cl, ah ; Ci[8,9]
+ mov bx, 7c00h ; ES:BX = 0000:7C00h
+ mov ah, 2h ; Function 02h
+ mov al, 1 ; 1 Sector
+ mov dh, dl ; Hi
+ mov bp, 0600h
+ mov dl, byte ptr [bp + PhysicalDrive] ; Drive number
+ int 13h
+ jc BadDbr
+
+
+
+; ****************************************************************************
+; Transfer control to BootSector - Jump to 0x0000:0x7C00
+; ****************************************************************************
+ xor ax, ax
+ push ax ; PUSH 0x0000 - Segment
+ mov di, 07c00h
+ push di ; PUSH 0x7C00 - Offset
+ retf ; JMP 0x0000:0x7C00
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+
+BadDbr:
+ push ax
+ mov ax, 0b800h
+ mov es, ax
+ mov ax, 060h
+ mov ds, ax
+ lea si, cs:[ErrorString]
+ mov di, 320
+ pop ax
+ call A2C
+ mov [si+16], ah
+ mov [si+18], al
+ mov cx, 10
+ rep movsw
+Halt:
+ jmp Halt
+
+StartString:
+ db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, ':', 0ch, '?', 0ch, '?', 0ch
+
+; ****************************************************************************
+; A2C - convert Ascii code stored in AH to character stored in AX
+; ****************************************************************************
+A2C:
+ mov al, ah
+ shr ah, 4
+ and al, 0Fh
+ add ah, '0'
+ add al, '0'
+
+ cmp ah, '9'
+ jle @f
+ add ah, 7
+@@:
+
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+
+; ****************************************************************************
+; PhysicalDrive - Used to indicate which disk to be boot
+; Can be patched by tool
+; ****************************************************************************
+ org 01B6h
+PhysicalDrive db 80h
+
+; ****************************************************************************
+; MbrPartitionIndicator - Used to indicate which MBR partition to be boot
+; Can be patched by tool
+; OxFF means boot to legacy MBR. (LBA OFFSET 6)
+; ****************************************************************************
+ org 01B7h
+MbrPartitionIndicator db 0
+
+; ****************************************************************************
+; Unique MBR signature
+; ****************************************************************************
+ org 01B8h
+ db 'DUET'
+
+; ****************************************************************************
+; Unknown
+; ****************************************************************************
+ org 01BCh
+ dw 0
+
+; ****************************************************************************
+; MBR Entry - To be patched
+; ****************************************************************************
+ org 01BEh
+ dd 0, 0, 0, 0
+ org 01CEh
+ dd 0, 0, 0, 0
+ org 01DEh
+ dd 0, 0, 0, 0
+ org 01EEh
+ dd 0, 0, 0, 0
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01FEh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bootsect.asm b/DuetPkg/BootSector/bootsect.asm new file mode 100644 index 0000000000..972e36e8a1 --- /dev/null +++ b/DuetPkg/BootSector/bootsect.asm @@ -0,0 +1,288 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bootsect.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 020205244h ; "DR__"
+LOADER_FILENAME_PART3 EQU 020202020h ; "____"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+Id db " " ; Id - 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read entire Root Directory
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
+ mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bs16.asm b/DuetPkg/BootSector/bs16.asm new file mode 100644 index 0000000000..41040269cd --- /dev/null +++ b/DuetPkg/BootSector/bs16.asm @@ -0,0 +1,288 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bs16.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 036315244h ; "DR16"
+LOADER_FILENAME_PART3 EQU 020202036h ; "6___"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+Id db " " ; Id - 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read entire Root Directory
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)
+ mov word ptr [bp],ax ; Save FirstClusterLBA (FirstDataSector) for later use
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/bs32.asm b/DuetPkg/BootSector/bs32.asm new file mode 100644 index 0000000000..bc84f83732 --- /dev/null +++ b/DuetPkg/BootSector/bs32.asm @@ -0,0 +1,310 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* bs32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+ ; "EFILDR_____"
+LOADER_FILENAME_PART1 EQU 04c494645h ; "EFIL"
+LOADER_FILENAME_PART2 EQU 030325244h ; "DR20"
+LOADER_FILENAME_PART3 EQU 020202030h ; "0___"
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+; BPB data below will be fixed by tool
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+
+; ****************************************************************************
+; Start Print
+; ****************************************************************************
+ lea si, cs:[StartString]
+ call PrintString
+
+; ****************************************************************************
+; Print over
+; ****************************************************************************
+
+ mov ax,cs ; ax = 0
+ mov ss,ax ; ss = 0
+ add ax,1000h
+ mov ds,ax
+
+ mov sp,07c00h ; sp = 0x7c00
+ mov bp,sp ; bp = 0x7c00
+
+ mov ah,8 ; ah = 8 - Get Drive Parameters Function
+ mov byte ptr [bp+PhysicalDrive],dl ; BBS defines that BIOS would pass the booting driver number to the loader through DL
+ int 13h ; Get Drive Parameters
+ xor ax,ax ; ax = 0
+ mov al,dh ; al = dh
+ inc al ; MaxHead = al + 1
+ push ax ; 0000:7bfe = MaxHead
+ mov al,cl ; al = cl
+ and al,03fh ; MaxSector = al & 0x3f
+ push ax ; 0000:7bfc = MaxSector
+
+ cmp word ptr [bp+SectorSignature],0aa55h ; Verify Boot Sector Signature
+ jne BadBootSector
+ mov cx,word ptr [bp+RootEntries] ; cx = RootEntries
+ shl cx,FAT_DIRECTORY_ENTRY_SHIFT ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ and bx,BLOCK_MASK ; See if it is an even number of sectors long
+ jne BadBootSector ; If is isn't, then the boot sector is bad.
+ mov bx,cx ; bx = size of the Root Directory in bytes
+ shr bx,BLOCK_SHIFT ; bx = size of Root Directory in sectors
+ mov al,byte ptr [bp+NoFats] ; al = NoFats
+ xor ah,ah ; ah = 0 ==> ax = NoFats
+ mul word ptr [bp+SectorsPerFat32] ; ax = NoFats * SectorsPerFat
+ add ax,word ptr [bp+ReservedSectors] ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
+ add ax,bx ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
+ mov word ptr [bp],ax ; Save FirstClusterLBA for later use
+
+ mov ax,word ptr [bp+RootCluster] ; ax = StartCluster of Root Directory
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ds
+ pop es
+ xor di,di ; Store directory in es:di = 1000:0000
+ call ReadBlocks ; Read StartCluster of Root Directory
+
+ ; dx - variable storage (initial value is 0)
+ ; bx - loader (initial value is 0)
+ xor dx, dx
+ xor bx, bx
+
+FindEFILDR:
+ cmp dword ptr [di],LOADER_FILENAME_PART1 ; Compare to "EFIL"
+ jne FindVARSTORE
+ cmp dword ptr [di+4],LOADER_FILENAME_PART2
+ jne FindVARSTORE
+ cmp dword ptr [di+7],LOADER_FILENAME_PART3
+ jne FindVARSTORE
+ mov bx, word ptr [di+26] ; bx = Start Cluster for EFILDR <----------------------------------
+ test dx, dx
+ je FindNext ; Efivar.bin is not loaded
+ jmp FoundAll
+
+FindVARSTORE:
+ ; if the file is not loader file, see if it's "EFIVAR BIN"
+ cmp dword ptr [di], 056494645h ; Compare to "EFIV"
+ jne FindNext
+ cmp dword ptr [di+4], 020205241h ; Compare to "AR "
+ jne FindNext
+ cmp dword ptr [di+7], 04e494220h ; Compare to " BIN"
+ jne FindNext
+ mov dx, di ; dx = Offset of Start Cluster for Efivar.bin <---------------------
+ add dx, 26
+ test bx, bx
+ je FindNext ; Efildr is not loaded
+ jmp FoundAll
+
+FindNext:
+ ; go to next find
+ add di,FAT_DIRECTORY_ENTRY_SIZE ; Increment di
+ sub cx,FAT_DIRECTORY_ENTRY_SIZE ; Decrement cx
+ ; TODO: jump to FindVarStore if ...
+ jne FindEFILDR
+ jmp NotFoundAll
+
+FoundAll:
+FoundEFILDR:
+ mov cx,bx ; cx = Start Cluster for EFILDR <----------------------------------
+ mov ax,cs ; Destination = 2000:0000
+ add ax,2000h
+ mov es,ax
+ xor di,di
+ReadFirstClusterOfEFILDR:
+ mov ax,cx ; ax = StartCluster
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ push dx
+ mul bx
+ pop dx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = Number of Sectors in a cluster
+ push es
+ call ReadBlocks
+ pop ax
+JumpIntoFirstSectorOfEFILDR:
+ mov word ptr [bp+JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0000h
+JumpSegment:
+ dw 2000h
+
+
+PrintString:
+ mov ax,0b800h
+ mov es,ax
+ mov ax, 07c0h
+ mov ds, ax
+ mov cx, 7
+ mov di, 160
+ rep movsw
+ ret
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+; ****************************************************************************
+; ERROR Condition:
+; ****************************************************************************
+NotFoundAll:
+ ; if we found EFILDR, continue
+ test bx,bx
+ jne FoundEFILDR
+BadBootSector:
+DiskError:
+ lea si, cs:[ErrorString]
+ call PrintString
+Halt:
+ jmp Halt
+
+StartString:
+ db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch
+ErrorString:
+ db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+; ****************************************************************************
+; LBA Offset for BootSector, need patched by tool for HD boot.
+; ****************************************************************************
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+; ****************************************************************************
+; Sector Signature
+; ****************************************************************************
+
+ org 01feh
+SectorSignature:
+ dw 0aa55h ; Boot Sector Signature
+
+ end
+
diff --git a/DuetPkg/BootSector/efi32.asm b/DuetPkg/BootSector/efi32.asm new file mode 100644 index 0000000000..d9560221d6 --- /dev/null +++ b/DuetPkg/BootSector/efi32.asm @@ -0,0 +1,581 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* efi32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Now in 32-bit protected mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .486
+ .model flat
+ .stack
+ .code
+ org 21000h
+
+DEFAULT_HANDLER_SIZE EQU INT1 - INT0
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit relative
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+
+Start:
+ mov ds,ax
+ mov es,ax
+ mov fs,ax
+ mov gs,ax
+ mov ss,ax
+ mov esp,0001ffff0h
+
+ call ClearScreen
+
+ ; Populate IDT with meaningful offsets for exception handlers...
+ sidt fword ptr [Idtr] ; get fword address of IDT
+
+ mov eax, offset Halt
+ mov ebx, eax ; use bx to copy 15..0 to descriptors
+ shr eax, 16 ; use ax to copy 31..16 to descriptors
+ mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
+ mov esi, [offset Idtr + 2]
+ mov edi, [esi]
+
+@@: ; loop through all IDT entries exception handlers and initialize to default handler
+ mov word ptr [edi], bx ; write bits 15..0 of offset
+ mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
+ mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+ mov word ptr [edi+6], ax ; write bits 31..16 of offset
+ add edi, 8 ; move up to next descriptor
+ add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
+ loop @b ; loop back through again until all descriptors are initialized
+
+ ;; at this point edi contains the offset of the descriptor for INT 20
+ ;; and bx contains the low 16 bits of the offset of the default handler
+ ;; so initialize all the rest of the descriptors with these two values...
+; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
+;@@: ; loop through all IDT entries exception handlers and initialize to default handler
+; mov word ptr [edi], bx ; write bits 15..0 of offset
+; mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT
+; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+; mov word ptr [edi+6], ax ; write bits 31..16 of offset
+; add edi, 8 ; move up to next descriptor
+; loop @b ; loop back through again until all descriptors are initialized
+
+
+;; DUMP location of IDT and several of the descriptors
+; mov ecx, 8
+; mov eax, [offset Idtr + 2]
+; mov eax, [eax]
+; mov edi, 0b8000h
+; call PrintDword
+; mov esi, eax
+; mov edi, 0b80a0h
+; jmp OuterLoop
+
+;;
+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
+; mov eax, 011111111h
+; mov ebx, 022222222h
+; mov ecx, 033333333h
+; mov edx, 044444444h
+; mov ebp, 055555555h
+; mov esi, 066666666h
+; mov edi, 077777777h
+; push 011111111h
+; push 022222222h
+; push 033333333h
+; int 119
+
+
+ mov esi,022000h ; esi = 22000
+ mov eax,[esi+014h] ; eax = [22014]
+ add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
+ mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
+ add ebp,esi
+ mov edi,[ebp+034h] ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase
+ mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
+ add eax,edi ; eax = ImageBase + EntryPoint
+ mov dword ptr [EfiLdrOffset],eax ; Modify far jump instruction for correct entry point
+
+ mov bx,word ptr[ebp+6] ; bx = Number of sections
+ xor eax,eax
+ mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
+ add ebp,eax
+ add ebp,018h ; ebp = Start of 1st Section
+
+SectionLoop:
+ push esi ; Save Base of EFILDR.C
+ push edi ; Save ImageBase
+ add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
+ add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
+ mov ecx,[ebp+010h] ; ecs = SizeOfRawData
+
+ cld
+ shr ecx,2
+ rep movsd
+
+ pop edi ; Restore ImageBase
+ pop esi ; Restore Base of EFILDR.C
+
+ add bp,028h ; ebp = ebp + 028h = Pointer to next section record
+ dec bx
+ cmp bx,0
+ jne SectionLoop
+
+ movzx eax, word ptr [Idtr] ; get size of IDT
+ inc eax
+ add eax, dword ptr [Idtr + 2] ; add to base of IDT to get location of memory map...
+ push eax ; push memory map location on stack for call to EFILDR...
+
+ push eax ; push return address (useless, just for stack balance)
+ db 0b8h
+EfiLdrOffset:
+ dd 000401000h ; Offset of EFILDR
+; mov eax, 401000h
+ push eax
+ ret
+
+; db "**** DEFAULT IDT ENTRY ***",0
+ align 02h
+Halt:
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (78h - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+
+commonIdtEntry:
+ pushad
+ mov ebp, esp
+;;
+;; At this point the stack looks like this:
+;;
+;; eflags
+;; Calling CS
+;; Calling EIP
+;; Error code or 0
+;; Int num or 0ffh for unknown int num
+;; eax
+;; ecx
+;; edx
+;; ebx
+;; esp
+;; ebp
+;; esi
+;; edi <------- ESP, EBP
+;;
+
+ call ClearScreen
+ mov esi, offset String1
+ call PrintString
+ mov eax, [ebp + 32] ;; move Int number into EAX
+ cmp eax, 19
+ ja PrintDefaultString
+PrintExceptionString:
+ shl eax, 2 ;; multiply by 4 to get offset from StringTable to actual string address
+ add eax, offset StringTable
+ mov esi, [eax]
+ jmp PrintTheString
+PrintDefaultString:
+ mov esi, offset IntUnknownString
+ ; patch Int number
+ mov edx, eax
+ call A2C
+ mov [esi + 1], al
+ mov eax, edx
+ shr eax, 4
+ call A2C
+ mov [esi], al
+PrintTheString:
+ call PrintString
+ mov esi, offset String2
+ call PrintString
+ mov eax, [ebp+44] ; CS
+ call PrintDword
+ mov al, ':'
+ mov byte ptr [edi], al
+ add edi, 2
+ mov eax, [ebp+40] ; EIP
+ call PrintDword
+ mov esi, offset String3
+ call PrintString
+
+ mov edi, 0b8140h
+
+ mov esi, offset StringEax ; eax
+ call PrintString
+ mov eax, [ebp+28]
+ call PrintDword
+
+ mov esi, offset StringEbx ; ebx
+ call PrintString
+ mov eax, [ebp+16]
+ call PrintDword
+
+ mov esi, offset StringEcx ; ecx
+ call PrintString
+ mov eax, [ebp+24]
+ call PrintDword
+
+ mov esi, offset StringEdx ; edx
+ call PrintString
+ mov eax, [ebp+20]
+ call PrintDword
+
+ mov esi, offset StringEcode ; error code
+ call PrintString
+ mov eax, [ebp+36]
+ call PrintDword
+
+ mov edi, 0b81e0h
+
+ mov esi, offset StringEsp ; esp
+ call PrintString
+ mov eax, [ebp+12]
+ call PrintDword
+
+ mov esi, offset StringEbp ; ebp
+ call PrintString
+ mov eax, [ebp+8]
+ call PrintDword
+
+ mov esi, offset StringEsi ; esi
+ call PrintString
+ mov eax, [ebp+4]
+ call PrintDword
+
+ mov esi, offset StringEdi ; edi
+ call PrintString
+ mov eax, [ebp]
+ call PrintDword
+
+ mov esi, offset StringEflags ; eflags
+ call PrintString
+ mov eax, [ebp+48]
+ call PrintDword
+
+ mov edi, 0b8320h
+
+ mov esi, ebp
+ add esi, 52
+ mov ecx, 8
+
+
+OuterLoop:
+ push ecx
+ mov ecx, 8
+ mov edx, edi
+
+InnerLoop:
+ mov eax, [esi]
+ call PrintDword
+ add esi, 4
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop
+
+
+ mov edi, 0b8960h
+
+ mov eax, [ebp+40] ; EIP
+ sub eax, 32 * 4
+ mov esi, eax ; esi = eip - 32 DWORD linear (total 64 DWORD)
+
+ mov ecx, 8
+
+OuterLoop1:
+ push ecx
+ mov ecx, 8
+ mov edx, edi
+
+InnerLoop1:
+ mov eax, [esi]
+ call PrintDword
+ add esi, 4
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop1
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop1
+
+
+
+; wbinvd ; Ken: this intruction does not support in early than 486 arch
+@@:
+ jmp @b
+;
+; return
+;
+ mov esp, ebp
+ popad
+ add esp, 8 ; error code and INT number
+
+ iretd
+
+
+PrintString:
+ push eax
+@@:
+ mov al, byte ptr [esi]
+ cmp al, 0
+ je @f
+ mov byte ptr [edi], al
+ inc esi
+ add edi, 2
+ jmp @b
+@@:
+ pop eax
+ ret
+
+;; EAX contains dword to print
+;; EDI contains memory location (screen location) to print it to
+PrintDword:
+ push ecx
+ push ebx
+ push eax
+
+ mov ecx, 8
+looptop:
+ rol eax, 4
+ mov bl, al
+ and bl, 0fh
+ add bl, '0'
+ cmp bl, '9'
+ jle @f
+ add bl, 7
+@@:
+ mov byte ptr [edi], bl
+ add edi, 2
+ loop looptop
+ wbinvd
+
+ pop eax
+ pop ebx
+ pop ecx
+ ret
+
+ClearScreen:
+ push eax
+ push ecx
+
+ mov al, ' '
+ mov ah, 0ch
+ mov edi, 0b8000h
+ mov ecx, 80 * 24
+@@:
+ mov word ptr [edi], ax
+ add edi, 2
+ loop @b
+ mov edi, 0b8000h
+
+ pop ecx
+ pop eax
+
+ ret
+
+A2C:
+ and al, 0fh
+ add al, '0'
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+String1 db "*** INT ",0
+
+Int0String db "00h Divide by 0 -",0
+Int1String db "01h Debug exception -",0
+Int2String db "02h NMI -",0
+Int3String db "03h Breakpoint -",0
+Int4String db "04h Overflow -",0
+Int5String db "05h Bound -",0
+Int6String db "06h Invalid opcode -",0
+Int7String db "07h Device not available -",0
+Int8String db "08h Double fault -",0
+Int9String db "09h Coprocessor seg overrun (reserved) -",0
+Int10String db "0Ah Invalid TSS -",0
+Int11String db "0Bh Segment not present -",0
+Int12String db "0Ch Stack fault -",0
+Int13String db "0Dh General protection fault -",0
+Int14String db "0Eh Page fault -",0
+Int15String db "0Fh (Intel reserved) -",0
+Int16String db "10h Floating point error -",0
+Int17String db "11h Alignment check -",0
+Int18String db "12h Machine check -",0
+Int19String db "13h SIMD Floating-Point Exception -",0
+IntUnknownString db "??h Unknown interrupt -",0
+
+StringTable dd offset Int0String, offset Int1String, offset Int2String, offset Int3String,
+ offset Int4String, offset Int5String, offset Int6String, offset Int7String,
+ offset Int8String, offset Int9String, offset Int10String, offset Int11String,
+ offset Int12String, offset Int13String, offset Int14String, offset Int15String,
+ offset Int16String, offset Int17String, offset Int18String, offset Int19String
+
+String2 db " HALT!! *** (",0
+String3 db ")",0
+StringEax db "EAX=",0
+StringEbx db " EBX=",0
+StringEcx db " ECX=",0
+StringEdx db " EDX=",0
+StringEcode db " ECODE=",0
+StringEsp db "ESP=",0
+StringEbp db " EBP=",0
+StringEsi db " ESI=",0
+StringEdi db " EDI=",0
+StringEflags db " EFLAGS=",0
+
+Idtr df 0
+
+ org 21ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/efi64.asm b/DuetPkg/BootSector/efi64.asm new file mode 100644 index 0000000000..bbf8fee35a --- /dev/null +++ b/DuetPkg/BootSector/efi64.asm @@ -0,0 +1,787 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* efi64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Now in 64-bit long mode.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ .486
+ .model flat
+ .stack
+ .code
+ org 21000h
+
+DEFAULT_HANDLER_SIZE EQU INT1 - INT0
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit reletive
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+
+Start:
+
+ mov esp,0001fffe8h ; make final stack aligned
+
+ ; set OSFXSR and OSXMMEXCPT because some code will use XMM register
+ db 0fh
+ db 20h
+ db 0e0h
+; mov rax, cr4
+ bts eax, 9
+ bts eax, 0ah
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, rax
+
+ call ClearScreen
+
+ ; Populate IDT with meaningful offsets for exception handlers...
+ mov eax, offset Idtr
+ sidt fword ptr [eax] ; get fword address of IDT
+
+ mov eax, offset Halt
+ mov ebx, eax ; use bx to copy 15..0 to descriptors
+ shr eax, 16 ; use ax to copy 31..16 to descriptors
+ ; 63..32 of descriptors is 0
+ mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions)
+ mov esi, [offset Idtr + 2]
+ mov edi, [esi]
+
+@@: ; loop through all IDT entries exception handlers and initialize to default handler
+ mov word ptr [edi], bx ; write bits 15..0 of offset
+ mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
+ mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+ mov word ptr [edi+6], ax ; write bits 31..16 of offset
+ mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
+ add edi, 16 ; move up to next descriptor
+ add bx, DEFAULT_HANDLER_SIZE ; move to next entry point
+ loop @b ; loop back through again until all descriptors are initialized
+
+ ;; at this point edi contains the offset of the descriptor for INT 20
+ ;; and bx contains the low 16 bits of the offset of the default handler
+ ;; so initialize all the rest of the descriptors with these two values...
+; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
+;@@: ; loop through all IDT entries exception handlers and initialize to default handler
+; mov word ptr [edi], bx ; write bits 15..0 of offset
+; mov word ptr [edi+2], 38h ; SYS_CODE64_SEL from GDT
+; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
+; mov word ptr [edi+6], ax ; write bits 31..16 of offset
+; mov dword ptr [edi+8], 0 ; write bits 63..32 of offset
+; add edi, 16 ; move up to next descriptor
+; loop @b ; loop back through again until all descriptors are initialized
+
+
+;; DUMP location of IDT and several of the descriptors
+; mov ecx, 8
+; mov eax, [offset Idtr + 2]
+; mov eax, [eax]
+; mov edi, 0b8000h
+; call PrintQword
+; mov esi, eax
+; mov edi, 0b80a0h
+; jmp OuterLoop
+
+;;
+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
+; mov eax, 011111111h
+; mov ebx, 022222222h
+; mov ecx, 033333333h
+; mov edx, 044444444h
+; mov ebp, 055555555h
+; mov esi, 066666666h
+; mov edi, 077777777h
+; push 011111111h
+; push 022222222h
+; push 033333333h
+; int 119
+
+ mov esi,022000h ; esi = 22000
+ mov eax,[esi+014h] ; eax = [22014]
+ add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C
+ mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
+ add ebp,esi
+ mov edi,[ebp+030h] ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)
+ mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
+ add eax,edi ; eax = ImageBase + EntryPoint
+ mov ebx, offset EfiLdrOffset
+ mov dword ptr [ebx],eax ; Modify far jump instruction for correct entry point
+
+ mov bx,word ptr[ebp+6] ; bx = Number of sections
+ xor eax,eax
+ mov ax,word ptr[ebp+014h] ; ax = Optional Header Size
+ add ebp,eax
+ add ebp,018h ; ebp = Start of 1st Section
+
+SectionLoop:
+ push esi ; Save Base of EFILDR.C
+ push edi ; Save ImageBase
+ add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData
+ add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress
+ mov ecx,[ebp+010h] ; ecs = SizeOfRawData
+
+ cld
+ shr ecx,2
+ rep movsd
+
+ pop edi ; Restore ImageBase
+ pop esi ; Restore Base of EFILDR.C
+
+ add bp,028h ; ebp = ebp + 028h = Pointer to next section record
+ db 66h
+ db 0ffh
+ db 0cbh
+; dec bx
+ cmp bx,0
+ jne SectionLoop
+
+ mov edx, offset Idtr
+ movzx eax, word ptr [edx] ; get size of IDT
+ db 0ffh
+ db 0c0h
+; inc eax
+ add eax, dword ptr [edx + 2] ; add to base of IDT to get location of memory map...
+ xor ecx, ecx
+ mov ecx, eax ; put argument to RCX
+
+ db 48h
+ db 0c7h
+ db 0c0h
+EfiLdrOffset:
+ dd 000401000h ; Offset of EFILDR
+; mov rax, 401000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+; db "**** DEFAULT IDT ENTRY ***",0
+ align 02h
+Halt:
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (78h - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+
+commonIdtEntry:
+ push eax
+ push ecx
+ push edx
+ push ebx
+ push esp
+ push ebp
+ push esi
+ push edi
+ db 41h
+ db 50h
+; push r8
+ db 41h
+ db 51h
+; push r9
+ db 41h
+ db 52h
+; push r10
+ db 41h
+ db 53h
+; push r11
+ db 41h
+ db 54h
+; push r12
+ db 41h
+ db 55h
+; push r13
+ db 41h
+ db 56h
+; push r14
+ db 41h
+ db 57h
+; push r15
+ db 48h
+ mov ebp, esp
+; mov rbp, rsp
+
+;;
+;; At this point the stack looks like this:
+;;
+;; Calling SS
+;; Calling RSP
+;; rflags
+;; Calling CS
+;; Calling RIP
+;; Error code or 0
+;; Int num or 0ffh for unknown int num
+;; rax
+;; rcx
+;; rdx
+;; rbx
+;; rsp
+;; rbp
+;; rsi
+;; rdi
+;; r8
+;; r9
+;; r10
+;; r11
+;; r12
+;; r13
+;; r14
+;; r15 <------- RSP, RBP
+;;
+
+ call ClearScreen
+ mov esi, offset String1
+ call PrintString
+ db 48h
+ mov eax, [ebp + 16*8] ;; move Int number into RAX
+ db 48h
+ cmp eax, 18
+ ja PrintDefaultString
+PrintExceptionString:
+ shl eax, 3 ;; multiply by 8 to get offset from StringTable to actual string address
+ add eax, offset StringTable
+ mov esi, [eax]
+ jmp PrintTheString
+PrintDefaultString:
+ mov esi, offset IntUnknownString
+ ; patch Int number
+ mov edx, eax
+ call A2C
+ mov [esi + 1], al
+ mov eax, edx
+ shr eax, 4
+ call A2C
+ mov [esi], al
+PrintTheString:
+ call PrintString
+ mov esi, offset String2
+ call PrintString
+ db 48h
+ mov eax, [ebp+19*8] ; CS
+ call PrintQword
+ mov al, ':'
+ mov byte ptr [edi], al
+ add edi, 2
+ db 48h
+ mov eax, [ebp+18*8] ; RIP
+ call PrintQword
+ mov esi, offset String3
+ call PrintString
+
+ mov edi, 0b8140h
+
+ mov esi, offset StringRax ; rax
+ call PrintString
+ db 48h
+ mov eax, [ebp+15*8]
+ call PrintQword
+
+ mov esi, offset StringRcx ; rcx
+ call PrintString
+ db 48h
+ mov eax, [ebp+14*8]
+ call PrintQword
+
+ mov esi, offset StringRdx ; rdx
+ call PrintString
+ db 48h
+ mov eax, [ebp+13*8]
+ call PrintQword
+
+ mov edi, 0b81e0h
+
+ mov esi, offset StringRbx ; rbx
+ call PrintString
+ db 48h
+ mov eax, [ebp+12*8]
+ call PrintQword
+
+ mov esi, offset StringRsp ; rsp
+ call PrintString
+ db 48h
+ mov eax, [ebp+21*8]
+ call PrintQword
+
+ mov esi, offset StringRbp ; rbp
+ call PrintString
+ db 48h
+ mov eax, [ebp+10*8]
+ call PrintQword
+
+ mov edi, 0b8280h
+
+ mov esi, offset StringRsi ; rsi
+ call PrintString
+ db 48h
+ mov eax, [ebp+9*8]
+ call PrintQword
+
+ mov esi, offset StringRdi ; rdi
+ call PrintString
+ db 48h
+ mov eax, [ebp+8*8]
+ call PrintQword
+
+ mov esi, offset StringEcode ; error code
+ call PrintString
+ db 48h
+ mov eax, [ebp+17*8]
+ call PrintQword
+
+ mov edi, 0b8320h
+
+ mov esi, offset StringR8 ; r8
+ call PrintString
+ db 48h
+ mov eax, [ebp+7*8]
+ call PrintQword
+
+ mov esi, offset StringR9 ; r9
+ call PrintString
+ db 48h
+ mov eax, [ebp+6*8]
+ call PrintQword
+
+ mov esi, offset StringR10 ; r10
+ call PrintString
+ db 48h
+ mov eax, [ebp+5*8]
+ call PrintQword
+
+ mov edi, 0b83c0h
+
+ mov esi, offset StringR11 ; r11
+ call PrintString
+ db 48h
+ mov eax, [ebp+4*8]
+ call PrintQword
+
+ mov esi, offset StringR12 ; r12
+ call PrintString
+ db 48h
+ mov eax, [ebp+3*8]
+ call PrintQword
+
+ mov esi, offset StringR13 ; r13
+ call PrintString
+ db 48h
+ mov eax, [ebp+2*8]
+ call PrintQword
+
+ mov edi, 0b8460h
+
+ mov esi, offset StringR14 ; r14
+ call PrintString
+ db 48h
+ mov eax, [ebp+1*8]
+ call PrintQword
+
+ mov esi, offset StringR15 ; r15
+ call PrintString
+ db 48h
+ mov eax, [ebp+0*8]
+ call PrintQword
+
+ mov esi, offset StringSs ; ss
+ call PrintString
+ db 48h
+ mov eax, [ebp+22*8]
+ call PrintQword
+
+ mov edi, 0b8500h
+
+ mov esi, offset StringRflags ; rflags
+ call PrintString
+ db 48h
+ mov eax, [ebp+20*8]
+ call PrintQword
+
+ mov edi, 0b8640h
+
+ mov esi, ebp
+ add esi, 23*8
+ mov ecx, 4
+
+
+OuterLoop:
+ push ecx
+ mov ecx, 4
+ db 48h
+ mov edx, edi
+
+InnerLoop:
+ db 48h
+ mov eax, [esi]
+ call PrintQword
+ add esi, 8
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop
+
+
+ mov edi, 0b8960h
+
+ db 48h
+ mov eax, [ebp+18*8] ; RIP
+ sub eax, 8 * 8
+ db 48h
+ mov esi, eax ; esi = rip - 8 QWORD linear (total 16 QWORD)
+
+ mov ecx, 4
+
+OuterLoop1:
+ push ecx
+ mov ecx, 4
+ mov edx, edi
+
+InnerLoop1:
+ db 48h
+ mov eax, [esi]
+ call PrintQword
+ add esi, 8
+ mov al, ' '
+ mov [edi], al
+ add edi, 2
+ loop InnerLoop1
+
+ pop ecx
+ add edx, 0a0h
+ mov edi, edx
+ loop OuterLoop1
+
+
+
+ wbinvd
+@@:
+ jmp @b
+
+;
+; return
+;
+ mov esp, ebp
+; mov rsp, rbp
+ db 41h
+ db 5fh
+; pop r15
+ db 41h
+ db 5eh
+; pop r14
+ db 41h
+ db 5dh
+; pop r13
+ db 41h
+ db 5ch
+; pop r12
+ db 41h
+ db 5bh
+; pop r11
+ db 41h
+ db 5ah
+; pop r10
+ db 41h
+ db 59h
+; pop r9
+ db 41h
+ db 58h
+; pop r8
+ pop edi
+ pop esi
+ pop ebp
+ pop eax ; esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ db 48h
+ db 83h
+ db 0c4h
+ db 10h
+; add esp, 16 ; error code and INT number
+
+ db 48h
+ db 0cfh
+; iretq
+
+PrintString:
+ push eax
+@@:
+ mov al, byte ptr [esi]
+ cmp al, 0
+ je @f
+ mov byte ptr [edi], al
+ db 0ffh
+ db 0c6h
+; inc esi
+ add edi, 2
+ jmp @b
+@@:
+ pop eax
+ ret
+
+;; RAX contains qword to print
+;; RDI contains memory location (screen location) to print it to
+PrintQword:
+ push ecx
+ push ebx
+ push eax
+
+ db 48h
+ db 0c7h
+ db 0c1h
+ dd 16
+; mov rcx, 16
+looptop:
+ db 48h
+ rol eax, 4
+ mov bl, al
+ and bl, 0fh
+ add bl, '0'
+ cmp bl, '9'
+ jle @f
+ add bl, 7
+@@:
+ mov byte ptr [edi], bl
+ add edi, 2
+ loop looptop
+ wbinvd
+
+ pop eax
+ pop ebx
+ pop ecx
+ ret
+
+ClearScreen:
+ push eax
+ push ecx
+
+ mov al, ' '
+ mov ah, 0ch
+ mov edi, 0b8000h
+ mov ecx, 80 * 24
+@@:
+ mov word ptr [edi], ax
+ add edi, 2
+ loop @b
+ mov edi, 0b8000h
+
+ pop ecx
+ pop eax
+
+ ret
+
+A2C:
+ and al, 0fh
+ add al, '0'
+ cmp al, '9'
+ jle @f
+ add al, 7
+@@:
+ ret
+
+String1 db "*** INT ",0
+
+Int0String db "00h Divide by 0 -",0
+Int1String db "01h Debug exception -",0
+Int2String db "02h NMI -",0
+Int3String db "03h Breakpoint -",0
+Int4String db "04h Overflow -",0
+Int5String db "05h Bound -",0
+Int6String db "06h Invalid opcode -",0
+Int7String db "07h Device not available -",0
+Int8String db "08h Double fault -",0
+Int9String db "09h Coprocessor seg overrun (reserved) -",0
+Int10String db "0Ah Invalid TSS -",0
+Int11String db "0Bh Segment not present -",0
+Int12String db "0Ch Stack fault -",0
+Int13String db "0Dh General protection fault -",0
+Int14String db "0Eh Page fault -",0
+Int15String db "0Fh (Intel reserved) -",0
+Int16String db "10h Floating point error -",0
+Int17String db "11h Alignment check -",0
+Int18String db "12h Machine check -",0
+Int19String db "13h SIMD Floating-Point Exception -",0
+IntUnknownString db "??h Unknown interrupt -",0
+
+StringTable dq offset Int0String, offset Int1String, offset Int2String, offset Int3String,
+ offset Int4String, offset Int5String, offset Int6String, offset Int7String,
+ offset Int8String, offset Int9String, offset Int10String, offset Int11String,
+ offset Int12String, offset Int13String, offset Int14String, offset Int15String,
+ offset Int16String, offset Int17String, offset Int18String, offset Int19String
+
+String2 db " HALT!! *** (",0
+String3 db ")",0
+StringRax db "RAX=",0
+StringRcx db " RCX=",0
+StringRdx db " RDX=",0
+StringRbx db "RBX=",0
+StringRsp db " RSP=",0
+StringRbp db " RBP=",0
+StringRsi db "RSI=",0
+StringRdi db " RDI=",0
+StringEcode db " ECODE=",0
+StringR8 db "R8 =",0
+StringR9 db " R9 =",0
+StringR10 db " R10=",0
+StringR11 db "R11=",0
+StringR12 db " R12=",0
+StringR13 db " R13=",0
+StringR14 db "R14=",0
+StringR15 db " R15=",0
+StringSs db " SS =",0
+StringRflags db "RFLAGS=",0
+
+Idtr df 0
+ df 0
+
+ org 21ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/st16_64.asm b/DuetPkg/BootSector/st16_64.asm new file mode 100644 index 0000000000..b2df0eb042 --- /dev/null +++ b/DuetPkg/BootSector/st16_64.asm @@ -0,0 +1,1140 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* st16_64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; FatOffset = ClusterNumber * 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/st32_64.asm b/DuetPkg/BootSector/st32_64.asm new file mode 100644 index 0000000000..970cdc8f0d --- /dev/null +++ b/DuetPkg/BootSector/st32_64.asm @@ -0,0 +1,1156 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* st32_64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+SectorSize dw 0 ; Sector Size - 2 bytes
+SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte
+ReservedSectors dw 0 ; Reserved Sectors - 2 bytes
+NoFats db 0 ; Number of FATs - 1 byte
+RootEntries dw 0 ; Root Entries - 2 bytes
+Sectors dw 0 ; Number of Sectors - 2 bytes
+Media db 0 ; Media - 1 byte
+SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte
+SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes
+Heads dw 0 ; Heads - 2 bytes
+HiddenSectors dd 0 ; Hidden Sectors - 4 bytes
+LargeSectors dd 0 ; Large Sectors - 4 bytes
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,2 ; FatOffset = ClusterNumber * 4
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start.asm b/DuetPkg/BootSector/start.asm new file mode 100644 index 0000000000..e8eb22982d --- /dev/null +++ b/DuetPkg/BootSector/start.asm @@ -0,0 +1,921 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0ff8h ; ax = ax & 0xff8
+ cmp ax,0ff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; ax = ClusterNumber * 2
+ add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
+ shr ax,1 ; FatOffset = ClusterNumber*3 / 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ and ax,1 ; See if this is an odd cluster number
+ je EvenFatEntry
+ shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
+EvenFatEntry:
+ and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start16.asm b/DuetPkg/BootSector/start16.asm new file mode 100644 index 0000000000..4775c4e8a3 --- /dev/null +++ b/DuetPkg/BootSector/start16.asm @@ -0,0 +1,914 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start16.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT16 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; FatOffset = ClusterNumber * 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start32.asm b/DuetPkg/BootSector/start32.asm new file mode 100644 index 0000000000..6cc6fcaa6c --- /dev/null +++ b/DuetPkg/BootSector/start32.asm @@ -0,0 +1,929 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start32.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+SectorSize dw 0 ; Sector Size - 2 bytes
+SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte
+ReservedSectors dw 0 ; Reserved Sectors - 2 bytes
+NoFats db 0 ; Number of FATs - 1 byte
+RootEntries dw 0 ; Root Entries - 2 bytes
+Sectors dw 0 ; Number of Sectors - 2 bytes
+Media db 0 ; Media - 1 byte
+SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte
+SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes
+Heads dw 0 ; Heads - 2 bytes
+HiddenSectors dd 0 ; Hidden Sectors - 4 bytes
+LargeSectors dd 0 ; Large Sectors - 4 bytes
+
+;******************************************************************************
+;
+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
+;
+;******************************************************************************
+
+SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes
+ExtFlags dw 0 ; Mirror Flag - 2 bytes
+FSVersion dw 0 ; File System Version - 2 bytes
+RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes
+FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes
+BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes
+Reserved db 12 dup(0) ; Reserved Field - 12 bytes
+PhysicalDrive db 0 ; Physical Drive Number - 1 byte
+Reserved1 db 0 ; Reserved Field - 1 byte
+Signature db 0 ; Extended Boot Signature - 1 byte
+VolId db " " ; Volume Serial Number - 4 bytes
+FatLabel db " " ; Volume Label - 11 bytes
+FileSystemType db "FAT32 " ; File System Type - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0fff8h ; ax = ax & 0xfff8
+ cmp ax,0fff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,2 ; FatOffset = ClusterNumber * 4
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+ add ebx,01000h ; Source of EFI32
+ mov dword ptr [JUMP+2],ebx
+ add ebx,01000h
+ mov esi,ebx ; Source of EFILDR32
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ db 66h
+ lgdt fword ptr [gdtr]
+ db 66h
+ lidt fword ptr [idtr]
+
+ mov eax,cr0
+ or al,1
+ mov cr0,eax
+
+ mov eax,0008h ; Flat data descriptor
+ mov ebp,000400000h ; Destination of EFILDR32
+ mov ebx,000070000h ; Length of copy
+
+JUMP:
+; jmp far 0010:00020000
+ db 066h
+ db 0eah
+ dd 000020000h
+ dw 00010h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/BootSector/start64.asm b/DuetPkg/BootSector/start64.asm new file mode 100644 index 0000000000..5491722e58 --- /dev/null +++ b/DuetPkg/BootSector/start64.asm @@ -0,0 +1,1147 @@ +;------------------------------------------------------------------------------
+;*
+;* Copyright 2006 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* start64.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .model small
+ .stack
+ .486p
+ .code
+
+FAT_DIRECTORY_ENTRY_SIZE EQU 020h
+FAT_DIRECTORY_ENTRY_SHIFT EQU 5
+BLOCK_SIZE EQU 0200h
+BLOCK_MASK EQU 01ffh
+BLOCK_SHIFT EQU 9
+
+ org 0h
+Ia32Jump:
+ jmp BootSectorEntryPoint ; JMP inst - 3 bytes
+ nop
+
+OemId db "INTEL " ; OemId - 8 bytes
+
+SectorSize dw 0 ; Sector Size - 16 bits
+SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
+ReservedSectors dw 0 ; Reserved Sectors - 16 bits
+NoFats db 0 ; Number of FATs - 8 bits
+RootEntries dw 0 ; Root Entries - 16 bits
+Sectors dw 0 ; Number of Sectors - 16 bits
+Media db 0 ; Media - 8 bits - ignored
+SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
+SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
+Heads dw 0 ; Heads - 16 bits - ignored
+HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
+LargeSectors dd 0 ; Large Sectors - 32 bits
+PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
+CurrentHead db 0 ; Current Head - 8 bits
+Signature db 0 ; Signature - 8 bits - ignored
+VolId db " " ; Volume Serial Number- 4 bytes
+FatLabel db " " ; Label - 11 bytes
+SystemId db "FAT12 " ; SystemId - 8 bytes
+
+BootSectorEntryPoint:
+ ASSUME ds:@code
+ ASSUME ss:@code
+ ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
+ ; cx = Start Cluster of EfiLdr
+ ; dx = Start Cluster of Efivar.bin
+
+; Re use the BPB data stored in Boot Sector
+ mov bp,07c00h
+
+ push cx
+; Read Efivar.bin
+; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
+ mov ax,01900h
+ mov es,ax
+ test dx,dx
+ jnz CheckVarStoreSize
+
+ mov al,1
+NoVarStore:
+ push es
+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
+ mov byte ptr es:[4],al
+ jmp SaveVolumeId
+
+CheckVarStoreSize:
+ mov di,dx
+ cmp dword ptr ds:[di+2], 04000h
+ mov al,2
+ jne NoVarStore
+
+LoadVarStore:
+ mov al,0
+ mov byte ptr es:[4],al
+ mov cx,word ptr[di]
+; ES:DI = 1500:0
+ xor di,di
+ push es
+ mov ax,01500h
+ mov es,ax
+ call ReadFile
+SaveVolumeId:
+ pop es
+ mov ax,word ptr [bp+VolId]
+ mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
+ mov ax,word ptr [bp+VolId+2]
+ mov word ptr es:[2],ax
+
+; Read Efildr
+ pop cx
+; cx = Start Cluster of Efildr -> BS.com has filled already
+; ES:DI = 2000:0, first cluster will be read again
+ xor di,di ; di = 0
+ mov ax,02000h
+ mov es,ax
+ call ReadFile
+ mov ax,cs
+ mov word ptr cs:[JumpSegment],ax
+
+CheckEm64T:
+ mov eax, 080000001h
+; cpuid
+ dw 0A20Fh
+ bt edx, 29
+ jc CheckEm64TPass
+ push cs
+ pop ds
+ lea si, [Em64String]
+ mov cx, 18
+ jmp PrintStringAndHalt
+CheckEm64TPass:
+JumpFarInstruction:
+ db 0eah
+JumpOffset:
+ dw 0200h
+JumpSegment:
+ dw 2000h
+
+
+
+; ****************************************************************************
+; ReadFile
+;
+; Arguments:
+; CX = Start Cluster of File
+; ES:DI = Buffer to store file content read from disk
+;
+; Return:
+; (ES << 4 + DI) = end of file content Buffer
+;
+; ****************************************************************************
+ReadFile:
+; si = NumberOfClusters
+; cx = ClusterNumber
+; dx = CachedFatSectorNumber
+; ds:0000 = CacheFatSectorBuffer
+; es:di = Buffer to load file
+; bx = NextClusterNumber
+ pusha
+ mov si,1 ; NumberOfClusters = 1
+ push cx ; Push Start Cluster onto stack
+ mov dx,0fffh ; CachedFatSectorNumber = 0xfff
+FatChainLoop:
+ mov ax,cx ; ax = ClusterNumber
+ and ax,0ff8h ; ax = ax & 0xff8
+ cmp ax,0ff8h ; See if this is the last cluster
+ je FoundLastCluster ; Jump if last cluster found
+ mov ax,cx ; ax = ClusterNumber
+ shl ax,1 ; ax = ClusterNumber * 2
+ add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
+ shr ax,1 ; FatOffset = ClusterNumber*3 / 2
+ push si ; Save si
+ mov si,ax ; si = FatOffset
+ shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
+ add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
+ and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
+ cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
+ je SkipFatRead
+ mov bx,2
+ push es
+ push ds
+ pop es
+ call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
+ pop es
+ mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
+SkipFatRead:
+ mov bx,word ptr [si] ; bx = NextClusterNumber
+ mov ax,cx ; ax = ClusterNumber
+ and ax,1 ; See if this is an odd cluster number
+ je EvenFatEntry
+ shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
+EvenFatEntry:
+ and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
+ pop si ; Restore si
+ dec bx ; bx = NextClusterNumber - 1
+ cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
+ jne ReadClusters
+ inc bx ; bx = NextClusterNumber
+ inc si ; NumberOfClusters++
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ jmp FatChainLoop
+ReadClusters:
+ inc bx
+ pop ax ; ax = StartCluster
+ push bx ; StartCluster = NextClusterNumber
+ mov cx,bx ; ClusterNumber = NextClusterNumber
+ sub ax,2 ; ax = StartCluster - 2
+ xor bh,bh
+ mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
+ mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
+ add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
+ push ax ; save start sector
+ mov ax,si ; ax = NumberOfClusters
+ mul bx ; ax = NumberOfClusters * SectorsPerCluster
+ mov bx,ax ; bx = Number of Sectors
+ pop ax ; ax = Start Sector
+ call ReadBlocks
+ mov si,1 ; NumberOfClusters = 1
+ jmp FatChainLoop
+FoundLastCluster:
+ pop cx
+ popa
+ ret
+
+
+; ****************************************************************************
+; ReadBlocks - Reads a set of blocks from a block device
+;
+; AX = Start LBA
+; BX = Number of Blocks to Read
+; ES:DI = Buffer to store sectors read from disk
+; ****************************************************************************
+
+; cx = Blocks
+; bx = NumberOfBlocks
+; si = StartLBA
+
+ReadBlocks:
+ pusha
+ add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
+ add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
+ mov esi,eax ; esi = Start LBA
+ mov cx,bx ; cx = Number of blocks to read
+ReadCylinderLoop:
+ mov bp,07bfch ; bp = 0x7bfc
+ mov eax,esi ; eax = Start LBA
+ xor edx,edx ; edx = 0
+ movzx ebx,word ptr [bp] ; bx = MaxSector
+ div ebx ; ax = StartLBA / MaxSector
+ inc dx ; dx = (StartLBA % MaxSector) + 1
+
+ mov bx,word ptr [bp] ; bx = MaxSector
+ sub bx,dx ; bx = MaxSector - Sector
+ inc bx ; bx = MaxSector - Sector + 1
+ cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
+ jg LimitTransfer
+ mov bx,cx ; bx = Blocks
+LimitTransfer:
+ push ax ; save ax
+ mov ax,es ; ax = es
+ shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
+ and ax,07fh ; ax = Number of blocks into current seg
+ add ax,bx ; ax = End Block number of transfer
+ cmp ax,080h ; See if it crosses a 64K boundry
+ jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
+ sub ax,080h ; ax = Number of blocks past 64K boundry
+ sub bx,ax ; Decrease transfer size by block overage
+NotCrossing64KBoundry:
+ pop ax ; restore ax
+
+ push cx
+ mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
+ xor dx,dx ; dx = 0
+ div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
+ ; dx = ax % (MaxHead + 1) = Head
+
+ push bx ; Save number of blocks to transfer
+ mov dh,dl ; dh = Head
+ mov bp,07c00h ; bp = 0x7c00
+ mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
+ mov ch,al ; ch = Cylinder
+ mov al,bl ; al = Blocks
+ mov ah,2 ; ah = Function 2
+ mov bx,di ; es:bx = Buffer address
+ int 013h
+ jc DiskError
+ pop bx
+ pop cx
+ movzx ebx,bx
+ add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
+ sub cx,bx ; Blocks = Blocks - NumberOfBlocks
+ mov ax,es
+ shl bx,(BLOCK_SHIFT-4)
+ add ax,bx
+ mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
+ cmp cx,0
+ jne ReadCylinderLoop
+ popa
+ ret
+
+DiskError:
+ push cs
+ pop ds
+ lea si, [ErrorString]
+ mov cx, 7
+ jmp PrintStringAndHalt
+
+PrintStringAndHalt:
+ mov ax,0b800h
+ mov es,ax
+ mov di,160
+ rep movsw
+Halt:
+ jmp Halt
+
+ErrorString:
+ db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
+
+ org 01fah
+LBAOffsetForBootSector:
+ dd 0h
+
+ org 01feh
+ dw 0aa55h
+
+;******************************************************************************
+;******************************************************************************
+;******************************************************************************
+
+DELAY_PORT equ 0edh ; Port to use for 1uS delay
+KBD_CONTROL_PORT equ 060h ; 8042 control port
+KBD_STATUS_PORT equ 064h ; 8042 status port
+WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
+ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
+
+ org 200h
+ jmp start
+Em64String:
+ db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
+
+start:
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ss,ax
+ mov sp,MyStack
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[160],'a'
+; mov ax,cs
+; mov es,ax
+
+ mov ebx,0
+ lea edi,MemoryMap
+MemMapLoop:
+ mov eax,0e820h
+ mov ecx,20
+ mov edx,'SMAP'
+ int 15h
+ jc MemMapDone
+ add edi,20
+ cmp ebx,0
+ je MemMapDone
+ jmp MemMapLoop
+MemMapDone:
+ lea eax,MemoryMap
+ sub edi,eax ; Get the address of the memory map
+ mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
+
+ xor ebx,ebx
+ mov bx,cs ; BX=segment
+ shl ebx,4 ; BX="linear" address of segment base
+ lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[162],'b'
+; mov ax,cs
+; mov es,ax
+
+;
+; Enable A20 Gate
+;
+
+ mov ax,2401h ; Enable A20 Gate
+ int 15h
+ jnc A20GateEnabled ; Jump if it suceeded
+
+;
+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
+;
+
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ out DELAY_PORT,ax ; Delay 1 uS
+ mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
+ out KBD_STATUS_PORT,al ; Send command to the 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ jnz Timeout8042 ; Jump if the 8042 timed out
+ mov al,ENABLE_A20_CMD ; gate address bit 20 on
+ out KBD_CONTROL_PORT,al ; Send command to thre 8042
+ call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
+ mov cx,25 ; Delay 25 uS for the command to complete on the 8042
+Delay25uS:
+ out DELAY_PORT,ax ; Delay 1 uS
+ loop Delay25uS
+Timeout8042:
+
+
+A20GateEnabled:
+
+;
+; DISABLE INTERRUPTS - Entering Protected Mode
+;
+
+ cli
+
+; mov ax,0b800h
+; mov es,ax
+; mov byte ptr es:[164],'c'
+; mov ax,cs
+; mov es,ax
+
+ lea eax, OffsetIn32BitProtectedMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetIn32BitProtectedMode], eax
+
+ lea eax, OffsetInLongMode
+ add eax, 20000h + 6h
+ mov dword ptr[OffsetInLongMode], eax
+
+ ;
+ ; load GDT
+ ;
+ db 66h
+ lgdt fword ptr [gdtr]
+
+ ;
+ ; Enable Protect Mode (set CR0.PE=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ or eax, 1h ; Set PE=1
+ mov cr0, eax ; Write CR0.
+ db 066h
+ db 0eah ; jmp far 16:32
+OffsetIn32BitProtectedMode:
+ dd 00000000h ; offset $+8 (In32BitProtectedMode)
+ dw 10h ; selector (flat CS)
+In32BitProtectedMode:
+
+;
+; Entering Long Mode
+;
+ db 66h
+ mov ax, 8
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;
+ ; Enable the 64-bit page-translation-table entries by
+ ; setting CR4.PAE=1 (this is _required_ before activating
+ ; long mode). Paging is not enabled until after long mode
+ ; is enabled.
+ ;
+ db 0fh
+ db 20h
+ db 0e0h
+; mov eax, cr4
+ bts eax, 5
+ db 0fh
+ db 22h
+ db 0e0h
+; mov cr4, eax
+
+ ;
+ ; This is the Trapolean Page Tables that are guarenteed
+ ; under 4GB.
+ ;
+ ; Address Map:
+ ; 10000 ~ 12000 - efildr (loaded)
+ ; 20000 ~ 21000 - start64.com
+ ; 21000 ~ 22000 - efi64.com
+ ; 22000 ~ 90000 - efildr
+ ; 90000 ~ 96000 - 4G pagetable (will be reload later)
+ ;
+ db 0b8h
+ dd 90000h
+; mov eax, 90000h
+ mov cr3, eax
+
+ ;
+ ; Enable long mode (set EFER.LME=1).
+ ;
+ db 0b9h
+ dd 0c0000080h
+; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0fh
+ db 32h
+; rdmsr ; Read EFER.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 08h
+; bts eax, 8 ; Set LME=1.
+ db 0fh
+ db 30h
+; wrmsr ; Write EFER.
+
+ ;
+ ; Enable paging to activate long mode (set CR0.PG=1)
+ ;
+ mov eax, cr0 ; Read CR0.
+ db 0fh
+ db 0bah
+ db 0e8h
+ db 01fh
+; bts eax, 31 ; Set PG=1.
+ mov cr0, eax ; Write CR0.
+ jmp GoToLongMode
+GoToLongMode:
+
+ db 067h
+ db 0eah ; Far Jump $+9:Selector to reload CS
+OffsetInLongMode:
+ dd 00000000 ; $+9 Offset is ensuing instruction boundary
+ dw 038h ; Selector is our code selector, 38h
+
+InLongMode:
+ db 66h
+ mov ax, 30h
+ mov ds, ax
+
+ db 66h
+ mov ax, 18h
+ mov es, ax
+ mov ss, ax
+ mov ds, ax
+
+ db 0bdh
+ dd 400000h
+; mov ebp,000400000h ; Destination of EFILDR32
+ db 0bbh
+ dd 70000h
+; mov ebx,000070000h ; Length of copy
+
+ ;
+ ; load idt later
+ ;
+ db 48h
+ db 33h
+ db 0c0h
+; xor rax, rax
+ db 66h
+ mov ax, offset idtr
+ db 48h
+ db 05h
+ dd 20000h
+; add rax, 20000h
+
+ db 0fh
+ db 01h
+ db 18h
+; lidt fword ptr [rax]
+
+ db 48h
+ db 0c7h
+ db 0c0h
+ dd 21000h
+; mov rax, 21000h
+ db 50h
+; push rax
+
+; ret
+ db 0c3h
+
+Empty8042InputBuffer:
+ mov cx,0
+Empty8042Loop:
+ out DELAY_PORT,ax ; Delay 1us
+ in al,KBD_STATUS_PORT ; Read the 8042 Status Port
+ and al,02h ; Check the Input Buffer Full Flag
+ loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
+ ret
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
+ db (85 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+IDT_END:
+
+ align 02h
+
+MemoryMapSize dd 0
+MemoryMap dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0
+
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+ org 0fe0h
+MyStack:
+ ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
+ ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
+ ; known low address (20f00) so it can be set up by PlMapIrqToVect in
+ ; 8259.c
+
+ int 8
+ iret
+
+ int 9
+ iret
+
+ int 10
+ iret
+
+ int 11
+ iret
+
+ int 12
+ iret
+
+ int 13
+ iret
+
+ int 14
+ iret
+
+ int 15
+ iret
+
+
+ org 0ffeh
+BlockSignature:
+ dw 0aa55h
+
+ end
diff --git a/DuetPkg/CpuDxe/Cpu.c b/DuetPkg/CpuDxe/Cpu.c new file mode 100644 index 0000000000..1390a89d57 --- /dev/null +++ b/DuetPkg/CpuDxe/Cpu.c @@ -0,0 +1,1151 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Cpu.c
+
+Abstract:
+
+--*/
+
+#include "CpuDxe.h"
+
+//
+// Global Variables
+//
+
+BOOLEAN mInterruptState = FALSE;
+extern UINT32 mExceptionCodeSize;
+UINTN mTimerVector = 0;
+volatile EFI_CPU_INTERRUPT_HANDLER mTimerHandler = NULL;
+EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL;
+
+//
+// The Cpu Architectural Protocol that this Driver produces
+//
+EFI_HANDLE mHandle = NULL;
+EFI_CPU_ARCH_PROTOCOL mCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 1, // NumberOfTimers
+ 4, // DmaBufferAlignment
+};
+
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+/*++
+
+Routine Description:
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+Arguments:
+ This - Protocol instance structure
+ Start - Physical address to start flushing from.
+ Length - Number of bytes to flush. Round up to chipset
+ granularity.
+ FlushType - Specifies the type of flush operation to perform.
+
+Returns:
+
+ EFI_SUCCESS - If cache was flushed
+ EFI_UNSUPPORTED - If flush type is not supported.
+ EFI_DEVICE_ERROR - If requested range could not be flushed.
+
+--*/
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ Enables CPU interrupts.
+
+Arguments:
+ This - Protocol instance structure
+
+Returns:
+ EFI_SUCCESS - If interrupts were enabled in the CPU
+ EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+
+--*/
+{
+ EnableInterrupts ();
+
+ mInterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ Disables CPU interrupts.
+
+Arguments:
+ This - Protocol instance structure
+
+Returns:
+ EFI_SUCCESS - If interrupts were disabled in the CPU.
+ EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
+
+--*/
+{
+ DisableInterrupts ();
+
+ mInterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+/*++
+
+Routine Description:
+ Return the state of interrupts.
+
+Arguments:
+ This - Protocol instance structure
+ State - Pointer to the CPU's current interrupt state
+
+Returns:
+ EFI_SUCCESS - If interrupts were disabled in the CPU.
+ EFI_INVALID_PARAMETER - State is NULL.
+
+--*/
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+
+/*++
+
+Routine Description:
+ Generates an INIT to the CPU
+
+Arguments:
+ This - Protocol instance structure
+ InitType - Type of CPU INIT to perform
+
+Returns:
+ EFI_SUCCESS - If CPU INIT occurred. This value should never be
+ seen.
+ EFI_DEVICE_ERROR - If CPU INIT failed.
+ EFI_NOT_SUPPORTED - Requested type of CPU INIT not supported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+/*++
+
+Routine Description:
+ Registers a function to be called from the CPU interrupt handler.
+
+Arguments:
+ This - Protocol instance structure
+ InterruptType - Defines which interrupt to hook. IA-32 valid range
+ is 0x00 through 0xFF
+ InterruptHandler - A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called when a
+ processor interrupt occurs. A null pointer
+ is an error condition.
+
+Returns:
+ EFI_SUCCESS - If handler installed or uninstalled.
+ EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ EFI_UNSUPPORTED - The interrupt specified by InterruptType is not
+ supported.
+
+--*/
+{
+ if ((InterruptType < 0) || (InterruptType >= INTERRUPT_VECTOR_NUMBER)) {
+ return EFI_UNSUPPORTED;
+ }
+ if ((UINTN)(UINT32)InterruptType != mTimerVector) {
+ return EFI_UNSUPPORTED;
+ }
+ if ((mTimerHandler == NULL) && (InterruptHandler == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((mTimerHandler != NULL) && (InterruptHandler != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+ mTimerHandler = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU
+ frequency.
+
+Arguments:
+ This - Protocol instance structure
+ TimerIndex - Specifies which CPU timer ie requested
+ TimerValue - Pointer to the returned timer value
+ TimerPeriod -
+
+Returns:
+ EFI_SUCCESS - If the CPU timer count was returned.
+ EFI_UNSUPPORTED - If the CPU does not have any readable timers
+ EFI_DEVICE_ERROR - If an error occurred reading the timer.
+ EFI_INVALID_PARAMETER - TimerIndex is not valid
+
+--*/
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex == 0) {
+ *TimerValue = AsmReadTsc ();
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+ Set memory cacheability attributes for given range of memeory
+
+Arguments:
+ This - Protocol instance structure
+ BaseAddress - Specifies the start address of the memory range
+ Length - Specifies the length of the memory range
+ Attributes - The memory cacheability for the memory range
+
+Returns:
+ EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ EFI_UNSUPPORTED - If the desired operation cannot be done
+ EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+#if CPU_EXCEPTION_DEBUG_OUTPUT
+STATIC
+VOID
+DumpExceptionDataDebugOut (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorCodeFlag;
+
+ ErrorCodeFlag = 0x00027d00;
+
+#ifdef EFI32
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ ));
+ if (ErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDTR - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+#else
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! X64 Exception Type - %016lx !!!!\n",
+ (UINT64)InterruptType
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags
+ ));
+ if (ErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GS - %016lx, SS - %016lx\n",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "IDTR - %016lx %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ ));
+#endif
+ return ;
+}
+#endif
+
+STATIC
+UINTN
+SPrint (
+ IN OUT CHAR16 *Buffer,
+ IN CONST CHAR16 *Format,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINTN Index;
+ UINTN Flags;
+ UINTN Width;
+ UINT64 Value;
+
+ VA_START (Marker, Format);
+
+ //
+ // Process the format string. Stop if Buffer is over run.
+ //
+
+ for (Index = 0; *Format != 0; Format++) {
+ if (*Format != L'%') {
+ Buffer[Index++] = *Format;
+ } else {
+
+ //
+ // Now it's time to parse what follows after %
+ // Support: % [ 0 width ] [ l ] x
+ // width - fill 0, to ensure the width of x will be "width"
+ // l - UINT64 instead of UINT32
+ //
+ Width = 0;
+ Flags = 0;
+ Format ++;
+
+ if (*Format == L'0') {
+ Flags |= PREFIX_ZERO;
+ do {
+ Width += Width * 10 + (*Format - L'0');
+ Format ++;
+ } while (*Format >= L'1' && *Format <= L'9');
+ }
+
+ if (*Format == L'l') {
+ Flags |= LONG_TYPE;
+ Format ++;
+ }
+
+
+ switch (*Format) {
+ case 'X':
+ Flags |= PREFIX_ZERO;
+ Width = sizeof (UINT64) * 2;
+ //
+ // break skiped on purpose
+ //
+ case 'x':
+ if ((Flags & LONG_TYPE) == LONG_TYPE) {
+ Value = VA_ARG (Marker, UINT64);
+ } else {
+ Value = VA_ARG (Marker, UINTN);
+ }
+
+ UnicodeValueToString (Buffer+Index, Flags, Value, Width);
+
+ for ( ; Buffer[Index] != L'\0'; Index ++) {
+ }
+
+ break;
+
+ default:
+ //
+ // if the type is unknown print it to the screen
+ //
+ Buffer[Index++] = *Format;
+ }
+ }
+ }
+ Buffer[Index++] = '\0';
+
+ VA_END (Marker);
+ return Index;
+}
+
+STATIC
+VOID
+DumpExceptionDataVgaOut (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN COLUMN_MAX;
+ UINTN ROW_MAX;
+ UINT32 ErrorCodeFlag;
+ CHAR16 *VideoBufferBase;
+ CHAR16 *VideoBuffer;
+ UINTN Index;
+
+ COLUMN_MAX = 80;
+ ROW_MAX = 25;
+ ErrorCodeFlag = 0x00027d00;
+ VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000;
+ VideoBuffer = (CHAR16 *) (UINTN) 0xb8000;
+
+#ifdef EFI32
+ SPrint (
+ VideoBuffer,
+ L"!!!! IA32 Exception Type - %08x !!!!",
+ InterruptType
+ );
+ VideoBuffer += COLUMN_MAX;
+ SPrint (
+ VideoBuffer,
+ L"EIP - %08x, CS - %08x, EFLAGS - %08x",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ );
+ VideoBuffer += COLUMN_MAX;
+ if (ErrorCodeFlag & (1 << InterruptType)) {
+ SPrint (
+ VideoBuffer,
+ L"ExceptionData - %08x",
+ SystemContext.SystemContextIa32->ExceptionData
+ );
+ VideoBuffer += COLUMN_MAX;
+ }
+ SPrint (
+ VideoBuffer,
+ L"EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"GDTR - %08x %08x, IDTR - %08x %08x",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"LDTR - %08x, TR - %08x",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DR6 - %08x, DR7 - %08x",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ );
+ VideoBuffer += COLUMN_MAX;
+#else
+ SPrint (
+ VideoBuffer,
+ L"!!!! X64 Exception Type - %016lx !!!!",
+ (UINT64)InterruptType
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"RIP - %016lx, CS - %016lx, RFLAGS - %016lx",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ if (ErrorCodeFlag & (1 << InterruptType)) {
+ SPrint (
+ VideoBuffer,
+ L"ExceptionData - %016lx",
+ SystemContext.SystemContextX64->ExceptionData
+ );
+ VideoBuffer += COLUMN_MAX;
+ }
+
+ SPrint (
+ VideoBuffer,
+ L"RAX - %016lx, RCX - %016lx, RDX - %016lx",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"RBX - %016lx, RSP - %016lx, RBP - %016lx",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"RSI - %016lx, RDI - %016lx",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"R8 - %016lx, R9 - %016lx, R10 - %016lx",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"R11 - %016lx, R12 - %016lx, R13 - %016lx",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"R14 - %016lx, R15 - %016lx",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DS - %016lx, ES - %016lx, FS - %016lx",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"GS - %016lx, SS - %016lx",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"GDTR - %016lx %016lx, LDTR - %016lx",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"IDTR - %016lx %016lx, TR - %016lx",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"CR0 - %016lx, CR2 - %016lx, CR3 - %016lx",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"CR4 - %016lx, CR8 - %016lx",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DR0 - %016lx, DR1 - %016lx, DR2 - %016lx",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ );
+ VideoBuffer += COLUMN_MAX;
+
+ SPrint (
+ VideoBuffer,
+ L"DR3 - %016lx, DR6 - %016lx, DR7 - %016lx",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ );
+ VideoBuffer += COLUMN_MAX;
+#endif
+
+ for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) {
+ if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) {
+ VideoBufferBase[Index] = 0x0c20;
+ } else {
+ VideoBufferBase[Index] |= 0x0c00;
+ }
+ }
+
+ return ;
+}
+
+#if CPU_EXCEPTION_VGA_SWITCH
+STATIC
+UINT16
+SwitchVideoMode (
+ UINT16 NewVideoMode
+ )
+/*++
+Description
+ Switch Video Mode from current mode to new mode, and return the old mode.
+ Use Thuink
+
+Arguments
+ NewVideoMode - new video mode want to set
+
+Return
+ UINT16 - (UINT16) -1 indicates failure
+ Other value indicates the old mode, which can be used for restore later
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_THUNK_PROTOCOL *LegacyBios;
+ EFI_IA32_REGISTER_SET Regs;
+ UINT16 OriginalVideoMode = (UINT16) -1;
+
+ //
+ // See if the Legacy BIOS Protocol is available
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosThunkProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return OriginalVideoMode;
+ }
+
+ //
+ // VESA SuperVGA BIOS - GET CURRENT VIDEO MODE
+ // AX = 4F03h
+ // Return:AL = 4Fh if function supported
+ // AH = status 00h successful
+ // BX = video mode (see #0082,#0083)
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = 0x4F03;
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ if (Regs.X.AX == 0x004F) {
+ OriginalVideoMode = Regs.X.BX;
+ } else {
+ //
+ // VIDEO - GET CURRENT VIDEO MODE
+ // AH = 0Fh
+ // Return:AH = number of character columns
+ // AL = display mode (see #0009 at AH=00h)
+ // BH = active page (see AH=05h)
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.H.AH = 0x0F;
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ OriginalVideoMode = Regs.H.AL;
+ }
+
+ //
+ // Set new video mode
+ //
+ if (NewVideoMode < 0x100) {
+ //
+ // Set the 80x25 Text VGA Mode: Assume successful always
+ //
+ // VIDEO - SET VIDEO MODE
+ // AH = 00h
+ // AL = desired video mode (see #0009)
+ // Return:AL = video mode flag (Phoenix, AMI BIOS)
+ // 20h mode > 7
+ // 30h modes 0-5 and 7
+ // 3Fh mode 6
+ // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.H.AH = 0x00;
+ Regs.H.AL = (UINT8) NewVideoMode;
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+
+ //
+ // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)
+ // AX = 1114h
+ // BL = block to load
+ // Return:Nothing
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.H.AH = 0x11;
+ Regs.H.AL = 0x14;
+ Regs.H.BL = 0;
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ } else {
+ //
+ // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
+ // AX = 4F02h
+ // BX = mode (see #0082,#0083)
+ // bit 15 set means don't clear video memory
+ // bit 14 set means enable linear framebuffer mode (VBE v2.0+)
+ // Return:AL = 4Fh if function supported
+ // AH = status
+ // 00h successful
+ // 01h failed
+ //
+ gBS->SetMem (&Regs, sizeof (Regs), 0);
+ Regs.X.AX = 0x4F02;
+ Regs.X.BX = NewVideoMode;
+ LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ if (Regs.X.AX != 0x004F) {
+ DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));
+ return (UINT16) -1;
+ }
+ }
+
+ return OriginalVideoMode;
+}
+#endif
+
+VOID
+ExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+#if CPU_EXCEPTION_VGA_SWITCH
+ UINT16 VideoMode;
+#endif
+
+#if CPU_EXCEPTION_DEBUG_OUTPUT
+ DumpExceptionDataDebugOut (InterruptType, SystemContext);
+#endif
+
+#if CPU_EXCEPTION_VGA_SWITCH
+ //
+ // Switch to text mode for RED-SCREEN output
+ //
+ VideoMode = SwitchVideoMode (0x83);
+ if (VideoMode == (UINT16) -1) {
+ DEBUG ((EFI_D_ERROR, "Video Mode Unknown!\n"));
+ }
+#endif
+
+ DumpExceptionDataVgaOut (InterruptType, SystemContext);
+
+ //
+ // Use this macro to hang so that the compiler does not optimize out
+ // the following RET instructions. This allows us to return if we
+ // have a debugger attached.
+ //
+ CpuDeadLoop ();
+
+#if CPU_EXCEPTION_VGA_SWITCH
+ //
+ // Switch back to the old video mode
+ //
+ if (VideoMode != (UINT16)-1) {
+ SwitchVideoMode (VideoMode);
+ }
+#endif
+
+ return ;
+}
+
+VOID
+TimerHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ if (mTimerHandler != NULL) {
+ mTimerHandler (InterruptType, SystemContext);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initialize the state information for the CPU Architectural Protocol
+
+Arguments:
+ ImageHandle of the loaded driver
+ Pointer to the System Table
+
+Returns:
+ EFI_SUCCESS - thread can be successfully created
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ EFI_DEVICE_ERROR - cannot create the thread
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_8259_IRQ Irq;
+ UINT32 InterruptVector;
+
+ //
+ // Find the Legacy8259 protocol.
+ //
+ Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver
+ //
+ Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Reload GDT, IDT
+ //
+ InitDescriptor ();
+
+ //
+ // Install Exception Handler (0x00 ~ 0x1F)
+ //
+ for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) {
+ InstallInterruptHandler (
+ InterruptVector,
+ (VOID (*)(VOID))(UINTN)((UINTN)SystemExceptionHandler + mExceptionCodeSize * InterruptVector)
+ );
+ }
+
+ //
+ // Install Timer Handler
+ //
+ InstallInterruptHandler (mTimerVector, SystemTimerHandler);
+
+ //
+ // BUGBUG: We add all other interrupt vector
+ //
+ for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) {
+ InterruptVector = 0;
+ Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector);
+ ASSERT_EFI_ERROR (Status);
+ InstallInterruptHandler (InterruptVector, SystemTimerHandler);
+ }
+
+ //
+ // Install CPU Architectural Protocol and the thunk protocol
+ //
+ mHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiCpuArchProtocolGuid,
+ &mCpu,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/CpuDxe/Cpu.dxs b/DuetPkg/CpuDxe/Cpu.dxs new file mode 100644 index 0000000000..b07f51b159 --- /dev/null +++ b/DuetPkg/CpuDxe/Cpu.dxs @@ -0,0 +1,25 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Cpu.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+#include "EfiDepex.h"
+#include EFI_PROTOCOL_DEFINITION (Legacy8259)
+
+DEPENDENCY_START
+ EFI_LEGACY_8259_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/CpuDxe/Cpu.inf b/DuetPkg/CpuDxe/Cpu.inf new file mode 100644 index 0000000000..8483aca65a --- /dev/null +++ b/DuetPkg/CpuDxe/Cpu.inf @@ -0,0 +1,53 @@ +#/*++
+#
+# Copyright (c) 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+# Cpu.inf
+#
+# Abstract:
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Cpu
+ FILE_GUID = 10527025-78B2-4d3e-A9DF-41E75C220F5A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeCpu
+
+[Packages]
+ DuetPkg/DuetPkg.dec
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ PrintLib
+ UefiBootServicesTableLib
+
+[Sources.IA32]
+ IA32/CpuInterrupt.asm
+
+[Sources.X64]
+ X64/CpuInterrupt.asm
+
+[Sources.common]
+ Cpu.c
+ CpuDxe.h
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiLegacyBiosThunkProtocolGuid
+ gEfiLegacy8259ProtocolGuid
diff --git a/DuetPkg/CpuDxe/CpuDxe.h b/DuetPkg/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000..5bca0ca10c --- /dev/null +++ b/DuetPkg/CpuDxe/CpuDxe.h @@ -0,0 +1,148 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ CpuDxe.h
+
+Abstract:
+
+--*/
+#ifndef _CPU_DXE_H
+#define _CPU_DXE_H
+
+#include <PiDxe.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/Legacy8259.h>
+
+#include <Protocol/LegacyBios.h>
+#include <Protocol/LegacyBiosThunk.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define CPU_EXCEPTION_DEBUG_OUTPUT 1
+#define CPU_EXCEPTION_VGA_SWITCH 1
+
+#define INTERRUPT_VECTOR_NUMBER 0x100
+
+//
+// Print primitives
+//
+//#define LEFT_JUSTIFY 0x01
+#define PREFIX_SIGN 0x02
+#define PREFIX_BLANK 0x04
+//#define COMMA_TYPE 0x08
+#define LONG_TYPE 0x10
+//#define PREFIX_ZERO 0x20
+#define OUTPUT_UNICODE 0x40
+//#define RADIX_HEX 0x80
+#define FORMAT_UNICODE 0x100
+#define PAD_TO_WIDTH 0x200
+#define ARGUMENT_UNICODE 0x400
+#define PRECISION 0x800
+#define ARGUMENT_REVERSED 0x1000
+
+//
+// Function declarations
+//
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes(
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+VOID
+InstallInterruptHandler (
+ UINTN Vector,
+ VOID (*Handler)(VOID)
+ );
+
+VOID
+SystemExceptionHandler (
+ VOID
+ );
+
+VOID
+SystemTimerHandler (
+ VOID
+ );
+
+VOID
+InitDescriptor (
+ VOID
+ );
+
+#endif
diff --git a/DuetPkg/CpuDxe/Ia32/CpuInterrupt.asm b/DuetPkg/CpuDxe/Ia32/CpuInterrupt.asm new file mode 100644 index 0000000000..cc1402cd9b --- /dev/null +++ b/DuetPkg/CpuDxe/Ia32/CpuInterrupt.asm @@ -0,0 +1,835 @@ + TITLE CpuInterrupt.asm:
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* CpuInterrupt.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+.686p
+.model flat, C
+
+PUBLIC SystemTimerHandler
+PUBLIC SystemExceptionHandler
+EXTERNDEF mExceptionCodeSize:DWORD
+
+.code
+.stack
+.MMX
+.XMM
+
+EXTERN TimerHandler: NEAR
+EXTERN ExceptionHandler: NEAR
+EXTERN mTimerVector: DWORD
+
+mExceptionCodeSize DD 9
+
+InitDescriptor PROC C
+ lea eax, [GDT_BASE] ; EAX=PHYSICAL address of gdt
+ mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
+ lgdt fword ptr [gdtr]
+ lea eax, [IDT_BASE] ; EAX=PHYSICAL address of idt
+ mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
+ lidt fword ptr [idtr]
+ ret
+InitDescriptor ENDP
+
+; VOID
+; InstallInterruptHandler (
+; UINTN Vector,
+; VOID (*Handler)(VOID)
+; )
+InstallInterruptHandler PROC C \
+ Vector:DWORD, \
+ Handler:DWORD
+
+ push edi
+ pushfd ; save eflags
+ cli ; turn off interrupts
+ sub esp, 6 ; open some space on the stack
+ mov edi, esp
+ sidt es:[edi] ; get fword address of IDT
+ mov edi, es:[edi+2] ; move offset of IDT into EDI
+ add esp, 6 ; correct stack
+ mov eax, Vector ; Get vector number
+ shl eax, 3 ; multiply by 8 to get offset
+ add edi, eax ; add to IDT base to get entry
+ mov eax, Handler ; load new address into IDT entry
+ mov word ptr es:[edi], ax ; write bits 15..0 of offset
+ shr eax, 16 ; use ax to copy 31..16 to descriptors
+ mov word ptr es:[edi+6], ax ; write bits 31..16 of offset
+ popfd ; restore flags (possible enabling interrupts)
+ pop edi
+ ret
+
+InstallInterruptHandler ENDP
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit reletive
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+ align 02h
+SystemExceptionHandler PROC
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (32 - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+SystemExceptionHandler ENDP
+
+SystemTimerHandler PROC
+ push 0
+ push mTimerVector
+ JmpCommonIdtEntry
+SystemTimerHandler ENDP
+
+commonIdtEntry:
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+
+ cli
+ push ebp
+ mov ebp, esp
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push eax
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 6 * 4]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 4 * 4]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ push dword ptr [ebp + 3 * 4]
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt fword ptr [esp]
+ sub esp, 8
+ sgdt fword ptr [esp]
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ push dword ptr [ebp + 5 * 4]
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+;; clear Dr7 while executing debugger itself
+ xor eax, eax
+ mov dr7, eax
+
+ mov eax, dr6
+ push eax
+;; insure all status bits in dr6 are clear...
+ xor eax, eax
+ mov dr6, eax
+
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 00000111y ;fxsave [edi]
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 2 * 4]
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ mov eax, dword ptr [ebp + 1 * 4]
+ push eax
+ cmp eax, 32
+ jb CallException
+ call TimerHandler
+ jmp ExceptionDone
+CallException:
+ call ExceptionHandler
+ExceptionDone:
+ add esp, 8
+
+ cli
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 00001110y ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop eax
+ mov dr0, eax
+ pop eax
+ mov dr1, eax
+ pop eax
+ mov dr2, eax
+ pop eax
+ mov dr3, eax
+;; skip restore of dr6. We cleared dr6 during the context save.
+ add esp, 4
+ pop eax
+ mov dr7, eax
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 5 * 4]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 3 * 4]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 4 * 4]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ mov esp, ebp
+ pop ebp
+ add esp, 8
+ iretd
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 02h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dd 0 ; (IDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+REPEAT (32 - 20)
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ENDM
+
+; 72 unspecified descriptors
+ db (72 * 8) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+
+ db (1 * 8) dup(0)
+
+IDT_END:
+
+END
diff --git a/DuetPkg/CpuDxe/x64/CpuInterrupt.asm b/DuetPkg/CpuDxe/x64/CpuInterrupt.asm new file mode 100644 index 0000000000..acf86059c4 --- /dev/null +++ b/DuetPkg/CpuDxe/x64/CpuInterrupt.asm @@ -0,0 +1,949 @@ + TITLE CpuInterrupt.asm:
+;------------------------------------------------------------------------------
+;*
+;* Copyright 2006, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* CpuInterrupt.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+EXTERNDEF mExceptionCodeSize:DWORD
+
+.code
+
+EXTERN TimerHandler: FAR
+EXTERN ExceptionHandler: NEAR
+EXTERN mTimerVector: QWORD
+
+mExceptionCodeSize DD 9
+
+InitDescriptor PROC
+ lea rax, [GDT_BASE] ; RAX=PHYSICAL address of gdt
+ mov qword ptr [gdtr + 2], rax ; Put address of gdt into the gdtr
+ lgdt fword ptr [gdtr]
+ mov rax, 18h
+ mov gs, rax
+ mov fs, rax
+ lea rax, [IDT_BASE] ; RAX=PHYSICAL address of idt
+ mov qword ptr [idtr + 2], rax ; Put address of idt into the idtr
+ lidt fword ptr [idtr]
+ ret
+InitDescriptor ENDP
+
+; VOID
+; InstallInterruptHandler (
+; UINTN Vector, // rcx
+; void (*Handler)(void) // rdx
+; )
+InstallInterruptHandler PROC
+ push rbx
+ pushfq ; save eflags
+ cli ; turn off interrupts
+ sub rsp, 10h ; open some space on the stack
+ mov rbx, rsp
+ sidt [rbx] ; get fword address of IDT
+ mov rbx, [rbx+2] ; move offset of IDT into RBX
+ add rsp, 10h ; correct stack
+ mov rax, rcx ; Get vector number
+ shl rax, 4 ; multiply by 16 to get offset
+ add rbx, rax ; add to IDT base to get entry
+ mov rax, rdx ; load new address into IDT entry
+ mov word ptr [rbx], ax ; write bits 15..0 of offset
+ shr rax, 16 ; use ax to copy 31..16 to descriptors
+ mov word ptr [rbx+6], ax ; write bits 31..16 of offset
+ shr rax, 16 ; use eax to copy 63..32 to descriptors
+ mov dword ptr [rbx+8], eax ; write bits 63..32 of offset
+ popfq ; restore flags (possible enabling interrupts)
+ pop rbx
+ ret
+
+InstallInterruptHandler ENDP
+
+JmpCommonIdtEntry macro
+ ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
+ ; using a 8 bit reletive jump when the entries are
+ ; within 255 bytes of the common entry. This must
+ ; be done to maintain the consistency of the size
+ ; of entry points...
+ db 0e9h ; jmp 16 bit reletive
+ dd commonIdtEntry - $ - 4 ; offset to jump to
+endm
+
+ align 02h
+SystemExceptionHandler PROC
+INT0:
+ push 0h ; push error code place holder on the stack
+ push 0h
+ JmpCommonIdtEntry
+; db 0e9h ; jmp 16 bit reletive
+; dd commonIdtEntry - $ - 4 ; offset to jump to
+
+INT1:
+ push 0h ; push error code place holder on the stack
+ push 1h
+ JmpCommonIdtEntry
+
+INT2:
+ push 0h ; push error code place holder on the stack
+ push 2h
+ JmpCommonIdtEntry
+
+INT3:
+ push 0h ; push error code place holder on the stack
+ push 3h
+ JmpCommonIdtEntry
+
+INT4:
+ push 0h ; push error code place holder on the stack
+ push 4h
+ JmpCommonIdtEntry
+
+INT5:
+ push 0h ; push error code place holder on the stack
+ push 5h
+ JmpCommonIdtEntry
+
+INT6:
+ push 0h ; push error code place holder on the stack
+ push 6h
+ JmpCommonIdtEntry
+
+INT7:
+ push 0h ; push error code place holder on the stack
+ push 7h
+ JmpCommonIdtEntry
+
+INT8:
+; Double fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 8h
+ JmpCommonIdtEntry
+
+INT9:
+ push 0h ; push error code place holder on the stack
+ push 9h
+ JmpCommonIdtEntry
+
+INT10:
+; Invalid TSS causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 10
+ JmpCommonIdtEntry
+
+INT11:
+; Segment Not Present causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 11
+ JmpCommonIdtEntry
+
+INT12:
+; Stack fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 12
+ JmpCommonIdtEntry
+
+INT13:
+; GP fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 13
+ JmpCommonIdtEntry
+
+INT14:
+; Page fault causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 14
+ JmpCommonIdtEntry
+
+INT15:
+ push 0h ; push error code place holder on the stack
+ push 15
+ JmpCommonIdtEntry
+
+INT16:
+ push 0h ; push error code place holder on the stack
+ push 16
+ JmpCommonIdtEntry
+
+INT17:
+; Alignment check causes an error code to be pushed so no phony push necessary
+ nop
+ nop
+ push 17
+ JmpCommonIdtEntry
+
+INT18:
+ push 0h ; push error code place holder on the stack
+ push 18
+ JmpCommonIdtEntry
+
+INT19:
+ push 0h ; push error code place holder on the stack
+ push 19
+ JmpCommonIdtEntry
+
+INTUnknown:
+REPEAT (32 - 20)
+ push 0h ; push error code place holder on the stack
+; push xxh ; push vector number
+ db 06ah
+ db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
+ JmpCommonIdtEntry
+ENDM
+SystemExceptionHandler ENDP
+
+SystemTimerHandler PROC
+ push 0
+ push mTimerVector
+ JmpCommonIdtEntry
+SystemTimerHandler ENDP
+
+commonIdtEntry:
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+
+ cli
+ push rbp
+ mov rbp, rsp
+
+ ;
+ ; Since here the stack pointer is 16-byte aligned, so
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ ; is 16-byte aligned
+ ;
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+ push rax
+ push rcx
+ push rdx
+ push rbx
+ push qword ptr [rbp + 6 * 8] ; RSP
+ push qword ptr [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word ptr [rbp + 7 * 8]
+ push rax ; for ss
+ movzx rax, word ptr [rbp + 4 * 8]
+ push rax ; for cs
+ mov rax, ds
+ push rax
+ mov rax, es
+ push rax
+ mov rax, fs
+ push rax
+ mov rax, gs
+ push rax
+
+;; UINT64 Rip;
+ push qword ptr [rbp + 3 * 8]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ sub rsp, 16
+ sidt fword ptr [rsp]
+ sub rsp, 16
+ sgdt fword ptr [rsp]
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword ptr [rbp + 5 * 8]
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ mov rax, cr8
+ push rax
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ xor rax, rax
+ push rax
+ mov rax, cr0
+ push rax
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+;; clear Dr7 while executing debugger itself
+ xor rax, rax
+ mov dr7, rax
+
+ mov rax, dr6
+ push rax
+;; insure all status bits in dr6 are clear...
+ xor rax, rax
+ mov dr6, rax
+
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 2 * 8]
+
+;; call into exception handler
+;; Prepare parameter and call
+ mov rcx, qword ptr [rbp + 1 * 8]
+ mov rdx, rsp
+ ;
+ ; Per X64 calling convention, allocate maximum parameter stack space
+ ; and make sure RSP is 16-byte aligned
+ ;
+ sub rsp, 4 * 8 + 8
+ cmp rcx, 32
+ jb CallException
+ call TimerHandler
+ jmp ExceptionDone
+CallException:
+ call ExceptionHandler
+ExceptionDone:
+ add rsp, 4 * 8 + 8
+
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop rax
+ mov dr0, rax
+ pop rax
+ mov dr1, rax
+ pop rax
+ mov dr2, rax
+ pop rax
+ mov dr3, rax
+;; skip restore of dr6. We cleared dr6 during the context save.
+ add rsp, 8
+ pop rax
+ mov dr7, rax
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; not for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+ pop rax
+ mov cr8, rax
+
+;; UINT64 RFlags;
+ pop qword ptr [rbp + 5 * 8]
+
+;; UINT64 Ldtr, Tr;
+;; UINT64 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add rsp, 48
+
+;; UINT64 Rip;
+ pop qword ptr [rbp + 3 * 8]
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ pop rax
+ ; mov gs, rax ; not for gs
+ pop rax
+ ; mov fs, rax ; not for fs
+ ; (X64 will not use fs and gs, so we do not restore it)
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 4 * 8] ; for cs
+ pop qword ptr [rbp + 7 * 8] ; for ss
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pop rdi
+ pop rsi
+ add rsp, 8 ; not for rbp
+ pop qword ptr [rbp + 6 * 8] ; for rsp
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rax
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16
+ iretq
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; data
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 010h
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dq 0 ; (GDT base gets set above)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; global descriptor table (GDT)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ align 010h
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0x0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+;
+; system data segment descriptor
+;
+SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0CFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+;
+; system code segment descriptor
+;
+SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
+ db 0AFh ; G | D | L | AVL | Segment [19..16]
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+ align 02h
+
+
+
+idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
+ dq 0 ; (IDT base gets set above)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; interrupt descriptor table (IDT)
+;
+; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
+; mappings. This implementation only uses the system timer and all other
+; IRQs will remain masked. The descriptors for vectors 33+ are provided
+; for convenience.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;idt_tag db "IDT",0
+ align 02h
+
+public IDT_BASE
+IDT_BASE:
+; divide by zero (INT 0)
+DIV_ZERO_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; debug exception (INT 1)
+DEBUG_EXCEPT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; NMI (INT 2)
+NMI_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; soft breakpoint (INT 3)
+BREAKPOINT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; overflow (INT 4)
+OVERFLOW_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; bounds check (INT 5)
+BOUNDS_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid opcode (INT 6)
+INVALID_OPCODE_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; device not available (INT 7)
+DEV_NOT_AVAIL_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; double fault (INT 8)
+DOUBLE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Coprocessor segment overrun - reserved (INT 9)
+RSVD_INTR_SEL1 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; invalid TSS (INT 0ah)
+INVALID_TSS_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; segment not present (INT 0bh)
+SEG_NOT_PRESENT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; stack fault (INT 0ch)
+STACK_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; general protection (INT 0dh)
+GP_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; page fault (INT 0eh)
+PAGE_FAULT_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Intel reserved - do not use (INT 0fh)
+RSVD_INTR_SEL2 equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; floating point error (INT 10h)
+FLT_POINT_ERR_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; alignment check (INT 11h)
+ALIGNMENT_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; machine check (INT 12h)
+MACHINE_CHECK_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; SIMD floating-point exception (INT 13h)
+SIMD_EXCEPTION_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+REPEAT (32 - 20)
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+ENDM
+
+; 72 unspecified descriptors
+ db (72 * 16) dup(0)
+
+; IRQ 0 (System timer) - (INT 68h)
+IRQ0_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 1 (8042 Keyboard controller) - (INT 69h)
+IRQ1_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
+IRQ2_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 3 (COM 2) - (INT 6bh)
+IRQ3_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 4 (COM 1) - (INT 6ch)
+IRQ4_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 5 (LPT 2) - (INT 6dh)
+IRQ5_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 6 (Floppy controller) - (INT 6eh)
+IRQ6_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 7 (LPT 1) - (INT 6fh)
+IRQ7_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 8 (RTC Alarm) - (INT 70h)
+IRQ8_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 9 - (INT 71h)
+IRQ9_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 10 - (INT 72h)
+IRQ10_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 11 - (INT 73h)
+IRQ11_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 12 (PS/2 mouse) - (INT 74h)
+IRQ12_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 13 (Floating point error) - (INT 75h)
+IRQ13_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 14 (Secondary IDE) - (INT 76h)
+IRQ14_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+; IRQ 15 (Primary IDE) - (INT 77h)
+IRQ15_SEL equ $-IDT_BASE
+ dw 0 ; offset 15:0
+ dw SYS_CODE64_SEL ; selector 15:0
+ db 0 ; 0 for interrupt gate
+ db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
+ dw 0 ; offset 31:16
+ dd 0 ; offset 63:32
+ dd 0 ; 0 for reserved
+
+ db (1 * 16) dup(0)
+
+IDT_END:
+
+ align 02h
+
+END
diff --git a/DuetPkg/CpuIoDxe/CpuIo.c b/DuetPkg/CpuIoDxe/CpuIo.c new file mode 100644 index 0000000000..f95697130c --- /dev/null +++ b/DuetPkg/CpuIoDxe/CpuIo.c @@ -0,0 +1,533 @@ +/*++
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ CpuIo.c
+
+Abstract:
+
+ This is the code that publishes the CPU I/O Protocol.
+ The intent herein is to have a single I/O service that can load
+ as early as possible, extend into runtime, and be layered upon by
+ the implementations of architectural protocols and the PCI Root
+ Bridge I/O Protocol.
+
+--*/
+
+#include "CpuIo.h"
+#include "CpuIoAccess.h"
+
+#define IA32_MAX_IO_ADDRESS 0xFFFF
+
+EFI_CPU_IO_PROTOCOL mCpuIo = {
+ {
+ CpuMemoryServiceRead,
+ CpuMemoryServiceWrite
+ },
+ {
+ CpuIoServiceRead,
+ CpuIoServiceWrite
+ }
+};
+
+STATIC
+EFI_STATUS
+CpuIoMemRW (
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN DestinationStrideFlag,
+ OUT PTR Destination,
+ IN BOOLEAN SourceStrideFlag,
+ IN PTR Source
+ )
+/*++
+
+Routine Description:
+
+ Private service to perform memory mapped I/O read/write
+
+Arguments:
+
+ Width - Width of the memory mapped I/O operation
+ Count - Count of the number of accesses to perform
+ DestinationStrideFlag - Boolean flag indicates if the destination is to be incremented
+ Destination - Destination of the memory mapped I/O operation
+ SourceStrideFlag - Boolean flag indicates if the source is to be incremented
+ Source - Source of the memory mapped I/O operation
+
+Returns:
+
+ EFI_SUCCESS - Successful operation
+ EFI_INVALID_PARAMETER - Width is invalid
+
+--*/
+{
+ UINTN Stride;
+ UINTN DestinationStride;
+ UINTN SourceStride;
+
+ Width = Width & 0x03;
+ Stride = (UINTN)1 << Width;
+ DestinationStride = DestinationStrideFlag ? Stride : 0;
+ SourceStride = SourceStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiCpuIoWidthUint8:
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
+ MemoryFence();
+ *Destination.ui8 = *Source.ui8;
+ MemoryFence();
+ }
+ break;
+
+ case EfiCpuIoWidthUint16:
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
+ MemoryFence ();
+ *Destination.ui16 = *Source.ui16;
+ MemoryFence ();
+ }
+ break;
+
+ case EfiCpuIoWidthUint32:
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
+ MemoryFence ();
+ *Destination.ui32 = *Source.ui32;
+ MemoryFence ();
+ }
+ break;
+
+ case EfiCpuIoWidthUint64:
+ for (; Count > 0; Count--, Destination.buf += DestinationStride, Source.buf += SourceStride) {
+ MemoryFence ();
+ *Destination.ui64 = *Source.ui64;
+ MemoryFence ();
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the memory mapped I/O read service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the memory mapped I/O operation
+ Address - Base address of the memory mapped I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the destination buffer to store the results
+
+Returns:
+
+ EFI_SUCCESS - The data was read.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+{
+ PTR Source;
+ PTR Destination;
+ EFI_STATUS Status;
+
+ Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Destination.buf = Buffer;
+ Source.buf = (VOID *) (UINTN) Address;
+
+ if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {
+ return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);
+ }
+
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the memory mapped I/O write service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the memory mapped I/O operation
+ Address - Base address of the memory mapped I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the source buffer from which to write data
+
+Returns:
+
+ EFI_SUCCESS - The data was written.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+{
+ PTR Source;
+ PTR Destination;
+ EFI_STATUS Status;
+
+ Status = CpuIoCheckParameter (Width, Address, Count, Buffer, EFI_MAX_ADDRESS);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Destination.buf = (VOID *) (UINTN) Address;
+ Source.buf = Buffer;
+
+ if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) {
+ return CpuIoMemRW (Width, Count, TRUE, Destination, TRUE, Source);
+ }
+
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ return CpuIoMemRW (Width, Count, FALSE, Destination, TRUE, Source);
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ return CpuIoMemRW (Width, Count, TRUE, Destination, FALSE, Source);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ OUT VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the port I/O read service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the port I/O operation
+ Address - Base address of the port I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the destination buffer to store the results
+
+Returns:
+
+ EFI_SUCCESS - The data was read.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+{
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN Address;
+ PTR Buffer;
+ EFI_STATUS Status;
+
+ Buffer.buf = (UINT8 *) UserBuffer;
+
+ if (Width >= EfiCpuIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Address = (UINTN) UserAddress;
+ InStride = (UINTN)1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ Width = Width & 0x03;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiCpuIoWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ *Buffer.ui8 = CpuIoRead8 ((UINT16) Address);
+ }
+ break;
+
+ case EfiCpuIoWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ *Buffer.ui16 = CpuIoRead16 ((UINT16) Address);
+ }
+ break;
+
+ case EfiCpuIoWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ *Buffer.ui32 = CpuIoRead32 ((UINT16) Address);
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the port I/O write service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the port I/O operation
+ Address - Base address of the port I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the source buffer from which to write data
+
+Returns:
+
+ EFI_SUCCESS - The data was written.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+{
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN Address;
+ PTR Buffer;
+ EFI_STATUS Status;
+
+ Buffer.buf = (UINT8 *) UserBuffer;
+
+ if (Width >= EfiCpuIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CpuIoCheckParameter (Width, UserAddress, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Address = (UINTN) UserAddress;
+ InStride = (UINTN)1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ Width = Width & 0x03;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiCpuIoWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ CpuIoWrite8 ((UINT16) Address, *Buffer.ui8);
+ }
+ break;
+
+ case EfiCpuIoWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ CpuIoWrite16 ((UINT16) Address, *Buffer.ui16);
+ }
+ break;
+
+ case EfiCpuIoWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ CpuIoWrite32 ((UINT16) Address, *Buffer.ui32);
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuIoInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ CpuIo driver entry point.
+
+Arguments:
+
+ ImageHandle - The firmware allocated handle for the EFI image.
+ SystemTable - A pointer to the EFI System Table.
+
+Returns:
+
+ EFI_SUCCESS - The driver was initialized.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ Status = SystemTable->BootServices->InstallProtocolInterface (
+ &Handle,
+ &gEfiCpuIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mCpuIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+CpuIoCheckParameter (
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer,
+ IN UINT64 Limit
+ )
+/*++
+
+Routine Description:
+
+ Check the validation of parameters for CPU I/O interface functions.
+
+Arguments:
+
+ Width - Width of the Memory Access
+ Address - Address of the Memory access
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the buffer to read from memory
+ Buffer - Memory buffer for the I/O operation
+ Limit - Maximum address supported
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is NULL
+ EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid
+ EFI_UNSUPPORTED - The memory buffer is not aligned
+ EFI_SUCCESS - Parameters are OK
+
+--*/
+{
+ UINTN AlignMask;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For FiFo type, the target address won't increase during the access,
+ // so treat count as 1
+ //
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width = Width & 0x03;
+ if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AlignMask = ((UINTN)1 << Width) - 1;
+ if ((UINTN) Buffer & AlignMask) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/CpuIoDxe/CpuIo.h b/DuetPkg/CpuIoDxe/CpuIo.h new file mode 100644 index 0000000000..622cc1560f --- /dev/null +++ b/DuetPkg/CpuIoDxe/CpuIo.h @@ -0,0 +1,245 @@ +/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ CpuIo.h
+
+Abstract:
+ *.h file for the driver
+
+ Note: the EFIAPI on the CpuIo functions is used to glue MASM (assembler) code
+ into C code. By making the MASM functions EFIAPI it ensures that a standard
+ C calling convention is assumed by the compiler, reguardless of the compiler
+ flags.
+
+
+--*/
+
+#ifndef _CPU_IO_H
+#define _CPU_IO_H
+
+#include <PiDxe.h>
+
+#include <Protocol/CpuIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#define VOLATILE volatile
+
+typedef union {
+ UINT8 VOLATILE *buf;
+ UINT8 VOLATILE *ui8;
+ UINT16 VOLATILE *ui16;
+ UINT32 VOLATILE *ui32;
+ UINT64 VOLATILE *ui64;
+ UINTN VOLATILE ui;
+} PTR;
+
+EFI_STATUS
+EFIAPI
+CpuIoInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ CpuIo driver entry point.
+
+Arguments:
+
+ ImageHandle - The firmware allocated handle for the EFI image.
+ SystemTable - A pointer to the EFI System Table.
+
+Returns:
+
+ EFI_SUCCESS - The driver was initialized.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the memory mapped I/O read service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the memory mapped I/O operation
+ Address - Base address of the memory mapped I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the destination buffer to store the results
+
+Returns:
+
+ EFI_SUCCESS - The data was read.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the memory mapped I/O write service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the memory mapped I/O operation
+ Address - Base address of the memory mapped I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the source buffer from which to write data
+
+Returns:
+
+ EFI_SUCCESS - The data was written.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ OUT VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the port I/O read service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the port I/O operation
+ Address - Base address of the port I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the destination buffer to store the results
+
+Returns:
+
+ EFI_SUCCESS - The data was read.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN EFI_CPU_IO_PROTOCOL *This,
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN VOID *UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Perform the port I/O write service
+
+Arguments:
+
+ This - Pointer to an instance of the CPU I/O Protocol
+ Width - Width of the port I/O operation
+ Address - Base address of the port I/O operation
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the source buffer from which to write data
+
+Returns:
+
+ EFI_SUCCESS - The data was written.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
+ EFI_UNSUPPORTED - The address range specified by Address, Width,
+ and Count is not valid.
+
+--*/
+;
+
+EFI_STATUS
+CpuIoCheckParameter (
+ IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer,
+ IN UINT64 Limit
+ )
+/*++
+
+Routine Description:
+
+ Check the validation of parameters for CPU I/O interface functions.
+
+Arguments:
+
+ Width - Width of the Memory Access
+ Address - Address of the Memory access
+ Count - Count of the number of accesses to perform
+ Buffer - Pointer to the buffer to read from memory
+ Buffer - Memory buffer for the I/O operation
+ Limit - Maximum address supported
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is NULL
+ EFI_UNSUPPORTED - The address range specified by Width, Address and Count is invalid
+ EFI_UNSUPPORTED - The memory buffer is not aligned
+ EFI_SUCCESS - Parameters are OK
+
+--*/
+;
+
+#endif
diff --git a/DuetPkg/CpuIoDxe/CpuIo.inf b/DuetPkg/CpuIoDxe/CpuIo.inf new file mode 100644 index 0000000000..9deda69ce0 --- /dev/null +++ b/DuetPkg/CpuIoDxe/CpuIo.inf @@ -0,0 +1,56 @@ +#/*++
+#
+# Copyright (c) 2004, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# CpuIo.inf
+#
+# Abstract:
+#
+# Component description file for CpuIo module
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuIo
+ FILE_GUID = BAE7599F-3C6B-43b7-BDF0-9CE07AA91AA6
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = CpuIoInitialize
+
+[Packages]
+ DuetPkg/DuetPkg.dec
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Sources.common]
+ CpuIo.c
+ CpuIo.h
+ CpuIoAccess.h
+
+[Sources.IA32]
+ IA32\CpuIoAccess.asm
+
+[Sources.X64]
+ X64\CpuIoAccess.asm
+
+[Protocols]
+ gEfiCpuIoProtocolGuid
\ No newline at end of file diff --git a/DuetPkg/CpuIoDxe/CpuIoAccess.h b/DuetPkg/CpuIoDxe/CpuIoAccess.h new file mode 100644 index 0000000000..3983ec8f73 --- /dev/null +++ b/DuetPkg/CpuIoDxe/CpuIoAccess.h @@ -0,0 +1,216 @@ +/*++
+#
+# Copyright (c) 2004, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ CpuIoAccess.h
+
+Abstract:
+
+--*/
+
+#ifndef _CPU_IO_ACCESS_H
+#define _CPU_IO_ACCESS_H
+
+
+#define IA32API __cdecl
+
+UINT8
+IA32API
+CpuIoRead8 (
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O read port
+Arguments:
+ Port: - Port number to read
+Returns:
+ Return read 8 bit value
+--*/
+UINT16
+IA32API
+CpuIoRead16 (
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O read port
+Arguments:
+ Port: - Port number to read
+Returns:
+ Return read 16 bit value
+--*/
+UINT32
+IA32API
+CpuIoRead32 (
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O read port
+Arguments:
+ Port: - Port number to read
+Returns:
+ Return read 32 bit value
+--*/
+VOID
+IA32API
+CpuIoWrite8 (
+ IN UINT16 Port,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+ Data - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O write 8 bit data to port
+Arguments:
+ Port: - Port number to read
+ Data: - Data to write to the Port
+Returns:
+ None
+--*/
+VOID
+IA32API
+CpuIoWrite16 (
+ IN UINT16 Port,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+ Data - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O write 16 bit data to port
+Arguments:
+ Port: - Port number to read
+ Data: - Data to write to the Port
+Returns:
+ None
+--*/
+VOID
+IA32API
+CpuIoWrite32 (
+ IN UINT16 Port,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Port - GC_TODO: add argument description
+ Data - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+/*++
+Routine Description:
+ Cpu I/O write 32 bit data to port
+Arguments:
+ Port: - Port number to read
+ Data: - Data to write to the Port
+Returns:
+ None
+--*/
+#endif
diff --git a/DuetPkg/CpuIoDxe/Ia32/CpuIoAccess.asm b/DuetPkg/CpuIoDxe/Ia32/CpuIoAccess.asm new file mode 100644 index 0000000000..07b14ea554 --- /dev/null +++ b/DuetPkg/CpuIoDxe/Ia32/CpuIoAccess.asm @@ -0,0 +1,120 @@ + title CpuIoAccess.asm
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2005, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* Module Name:
+;* CpuIoAccess.asm
+;*
+;* Abstract:
+;* Supports IA32 CPU IO operation
+;*
+;------------------------------------------------------------------------------
+;
+;
+;------------------------------------------------------------------------------
+
+ .686
+ .MODEL FLAT,C
+ .CODE
+
+
+UINT8 TYPEDEF BYTE
+UINT16 TYPEDEF WORD
+UINT32 TYPEDEF DWORD
+UINT64 TYPEDEF QWORD
+UINTN TYPEDEF UINT32
+
+
+
+;------------------------------------------------------------------------------
+; UINT8
+; CpuIoRead8 (
+; IN UINT16 Port
+; )
+;------------------------------------------------------------------------------
+CpuIoRead8 PROC PUBLIC Port:UINT16
+ mov dx, Port
+ in al, dx
+ ret
+CpuIoRead8 ENDP
+
+;------------------------------------------------------------------------------
+; UINT16
+; CpuIoRead16 (
+; IN UINT16 Port
+; )
+;------------------------------------------------------------------------------
+CpuIoRead16 PROC PUBLIC Port:UINT16
+ mov dx, Port
+ in ax, dx
+ ret
+CpuIoRead16 ENDP
+
+;------------------------------------------------------------------------------
+; UINT32
+; CpuIoRead32 (
+; IN UINT16 Port
+; )
+;------------------------------------------------------------------------------
+CpuIoRead32 PROC PUBLIC Port:UINT16
+ mov dx, Port
+ in eax, dx
+ ret
+CpuIoRead32 ENDP
+
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite8 (
+; IN UINT16 Port,
+; IN UINT32 Data
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite8 PROC PUBLIC Port:UINT16, Data:UINT32
+ mov eax, Data
+ mov dx, Port
+ out dx, al
+ ret
+CpuIoWrite8 ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite16 (
+; IN UINT16 Port,
+; IN UINT32 Data
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite16 PROC PUBLIC Port:UINT16, Data:UINT32
+ mov eax, Data
+ mov dx, Port
+ out dx, ax
+ ret
+CpuIoWrite16 ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite32 (
+; IN UINT16 Port,
+; IN UINT32 Data
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite32 PROC PUBLIC Port:UINT16, Data:UINT32
+ mov eax, Data
+ mov dx, Port
+ out dx, eax
+ ret
+CpuIoWrite32 ENDP
+
+
+END
\ No newline at end of file diff --git a/DuetPkg/CpuIoDxe/Ia32CpuIo.dxs b/DuetPkg/CpuIoDxe/Ia32CpuIo.dxs new file mode 100644 index 0000000000..874f333985 --- /dev/null +++ b/DuetPkg/CpuIoDxe/Ia32CpuIo.dxs @@ -0,0 +1,26 @@ +/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Ia32CpuIo.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+
+#include "EfiDepex.h"
+
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/DuetPkg/CpuIoDxe/x64/CpuIoAccess.asm b/DuetPkg/CpuIoDxe/x64/CpuIoAccess.asm new file mode 100644 index 0000000000..fa71762877 --- /dev/null +++ b/DuetPkg/CpuIoDxe/x64/CpuIoAccess.asm @@ -0,0 +1,111 @@ + title CpuIoAccess.asm
+
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2005 - 2007, Intel Corporation
+;* All rights reserved. This program and the accompanying materials
+;* are licensed and made available under the terms and conditions of the BSD License
+;* which accompanies this distribution. The full text of the license may be found at
+;* http://opensource.org/licenses/bsd-license.php
+;*
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;*
+;* Module Name:
+;* CpuIoAccess.asm
+;*
+;* Abstract:
+;* Supports x64 CPU IO operation
+;*
+;------------------------------------------------------------------------------
+;
+;
+;
+; Abstract:
+;
+;
+;------------------------------------------------------------------------------
+
+.CODE
+
+;------------------------------------------------------------------------------
+; UINT8
+; CpuIoRead8 (
+; UINT16 Port // rcx
+; )
+;------------------------------------------------------------------------------
+CpuIoRead8 PROC PUBLIC
+ xor eax, eax
+ mov dx, cx
+ in al, dx
+ ret
+CpuIoRead8 ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite8 (
+; UINT16 Port, // rcx
+; UINT32 Data // rdx
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite8 PROC PUBLIC
+ mov eax, edx
+ mov dx, cx
+ out dx, al
+ ret
+CpuIoWrite8 ENDP
+
+;------------------------------------------------------------------------------
+; UINT16
+; CpuIoRead16 (
+; UINT16 Port // rcx
+; )
+;------------------------------------------------------------------------------
+CpuIoRead16 PROC PUBLIC
+ xor eax, eax
+ mov dx, cx
+ in ax, dx
+ ret
+CpuIoRead16 ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite16 (
+; UINT16 Port, // rcx
+; UINT32 Data // rdx
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite16 PROC PUBLIC
+ mov eax, edx
+ mov dx, cx
+ out dx, ax
+ ret
+CpuIoWrite16 ENDP
+
+;------------------------------------------------------------------------------
+; UINT32
+; CpuIoRead32 (
+; UINT16 Port // rcx
+; )
+;------------------------------------------------------------------------------
+CpuIoRead32 PROC PUBLIC
+ mov dx, cx
+ in eax, dx
+ ret
+CpuIoRead32 ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuIoWrite32 (
+; UINT16 Port, // rcx
+; UINT32 Data // rdx
+; )
+;------------------------------------------------------------------------------
+CpuIoWrite32 PROC PUBLIC
+ mov eax, edx
+ mov dx, cx
+ out dx, eax
+ ret
+CpuIoWrite32 ENDP
+
+END
diff --git a/DuetPkg/DuetPkg.dec b/DuetPkg/DuetPkg.dec index 77a368c69e..7bea09ebb1 100644 --- a/DuetPkg/DuetPkg.dec +++ b/DuetPkg/DuetPkg.dec @@ -9,4 +9,8 @@ [Guids.common]
gEfiPciExpressBaseAddressGuid = {0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0 }}
- 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 }}
+ gEfiFlashMapHobGuid = { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 }}
+
+[Protocols.common]
+ gEfiLegacyBiosThunkProtocolGuid = {0x4c51a7ba, 0x7195, 0x442d, {0x87, 0x92, 0xbe, 0xea, 0x6e, 0x2f, 0xf6, 0xec}}
\ No newline at end of file diff --git a/DuetPkg/DuetPkg.dsc b/DuetPkg/DuetPkg.dsc index 3cd902fc83..d47bad9382 100644 --- a/DuetPkg/DuetPkg.dsc +++ b/DuetPkg/DuetPkg.dsc @@ -9,7 +9,7 @@ SUPPORTED_ARCHITECTURES = IA32|X64
BUILD_TARGETS = DEBUG
SKUID_IDENTIFIER = DEFAULT
- #FLASH_DEFINITION = DuetPkg/DuetPkg.fdf
+ FLASH_DEFINITION = DuetPkg/DuetPkg.fdf
[LibraryClasses.common]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
@@ -26,15 +26,106 @@ HiiLib|MdePkg/Library/HiiLib/HiiLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ BaseUefiTianoDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+ PlatformBdsLib|DuetPkg/Library/DuetBdsLib/PlatformBds.inf
+ IfrSupportLib|MdePkg/Library/IfrSupportLib/IfrSupportLib.inf
+ ExtendedIfrSupportLib|MdeModulePkg/Library/ExtendedIfrSupportLib/ExtendedIfrSupportLib.inf
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ GraphicsLib|MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf
+ ExtendedHiiLib|MdeModulePkg/Library/ExtendedHiiLib/ExtendedHiiLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ OemHookStatusCodeLib|IntelFrameworkModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
[LibraryClasses.common.DXE_DRIVER]
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+ SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+ IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf
+ UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+ SerialPortLib|MdePkg/Library/SerialPortLibNull/SerialPortLibNull.inf
+ IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf
+ TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
-[Components.IA32]
+[LibraryClasses.common.UEFI_DRIVER]
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
+
+[Components.common]
DuetPkg/DxeIpl/DxeIpl.inf
+
+ MdeModulePkg/Core/Dxe/DxeMain.inf
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+
+ DuetPkg/FSVariable/FSVariable.inf
+
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+ IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+
+ IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+
DuetPkg/DataHubGenDxe/DataHubGen.inf
+ DuetPkg/FvbRuntimeService/DUETFwh.inf
+ DuetPkg/EfiLdr/EfiLdr.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ DuetPkg/CpuIoDxe/CpuIo.inf
+ DuetPkg/CpuDxe/Cpu.inf
+
+ IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf
+ DuetPkg/KbcResetDxe/Reset.inf
+ DuetPkg/LegacyMetronome/Metronome.inf
-[Components.X64]
- DuetPkg/DxeIpl/DxeIpl.inf
- DuetPkg/DataHubGenDxe/DataHubGen.inf
\ No newline at end of file + DuetPkg/PcRtc/RealTimeClock.inf
+ DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+ IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
+
+ # IDE Support
+ #IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
+
+ # Usb Support
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+
+ # ISA Support
+ DuetPkg/IsaAcpiDxe/IsaAcpi.inf
+ DuetPkg/BootSector/BootSector.inf
diff --git a/DuetPkg/DuetPkg.fdf b/DuetPkg/DuetPkg.fdf new file mode 100644 index 0000000000..faa2ca0388 --- /dev/null +++ b/DuetPkg/DuetPkg.fdf @@ -0,0 +1,189 @@ +# This is NT32 FDF file with UEFI HII features enabled
+#
+# Copyright (c) 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into the Flash Device Image. Each FD section
+# defines one flash "device" image. A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash" image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+[FD.DuetMainFd]
+BaseAddress = 0x0 #The base address of the FLASH Device.
+Size = 0x002a0000 #The size in bytes of the FLASH Device
+ErasePolarity = 1
+BlockSize = 0x10000
+NumBlocks = 0x2a
+
+0x00000000|0x002a0000
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.DuetEfiMainFv]
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+
+INF DuetPkg/FSVariable/FSVariable.inf
+
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+
+INF IntelFrameworkModulePkg/Universal/DataHubDxe/DataHubDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+
+INF DuetPkg/DataHubGenDxe/DataHubGen.inf
+INF DuetPkg/FvbRuntimeService/DUETFwh.inf
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF DuetPkg/CpuIoDxe/CpuIo.inf
+INF DuetPkg/CpuDxe/Cpu.inf
+
+INF IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf
+INF DuetPkg/KbcResetDxe/Reset.inf
+INF DuetPkg/LegacyMetronome/Metronome.inf
+
+INF DuetPkg/PcRtc/RealTimeClock.inf
+INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+INF IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf
+
+ # IDE Support
+ #IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
+
+ # Usb Support
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+
+ # ISA Support
+INF DuetPkg/IsaAcpiDxe/IsaAcpi.inf
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+ FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+ PEI_DEPEX PEI_DEPEX Optional |.depex
+ GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ COMPRESS PI_STD {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ COMPRESS PI_STD {
+ GUIDED {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ COMPRESS PI_STD {
+ GUIDED {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ COMPRESS PI_STD {
+ GUIDED {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ COMPRESS PI_STD {
+ GUIDED {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+ }
+ }
diff --git a/DuetPkg/DxeIpl/DxeIpl.inf b/DuetPkg/DxeIpl/DxeIpl.inf index 0e6d1fb585..bea8730a2e 100644 --- a/DuetPkg/DxeIpl/DxeIpl.inf +++ b/DuetPkg/DxeIpl/DxeIpl.inf @@ -20,7 +20,7 @@ INF_VERSION = 0x00010005
BASE_NAME = DxeIpl
FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC
- MODULE_TYPE = USER_DEFINED
+ MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
@@ -38,6 +38,7 @@ BaseMemoryLib
PrintLib
ReportStatusCodeLib
+ UefiDriverEntryPoint
[Sources.common]
DxeIpl.h
@@ -65,9 +66,9 @@ Ia32\Paging.c
Ia32\VirtualMemory.h
-[BuildOptions.common]
+#[BuildOptions.common]
#MSFT:*_*_IA32_DLINK_FLAGS = /out:"$(BIN_DIR)\SecMain.exe" /base:0x10000000 /pdb:"$(BIN_DIR)\SecMain.pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib
- MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
- MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
- MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
- MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny
+ #MSFT:*_*_IA32_CC_FLAGS = /nologo /W4 /WX /Gy /c /D UNICODE /Od /FI$(DEST_DIR_DEBUG)/AutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
+ #MSFT:*_*_IA32_PP_FLAGS = /nologo /E /TC /FI$(DEST_DIR_DEBUG)/AutoGen.h
+ #MSFT:*_*_IA32_ASM_FLAGS = /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi
+ #MSFT:*_*_IA32_ASMLINK_FLAGS = /link /nologo /tiny
diff --git a/DuetPkg/Include/EfiFlashMap.h b/DuetPkg/Include/EfiFlashMap.h index 5dfad52205..240789c4c6 100644 --- a/DuetPkg/Include/EfiFlashMap.h +++ b/DuetPkg/Include/EfiFlashMap.h @@ -22,7 +22,6 @@ Abstract: #ifndef _EFI_FLASHMAP_H_
#define _EFI_FLASHMAP_H_
-
//
// Definition for flash map GUIDed HOBs
//
@@ -59,6 +58,7 @@ typedef UINT8 EFI_FLASH_AREA_TYPE; // An individual sub-area Entry.
// A single flash area may consist of more than one sub-area.
//
+/**
typedef struct {
EFI_FLASH_AREA_ATTRIBUTES Attributes;
UINT32 Reserved;
@@ -121,6 +121,32 @@ typedef struct { UINT8 Reserved[3];
EFI_GUID AreaTypeGuid;
} EFI_FLASH_AREA_DATA;
+**/
+
+typedef struct {
+ EFI_FLASH_AREA_ATTRIBUTES Attributes;
+ UINT32 Reserved;
+ EFI_PHYSICAL_ADDRESS Base;
+ EFI_PHYSICAL_ADDRESS Length;
+ EFI_GUID FileSystem;
+} EFI_FLASH_SUBAREA_ENTRY;
+
+typedef struct {
+ UINT8 Reserved[3];
+ EFI_FLASH_AREA_TYPE AreaType;
+ EFI_GUID AreaTypeGuid;
+ UINT32 NumberOfEntries;
+ EFI_FLASH_SUBAREA_ENTRY Entries[1];
+ //
+ // Extended Hob data.
+ //
+ // VolumeId and FilePath indicating a unique file.
+ //
+ UINT32 VolumeId;
+ CHAR16 FilePath[256];
+ UINT32 ActuralSize;
+ UINT32 Offset;
+} EFI_FLASH_MAP_FS_ENTRY_DATA;
#pragma pack()
diff --git a/DuetPkg/IsaAcpiDxe/ComponentName.c b/DuetPkg/IsaAcpiDxe/ComponentName.c new file mode 100644 index 0000000000..01084223d0 --- /dev/null +++ b/DuetPkg/IsaAcpiDxe/ComponentName.c @@ -0,0 +1,170 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "PcatIsaAcpi.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+
+EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PcatIsaAcpiComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PcatIsaAcpiComponentNameGetControllerName,
+ "en"
+};
+
+EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName = {
+ PcatIsaAcpiComponentNameGetDriverName,
+ PcatIsaAcpiComponentNameGetControllerName,
+ "eng"
+};
+
+
+static EFI_UNICODE_STRING_TABLE mPcatIsaAcpiDriverNameTable[] = {
+ {
+ "eng;en",
+ L"PC-AT ISA Device Enumeration Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCES - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mPcatIsaAcpiDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gPcatIsaAcpiComponentName)
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/DuetPkg/IsaAcpiDxe/IsaAcpi.c b/DuetPkg/IsaAcpiDxe/IsaAcpi.c new file mode 100644 index 0000000000..e3792a7818 --- /dev/null +++ b/DuetPkg/IsaAcpiDxe/IsaAcpi.c @@ -0,0 +1,306 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ IsaAcpi.c
+
+Abstract:
+
+ ISA ACPI Protocol Implementation
+
+Revision History
+
+--*/
+
+#include "PcatIsaAcpi.h"
+
+//
+// Platform specific data for the ISA devices that are present.in the platform
+//
+
+//
+// COM 1 UART Controller
+//
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom1DeviceResources[] = {
+ {EfiIsaAcpiResourceIo, 0, 0x3f8, 0x3ff},
+ {EfiIsaAcpiResourceInterrupt, 0, 4, 0},
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}
+};
+
+//
+// COM 2 UART Controller
+//
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiCom2DeviceResources[] = {
+ {EfiIsaAcpiResourceIo, 0, 0x2f8, 0x2ff},
+ {EfiIsaAcpiResourceInterrupt, 0, 3, 0},
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}
+};
+
+//
+// PS/2 Keyboard Controller
+//
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2KeyboardDeviceResources[] = {
+ {EfiIsaAcpiResourceIo, 0, 0x60, 0x64},
+ {EfiIsaAcpiResourceInterrupt, 0, 1, 0},
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}
+};
+
+//
+// PS/2 Mouse Controller
+//
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiPs2MouseDeviceResources[] = {
+ {EfiIsaAcpiResourceIo, 0, 0x60, 0x64},
+ {EfiIsaAcpiResourceInterrupt, 0, 12, 0},
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}
+};
+
+//
+// Floppy Disk Controller
+//
+static EFI_ISA_ACPI_RESOURCE mPcatIsaAcpiFloppyResources[] = {
+ {EfiIsaAcpiResourceIo, 0, 0x3f0, 0x3f7},
+ {EfiIsaAcpiResourceInterrupt, 0, 6, 0},
+ {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},
+ {EfiIsaAcpiResourceEndOfList, 0, 0, 0}
+};
+
+//
+// Table of ISA Controllers
+//
+EFI_ISA_ACPI_RESOURCE_LIST gPcatIsaAcpiDeviceList[] = {
+ {{EISA_PNP_ID(0x501), 0}, mPcatIsaAcpiCom1DeviceResources }, // COM 1 UART Controller
+ {{EISA_PNP_ID(0x501), 1}, mPcatIsaAcpiCom2DeviceResources }, // COM 2 UART Controller
+ {{EISA_PNP_ID(0x303), 0}, mPcatIsaAcpiPs2KeyboardDeviceResources }, // PS/2 Keyboard Controller
+ {{EISA_PNP_ID(0x303), 1}, mPcatIsaAcpiPs2MouseDeviceResources }, // PS/2 Mouse Controller
+ {{EISA_PNP_ID(0x604), 0}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller A:
+ {{EISA_PNP_ID(0x604), 1}, mPcatIsaAcpiFloppyResources }, // Floppy Disk Controller B:
+ {{0, 0}, NULL } // End if ISA Controllers
+};
+
+//
+// ISA ACPI Protocol Functions
+//
+VOID
+IsaDeviceLookup (
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **IsaAcpiDevice,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **NextIsaAcpiDevice
+ )
+/*++
+
+Routine Description:
+ Enumerate the ISA devices on the ISA bus
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Index;
+
+ *IsaAcpiDevice = NULL;
+ if (NextIsaAcpiDevice != NULL) {
+ *NextIsaAcpiDevice = NULL;
+ }
+ if (Device == NULL) {
+ Index = 0;
+ } else {
+ for(Index = 0; gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL; Index++) {
+ if (Device->HID == gPcatIsaAcpiDeviceList[Index].Device.HID &&
+ Device->UID == gPcatIsaAcpiDeviceList[Index].Device.UID ) {
+ break;
+ }
+ }
+ if (gPcatIsaAcpiDeviceList[Index].ResourceItem == NULL) {
+ return;
+ }
+ *IsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);
+ Index++;
+ }
+ if (gPcatIsaAcpiDeviceList[Index].ResourceItem != NULL && NextIsaAcpiDevice != NULL) {
+ *NextIsaAcpiDevice = &(gPcatIsaAcpiDeviceList[Index]);
+ }
+}
+
+EFI_STATUS
+EFIAPI
+IsaDeviceEnumerate (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ OUT EFI_ISA_ACPI_DEVICE_ID **Device
+ )
+/*++
+
+Routine Description:
+ Enumerate the ISA devices on the ISA bus
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_ISA_ACPI_RESOURCE_LIST *IsaAcpiDevice;
+ EFI_ISA_ACPI_RESOURCE_LIST *NextIsaAcpiDevice;
+
+ IsaDeviceLookup (*Device, &IsaAcpiDevice, &NextIsaAcpiDevice);
+ if (NextIsaAcpiDevice == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ *Device = &(NextIsaAcpiDevice->Device);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaDeviceSetPower (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN BOOLEAN OnOff
+ )
+/*++
+
+Routine Description:
+ Set ISA device power
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaGetCurrentResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
+ )
+/*++
+
+Routine Description:
+ Get current Resource of the specific ISA device
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ IsaDeviceLookup (Device, ResourceList, NULL);
+ if (*ResourceList == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaGetPossibleResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaSetResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaEnableDevice (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IsaInitDevice (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+IsaInterfaceInit (
+ IN EFI_ISA_ACPI_PROTOCOL *This
+)
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/IsaAcpiDxe/IsaAcpi.inf b/DuetPkg/IsaAcpiDxe/IsaAcpi.inf new file mode 100644 index 0000000000..ec01a28346 --- /dev/null +++ b/DuetPkg/IsaAcpiDxe/IsaAcpi.inf @@ -0,0 +1,50 @@ +#/*++
+#
+# Copyright (c) 2005, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+# IsaAcpi.inf
+#
+# Abstract:
+# Component description file for PCAT ISA ACPI driver
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IsaAcpi
+ FILE_GUID = 38A0EC22-FBE7-4911-8BC1-176E0D6C1DBD
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = PcatIsaAcpiDriverEntryPoint
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+
+[Sources]
+ PcatIsaAcpi.h
+ PcatIsaAcpi.c
+ IsaAcpi.c
+ ComponentName.c
+
+[Protocols]
+ gEfiPciIoProtocolGuid
+ gEfiIsaAcpiProtocolGuid
diff --git a/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.c b/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.c new file mode 100644 index 0000000000..a618728791 --- /dev/null +++ b/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.c @@ -0,0 +1,329 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PcatIsaAcpi.c
+
+Abstract:
+
+ EFI PCAT ISA ACPI Driver for a Generic PC Platform
+
+Revision History
+
+--*/
+
+#include "PcatIsaAcpi.h"
+
+//
+// PcatIsaAcpi Driver Binding Protocol
+//
+EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding = {
+ PcatIsaAcpiDriverBindingSupported,
+ PcatIsaAcpiDriverBindingStart,
+ PcatIsaAcpiDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+ Routine Description:
+ the entry point of the PcatIsaAcpi driver
+
+ Arguments:
+
+ Returns:
+
+--*/
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gPcatIsaAcpiDriverBinding,
+ ImageHandle,
+ &gPcatIsaAcpiComponentName,
+ &gPcatIsaAcpiComponentName2
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ ControllerDriver Protocol Method
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Get PciIo protocol instance
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof(Pci) / sizeof(UINT32),
+ &Pci);
+
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ if ((Pci.Hdr.Command & 0x03) == 0x03) {
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
+ //
+ // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code
+ //
+ if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA) {
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
+ //
+ if (Pci.Hdr.ClassCode[1] == PCI_CLASS_ISA_POSITIVE_DECODE &&
+ Pci.Hdr.VendorId == 0x8086 &&
+ Pci.Hdr.DeviceId == 0x7110) {
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+ Install EFI_ISA_ACPI_PROTOCOL
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;
+
+ PcatIsaAcpiDev = NULL;
+ //
+ // Open the PCI I/O Protocol Interface
+ //
+ PciIo = NULL;
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Allocate memory for the PCAT ISA ACPI Device structure
+ //
+ PcatIsaAcpiDev = NULL;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(PCAT_ISA_ACPI_DEV),
+ &PcatIsaAcpiDev
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Initialize the PCAT ISA ACPI Device structure
+ //
+ PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE;
+ PcatIsaAcpiDev->Handle = Controller;
+ PcatIsaAcpiDev->PciIo = PciIo;
+
+ //
+ // IsaAcpi interface
+ //
+ (PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate = IsaDeviceEnumerate;
+ (PcatIsaAcpiDev->IsaAcpi).SetPower = IsaDeviceSetPower;
+ (PcatIsaAcpiDev->IsaAcpi).GetCurResource = IsaGetCurrentResource;
+ (PcatIsaAcpiDev->IsaAcpi).GetPosResource = IsaGetPossibleResource;
+ (PcatIsaAcpiDev->IsaAcpi).SetResource = IsaSetResource;
+ (PcatIsaAcpiDev->IsaAcpi).EnableDevice = IsaEnableDevice;
+ (PcatIsaAcpiDev->IsaAcpi).InitDevice = IsaInitDevice;
+ (PcatIsaAcpiDev->IsaAcpi).InterfaceInit = IsaInterfaceInit;
+
+ //
+ // Install the ISA ACPI Protocol interface
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi,
+ NULL
+ );
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (PciIo) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
+ NULL
+ );
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (PcatIsaAcpiDev != NULL) {
+ gBS->FreePool (PcatIsaAcpiDev);
+ }
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Arguments:
+
+ Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_ISA_ACPI_PROTOCOL *IsaAcpi;
+ PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev;
+
+ //
+ // Get the ISA ACPI Protocol Interface
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaAcpiProtocolGuid,
+ &IsaAcpi,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the PCAT ISA ACPI Device structure from the ISA ACPI Protocol
+ //
+ PcatIsaAcpiDev = PCAT_ISA_ACPI_DEV_FROM_THIS (IsaAcpi);
+
+ PcatIsaAcpiDev->PciIo->Attributes (
+ PcatIsaAcpiDev->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO,
+ NULL
+ );
+
+ //
+ // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (PcatIsaAcpiDev);
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.h b/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.h new file mode 100644 index 0000000000..57e4112923 --- /dev/null +++ b/DuetPkg/IsaAcpiDxe/PcatIsaAcpi.h @@ -0,0 +1,159 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ PcatIsaAcpi.h
+
+Abstract:
+
+ EFI PCAT ISA ACPI Driver for a Generic PC Platform
+
+Revision History
+
+--*/
+
+#ifndef _PCAT_ISA_ACPI_H_
+#define _PCAT_ISA_ACPI_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/IsaIo.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/IsaAcpi.h>
+//
+// PCAT ISA ACPI device private data structure
+//
+#define PCAT_ISA_ACPI_DEV_SIGNATURE EFI_SIGNATURE_32('L','P','C','D')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_ISA_ACPI_PROTOCOL IsaAcpi;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+} PCAT_ISA_ACPI_DEV;
+
+#define PCAT_ISA_ACPI_DEV_FROM_THIS(a) _CR(a, PCAT_ISA_ACPI_DEV, IsaAcpi)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gPcatIsaAcpiDriverBinding;
+
+extern EFI_COMPONENT_NAME2_PROTOCOL gPcatIsaAcpiComponentName2;
+
+extern EFI_COMPONENT_NAME_PROTOCOL gPcatIsaAcpiComponentName;
+
+
+//
+// Prototypes for Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PcatIsaAcpiDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Prototypes for the ISA ACPI protocol interface
+//
+EFI_STATUS
+EFIAPI
+IsaDeviceEnumerate (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ OUT EFI_ISA_ACPI_DEVICE_ID **Device
+ );
+
+EFI_STATUS
+EFIAPI
+IsaDeviceSetPower (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN BOOLEAN OnOff
+ );
+
+EFI_STATUS
+EFIAPI
+IsaGetCurrentResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
+ );
+
+EFI_STATUS
+EFIAPI
+IsaGetPossibleResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList
+ );
+
+EFI_STATUS
+EFIAPI
+IsaSetResource (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList
+ );
+
+EFI_STATUS
+EFIAPI
+IsaEnableDevice (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device,
+ IN BOOLEAN Enable
+ );
+
+EFI_STATUS
+EFIAPI
+IsaInitDevice (
+ IN EFI_ISA_ACPI_PROTOCOL *This,
+ IN EFI_ISA_ACPI_DEVICE_ID *Device
+ );
+
+EFI_STATUS
+EFIAPI
+IsaInterfaceInit (
+ IN EFI_ISA_ACPI_PROTOCOL *This
+ );
+
+#endif
diff --git a/DuetPkg/KbcResetDxe/Ia32/Ia32Reset.c b/DuetPkg/KbcResetDxe/Ia32/Ia32Reset.c new file mode 100644 index 0000000000..00c5223a14 --- /dev/null +++ b/DuetPkg/KbcResetDxe/Ia32/Ia32Reset.c @@ -0,0 +1,79 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Ia32Reset.c
+
+Abstract:
+
+--*/
+
+#include "Reset.h"
+
+//
+// The handle onto which the Reset Architectural Protocol is installed
+//
+EFI_HANDLE mResetHandle = NULL;
+
+
+EFI_STATUS
+EFIAPI
+InitializeReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the state information for the Reset Architectural Protocol
+
+Arguments:
+
+ ImageHandle of the loaded driver
+ Pointer to the System Table
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS - thread can be successfully created
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ EFI_DEVICE_ERROR - cannot create the timer service
+
+--*/
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Reset Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);
+
+ //
+ // Hook the runtime service table
+ //
+ SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;
+
+ //
+ // Now install the Reset RT AP on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mResetHandle,
+ &gEfiResetArchProtocolGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/DuetPkg/KbcResetDxe/Ia32Reset.dxs b/DuetPkg/KbcResetDxe/Ia32Reset.dxs new file mode 100644 index 0000000000..ae2b86de40 --- /dev/null +++ b/DuetPkg/KbcResetDxe/Ia32Reset.dxs @@ -0,0 +1,27 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Ia32Reset.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuIO)
+
+DEPENDENCY_START
+ EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/KbcResetDxe/Ipf/IpfReset.c b/DuetPkg/KbcResetDxe/Ipf/IpfReset.c new file mode 100644 index 0000000000..028fd13876 --- /dev/null +++ b/DuetPkg/KbcResetDxe/Ipf/IpfReset.c @@ -0,0 +1,117 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IpfReset.c
+
+Abstract:
+
+--*/
+
+#include "Cf9Reset.h"
+
+SAL_RETURN_REGS
+ResetEsalServicesClassCommonEntry (
+ IN UINT64 FunctionId,
+ IN UINT64 Arg2,
+ IN UINT64 Arg3,
+ IN UINT64 Arg4,
+ IN UINT64 Arg5,
+ IN UINT64 Arg6,
+ IN UINT64 Arg7,
+ IN UINT64 Arg8,
+ IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,
+ IN BOOLEAN VirtualMode,
+ IN VOID *Global
+ )
+/*++
+
+Routine Description:
+
+ Main entry for Extended SAL Reset Services
+
+Arguments:
+
+ FunctionId Function Id which needed to be called.
+ Arg2 EFI_RESET_TYPE, whether WARM of COLD reset
+ Arg3 Last EFI_STATUS
+ Arg4 Data Size of UNICODE STRING passed in ARG5
+ Arg5 Unicode String which CHAR16*
+
+Returns:
+
+ SAL_RETURN_REGS
+
+--*/
+// TODO: Arg6 - add argument and description to function comment
+// TODO: Arg7 - add argument and description to function comment
+// TODO: Arg8 - add argument and description to function comment
+// TODO: ExtendedSalProc - add argument and description to function comment
+// TODO: VirtualMode - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+{
+ SAL_RETURN_REGS ReturnVal;
+
+ switch (FunctionId) {
+ case ResetSystem:
+ KbcResetSystem (Arg2, Arg3, (UINTN) Arg4, (VOID *) Arg5);
+ ReturnVal.Status = EFI_SUCCESS;
+ break;
+
+ default:
+ ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT;
+ break;
+ }
+
+ return ReturnVal;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the state information for the Reset Architectural Protocol
+
+Arguments:
+
+ ImageHandle of the loaded driver
+ Pointer to the System Table
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS - thread can be successfully created
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ EFI_DEVICE_ERROR - cannot create the timer service
+
+--*/
+// TODO: SystemTable - add argument and description to function comment
+{
+ EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);
+
+ RegisterEsalClass (
+ &gEfiExtendedSalResetServicesProtocolGuid,
+ NULL,
+ ResetEsalServicesClassCommonEntry,
+ ResetSystem,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/KbcResetDxe/IpfReset.dxs b/DuetPkg/KbcResetDxe/IpfReset.dxs new file mode 100644 index 0000000000..6bb389199d --- /dev/null +++ b/DuetPkg/KbcResetDxe/IpfReset.dxs @@ -0,0 +1,27 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IpfReset.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)
+
+DEPENDENCY_START
+ EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/KbcResetDxe/Reset.c b/DuetPkg/KbcResetDxe/Reset.c new file mode 100644 index 0000000000..b06c999842 --- /dev/null +++ b/DuetPkg/KbcResetDxe/Reset.c @@ -0,0 +1,70 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Reset.c
+
+Abstract:
+
+ Reset Architectural Protocol implementation
+
+--*/
+
+#include "Reset.h"
+
+VOID
+EFIAPI
+KbcResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Reset the system.
+
+Arguments:
+
+ ResetType - warm or cold
+ ResetStatus - possible cause of reset
+ DataSize - Size of ResetData in bytes
+ ResetData - Optional Unicode string
+ For details, see efiapi.h
+
+Returns:
+ Does not return if the reset takes place.
+ EFI_INVALID_PARAMETER If ResetType is invalid.
+
+--*/
+{
+ UINT8 Data;
+
+ switch (ResetType) {
+ case EfiResetWarm:
+ case EfiResetCold:
+ case EfiResetShutdown:
+ Data = 0xfe;
+ IoWrite8 (0x64, Data);
+ break;
+
+ default:
+ return ;
+ }
+
+ //
+ // Given we should have reset getting here would be bad
+ //
+ ASSERT (FALSE);
+}
+
diff --git a/DuetPkg/KbcResetDxe/Reset.h b/DuetPkg/KbcResetDxe/Reset.h new file mode 100644 index 0000000000..3777c331fb --- /dev/null +++ b/DuetPkg/KbcResetDxe/Reset.h @@ -0,0 +1,85 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Reset.h
+
+Abstract:
+
+ some definitions for reset
+
+--*/
+
+#ifndef _KBC_RESET_H
+#define _KBC_RESET_H
+
+#include <PiDxe.h>
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/Reset.h>
+
+EFI_STATUS
+EFIAPI
+InitializeReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ SystemTable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+KbcResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ResetType - TODO: add argument description
+ ResetStatus - TODO: add argument description
+ DataSize - TODO: add argument description
+ ResetData - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/DuetPkg/KbcResetDxe/Reset.inf b/DuetPkg/KbcResetDxe/Reset.inf new file mode 100644 index 0000000000..b491691962 --- /dev/null +++ b/DuetPkg/KbcResetDxe/Reset.inf @@ -0,0 +1,59 @@ +#/*++
+#
+# Copyright (c) 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+# Reset.inf
+#
+# Abstract:
+#
+#--*/
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = KbcReset
+ FILE_GUID = 6F0198AA-1F1D-426D-AE3E-39AB633FCC28
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeReset
+
+[Packages]
+ DuetPkg/DuetPkg.dec
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Sources.common]
+ Reset.c
+ Reset.h
+
+[Sources.ipf]
+ Ipf\IpfReset.c
+
+[Sources.ia32]
+ Ia32\Ia32Reset.c
+
+[Sources.x64]
+ x64\x64Reset.c
+
+[Protocols]
+ gEfiResetArchProtocolGuid
+
+[Depex]
+ gEfiCpuIoProtocolGuid
+
+
diff --git a/DuetPkg/KbcResetDxe/x64/x64Reset.c b/DuetPkg/KbcResetDxe/x64/x64Reset.c new file mode 100644 index 0000000000..1fd79bf0fe --- /dev/null +++ b/DuetPkg/KbcResetDxe/x64/x64Reset.c @@ -0,0 +1,79 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ x64Reset.c
+
+Abstract:
+
+--*/
+
+#include "Reset.h"
+
+//
+// The handle onto which the Reset Architectural Protocol is installed
+//
+EFI_HANDLE mResetHandle = NULL;
+
+
+EFI_STATUS
+EFIAPI
+InitializeReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the state information for the Reset Architectural Protocol
+
+Arguments:
+
+ ImageHandle of the loaded driver
+ Pointer to the System Table
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS - thread can be successfully created
+ EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ EFI_DEVICE_ERROR - cannot create the timer service
+
+--*/
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Reset Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);
+
+ //
+ // Hook the runtime service table
+ //
+ SystemTable->RuntimeServices->ResetSystem = KbcResetSystem;
+
+ //
+ // Now install the Reset RT AP on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mResetHandle,
+ &gEfiResetArchProtocolGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/DuetPkg/KbcResetDxe/x64Reset.dxs b/DuetPkg/KbcResetDxe/x64Reset.dxs new file mode 100644 index 0000000000..a2b1498f6c --- /dev/null +++ b/DuetPkg/KbcResetDxe/x64Reset.dxs @@ -0,0 +1,27 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ x64Reset.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuIO)
+
+DEPENDENCY_START
+ EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/LegacyMetronome/Metronome.c b/DuetPkg/LegacyMetronome/Metronome.c new file mode 100644 index 0000000000..acc0dad45c --- /dev/null +++ b/DuetPkg/LegacyMetronome/Metronome.c @@ -0,0 +1,201 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ LegacyMetronome.c
+
+Abstract:
+
+ This contains the installation function for the driver.
+
+--*/
+
+#include "Metronome.h"
+
+//
+// Handle for the Metronome Architectural Protocol instance produced by this driver
+//
+EFI_HANDLE mMetronomeHandle = NULL;
+
+//
+// The Metronome Architectural Protocol instance produced by this driver
+//
+EFI_METRONOME_ARCH_PROTOCOL mMetronome = {
+ WaitForTick,
+ TICK_PERIOD
+};
+
+//
+// The CPU I/O Protocol used to access system hardware
+//
+EFI_CPU_IO_PROTOCOL *mCpuIo = NULL;
+
+//
+// Worker Functions
+//
+VOID
+IoWrite8 (
+ UINT16 Port,
+ UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ Write an 8 bit value to an I/O port and save it to the S3 script
+
+Arguments:
+
+Returns:
+
+ None.
+
+--*/
+// TODO: Port - add argument and description to function comment
+// TODO: Data - add argument and description to function comment
+{
+ mCpuIo->Io.Write (
+ mCpuIo,
+ EfiCpuIoWidthUint8,
+ Port,
+ 1,
+ &Data
+ );
+
+}
+
+UINT8
+ReadRefresh (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Read the refresh bit from the REFRESH_PORT
+
+Arguments:
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINT8 Data;
+
+ mCpuIo->Io.Read (
+ mCpuIo,
+ EfiCpuIoWidthUint8,
+ REFRESH_PORT,
+ 1,
+ &Data
+ );
+ return (UINT8) (Data & REFRESH_ON);
+}
+
+EFI_STATUS
+EFIAPI
+WaitForTick (
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,
+ IN UINT32 TickNumber
+ )
+/*++
+
+Routine Description:
+
+ Waits for the TickNumber of ticks from a known platform time source.
+
+Arguments:
+
+ This Pointer to the protocol instance.
+
+Returns:
+
+ EFI_SUCCESS If number of ticks occurred.
+ EFI_NOT_FOUND Could not locate CPU IO protocol
+
+--*/
+// TODO: TickNumber - add argument and description to function comment
+{
+ //
+ // Wait for TickNumber toggles of the Refresh bit
+ //
+ for (; TickNumber != 0x00; TickNumber--) {
+ while (ReadRefresh () == REFRESH_ON)
+ ;
+ while (ReadRefresh () == REFRESH_OFF)
+ ;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+InstallMetronome (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Install the LegacyMetronome driver. Loads a Metronome Arch Protocol based
+ on the Port 61 timer.
+
+Arguments:
+
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+
+ EFI_SUCCESS - Metronome Architectural Protocol Installed
+
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Metronome Architectural Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid);
+
+ //
+ // Get the CPU I/O Protocol that this driver requires
+ // If the CPU I/O Protocol is not found, then ASSERT because the dependency expression
+ // should guarantee that it is present in the handle database.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &mCpuIo);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Program port 61 timer 1 as refresh timer. We could use ACPI timer in the
+ // future.
+ //
+ IoWrite8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB);
+ IoWrite8 (TIMER1_COUNT_PORT, COUNTER1_COUNT);
+
+ //
+ // Install on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mMetronomeHandle,
+ &gEfiMetronomeArchProtocolGuid,
+ &mMetronome,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/DuetPkg/LegacyMetronome/Metronome.dxs b/DuetPkg/LegacyMetronome/Metronome.dxs new file mode 100644 index 0000000000..6e224957fc --- /dev/null +++ b/DuetPkg/LegacyMetronome/Metronome.dxs @@ -0,0 +1,28 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ LegacyMetronome.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+
+DEPENDENCY_START
+ EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/DuetPkg/LegacyMetronome/Metronome.h b/DuetPkg/LegacyMetronome/Metronome.h new file mode 100644 index 0000000000..87a12cbc34 --- /dev/null +++ b/DuetPkg/LegacyMetronome/Metronome.h @@ -0,0 +1,75 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ LegacyMetronome.h
+
+Abstract:
+
+ Driver implementing the EFI 2.0 metronome protocol using the legacy PORT 61
+ timer.
+
+--*/
+
+#ifndef _LEGACY_METRONOME_H
+#define _LEGACY_METRONOME_H
+
+//
+// Statements that include other files
+//
+#include <PiDxe.h>
+
+#include <Protocol/CpuIo.h>
+#include <Protocol/Metronome.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+//
+// Private definitions
+//
+#define TICK_PERIOD 300
+#define REFRESH_PORT 0x61
+#define REFRESH_ON 0x10
+#define REFRESH_OFF 0x00
+#define TIMER1_CONTROL_PORT 0x43
+#define TIMER1_COUNT_PORT 0x41
+#define LOAD_COUNTER1_LSB 0x54
+#define COUNTER1_COUNT 0x12
+
+//
+// Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+WaitForTick (
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,
+ IN UINT32 TickNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ TickNumber - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/DuetPkg/LegacyMetronome/Metronome.inf b/DuetPkg/LegacyMetronome/Metronome.inf new file mode 100644 index 0000000000..d97b67f334 --- /dev/null +++ b/DuetPkg/LegacyMetronome/Metronome.inf @@ -0,0 +1,48 @@ +#/*++
+#
+# Copyright (c) 2005, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# Abstract:
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Metronome
+ FILE_GUID = 07A9330A-F347-11d4-9A49-0090273FC14D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InstallMetronome
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ DebugLib
+ UefiBootServicesTableLib
+
+[Sources.common]
+ Metronome.c
+ Metronome.h
+
+[Protocols]
+ gEfiMetronomeArchProtocolGuid
+ gEfiCpuIoProtocolGuid
+
+[Depex]
+ gEfiCpuIoProtocolGuid
diff --git a/DuetPkg/Library/DuetBdsLib/BdsPlatform.c b/DuetPkg/Library/DuetBdsLib/BdsPlatform.c new file mode 100644 index 0000000000..e8404e5524 --- /dev/null +++ b/DuetPkg/Library/DuetBdsLib/BdsPlatform.c @@ -0,0 +1,1720 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ BdsPlatform.c
+
+Abstract:
+
+ This file include all platform action which can be customized
+ by IBV/OEM.
+
+--*/
+
+#include "BdsPlatform.h"
+
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+CHAR16 mFirmwareVendor[] = L"TianoCore.org";
+extern BOOLEAN gConnectAllHappened;
+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;
+//
+// BDS Platform Functions
+//
+
+VOID
+GetSystemTablesFromHob (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
+
+Arguments:
+ None
+
+Returns:
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobList;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobStart;
+ EFI_PHYSICAL_ADDRESS *Table;
+ UINTN Index;
+ EFI_GUID *TableGuidArray[] = {
+ &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid
+ };
+
+ //
+ // Get Hob List
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
+ //
+ for (Index = 0; Index < sizeof (TableGuidArray) / sizeof (*TableGuidArray); ++Index) {
+ HobStart = HobList;
+ Table = NULL;
+ Table = GetNextGuidHob (TableGuidArray[Index], &HobStart);
+ if (!EFI_ERROR (Status)) {
+ if (Table != NULL) {
+ //
+ // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
+ // According to UEFI Spec, we should make sure Smbios table,
+ // ACPI table and Mps tables kept in memory of specified type
+ //
+ ConvertSystemTable(TableGuidArray[Index], &Table);
+ gBS->InstallConfigurationTable (TableGuidArray[Index], (VOID *)Table);
+ }
+ }
+ }
+
+ return ;
+}
+
+#define EFI_LDR_MEMORY_DESCRIPTOR_GUID \
+ { 0x7701d7e5, 0x7d1d, 0x4432, 0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }
+
+EFI_GUID gEfiLdrMemoryDescriptorGuid = EFI_LDR_MEMORY_DESCRIPTOR_GUID;
+
+#pragma pack(1)
+
+typedef struct {
+ EFI_HOB_GUID_TYPE Hob;
+ UINTN MemDescCount;
+ EFI_MEMORY_DESCRIPTOR *MemDesc;
+} MEMORY_DESC_HOB;
+
+#pragma pack()
+
+#if 0
+VOID
+PrintMemoryMap (
+ VOID
+ )
+{
+ EFI_MEMORY_DESCRIPTOR *MemMap;
+ EFI_MEMORY_DESCRIPTOR *MemMapPtr;
+ UINTN MemMapSize;
+ UINTN MapKey, DescriptorSize;
+ UINTN Index;
+ UINT32 DescriptorVersion;
+ UINT64 Bytes;
+ EFI_STATUS Status;
+
+ MemMapSize = 0;
+ MemMap = NULL;
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ MemMapSize += EFI_PAGE_SIZE;
+ Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap);
+ ASSERT (Status == EFI_SUCCESS);
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
+ ASSERT (Status == EFI_SUCCESS);
+ MemMapPtr = MemMap;
+
+ ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);
+
+ for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) {
+ Bytes = LShiftU64 (MemMap->NumberOfPages, 12);
+ DEBUG ((EFI_D_ERROR, "%lX-%lX %lX %lX %X\n",
+ MemMap->PhysicalStart,
+ MemMap->PhysicalStart + Bytes - 1,
+ MemMap->NumberOfPages,
+ MemMap->Attribute,
+ (UINTN)MemMap->Type));
+ MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize);
+ }
+
+ gBS->FreePool (MemMapPtr);
+}
+#endif
+
+VOID
+UpdateMemoryMap (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobList;
+ VOID *Table;
+ MEMORY_DESC_HOB MemoryDescHob;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS Memory;
+
+ //
+ // Get Hob List
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID *) &HobList);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Table = GetNextGuidHob (&gEfiLdrMemoryDescriptorGuid, &HobList);
+ MemoryDescHob.MemDescCount = *(UINTN *)Table;
+ MemoryDescHob.MemDesc = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));
+
+ //
+ // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
+ //
+ for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {
+ if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {
+ continue;
+ }
+ if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000) {
+ continue;
+ }
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
+ DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%x, ", MemoryDescHob.MemDesc[Index].PhysicalStart));
+ DEBUG ((EFI_D_ERROR, "PageNumber - 0x%x, ", MemoryDescHob.MemDesc[Index].NumberOfPages));
+ DEBUG ((EFI_D_ERROR, "Type - 0x%x\n", MemoryDescHob.MemDesc[Index].Type));
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {
+ //
+ // Skip RuntimeSevicesData and RuntimeServicesCode, they are BFV
+ //
+ continue;
+ }
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeSystemMemory,
+ MemoryDescHob.MemDesc[Index].PhysicalStart,
+ LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),
+ MemoryDescHob.MemDesc[Index].Attribute
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "AddMemorySpace fail!\n"));
+ if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
+ (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
+ //
+ // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
+ // For EfiReservedMemoryType, there maybe overlap. So skip check here.
+ //
+// ASSERT_EFI_ERROR (Status);
+ }
+ continue;
+ }
+
+ Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ MemoryDescHob.MemDesc[Index].Type,
+ (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,
+ &Memory
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "AllocatePages fail!\n"));
+ //
+ // For the page added, it must be allocated.
+ //
+// ASSERT_EFI_ERROR (Status);
+ continue;
+ }
+ }
+ }
+
+}
+
+EFI_STATUS
+DisableUsbLegacySupport(
+ void
+ )
+/*++
+
+Routine Description:
+ Disabble the USB legacy Support in all Ehci and Uhci.
+ This function assume all PciIo handles have been created in system.
+
+Arguments:
+ None
+
+Returns:
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleArray;
+ UINTN HandleArrayCount;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Class[3];
+ UINT16 Command;
+ UINT32 HcCapParams;
+ UINT32 ExtendCap;
+ UINT32 Value;
+ UINT32 TimeOut;
+
+ //
+ // Find the usb host controller
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleArrayCount,
+ &HandleArray
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleArrayCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleArray[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find the USB host controller controller
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+ if (!EFI_ERROR (Status)) {
+ if ((PCI_CLASS_SERIAL == Class[2]) &&
+ (PCI_CLASS_SERIAL_USB == Class[1])) {
+ if (PCI_CLASSC_PI_UHCI == Class[0]) {
+ //
+ // Found the UHCI, then disable the legacy support
+ //
+ Command = 0;
+ Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command);
+ } else if (PCI_CLASSC_PI_EHCI == Class[0]) {
+ //
+ // Found the EHCI, then disable the legacy support
+ //
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0, //EHC_BAR_INDEX
+ (UINT64) 0x08, //EHC_HCCPARAMS_OFFSET
+ 1,
+ &HcCapParams
+ );
+
+ ExtendCap = (HcCapParams >> 8) & 0xFF;
+ //
+ // Disable the SMI in USBLEGCTLSTS firstly
+ //
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
+ Value &= 0xFFFF0000;
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
+
+ //
+ // Get EHCI Ownership from legacy bios
+ //
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
+ Value |= (0x1 << 24);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
+
+ TimeOut = 40;
+ while (TimeOut--) {
+ gBS->Stall (500);
+
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
+
+ if ((Value & 0x01010000) == 0x01000000) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ return Status;
+ }
+ gBS->FreePool (HandleArray);
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsInit (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
+ )
+/*++
+
+Routine Description:
+
+ Platform Bds init. Incude the platform firmware vendor, revision
+ and so crc check.
+
+Arguments:
+
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
+
+Returns:
+
+ None.
+
+--*/
+{
+ //
+ // set firmwarevendor, here can be IBV/OEM customize
+ //
+ gST->FirmwareVendor = AllocateRuntimeCopyPool (
+ sizeof (mFirmwareVendor),
+ &mFirmwareVendor
+ );
+ ASSERT (gST->FirmwareVendor != NULL);
+
+ gST->FirmwareRevision = 0;
+
+ //
+ // Fixup Tasble CRC after we updated Firmware Vendor and Revision
+ //
+ gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
+}
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ )
+/*++
+
+Routine Description:
+ This routine is to get PciExpress Base Address for this RootBridge
+
+Arguments:
+ HostBridgeNumber - The number of HostBridge
+ RootBridgeNumber - The number of RootBridge
+
+Returns:
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
+
+--*/
+{
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
+ UINTN BufferSize;
+ UINT32 Index;
+ UINT32 Number;
+ VOID *HobList;
+ EFI_STATUS Status;
+
+ BufferSize = 0;
+ //
+ // Get Hob List from configuration table
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ //
+ // Get PciExpressAddressInfo Hob
+ //
+ PciExpressBaseAddressInfo = NULL;
+ PciExpressBaseAddressInfo = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);
+
+ //
+ // Search the PciExpress Base Address in the Hob for current RootBridge
+ //
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
+ for (Index = 0; Index < Number; Index++) {
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
+ }
+ }
+
+ //
+ // Do not find the PciExpress Base Address in the Hob
+ //
+ return 0;
+}
+
+VOID
+PatchPciRootBridgeDevicePath (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber,
+ IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH *RootBridge
+ )
+{
+ UINT64 PciExpressBase;
+
+ PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);
+
+ if (PciExpressBase != 0) {
+ RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);
+ }
+}
+
+EFI_STATUS
+ConnectRootBridge (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect RootBridge
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Connect RootBridge successfully.
+ EFI_STATUS - Connect RootBridge fail.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE RootHandle;
+
+ //
+ // Patch Pci Root Bridge Device Path
+ //
+ PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);
+
+ //
+ // Make all the PCI_IO protocols on PCI Seg 0 show up
+ //
+ BdsLibConnectDevicePath (gPlatformRootBridges[0]);
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &gPlatformRootBridges[0],
+ &RootHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add IsaKeyboard to ConIn,
+ add IsaSerial to ConOut, ConIn, ErrOut.
+ LPC Bridge: 06 01 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No LPC bridge is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TempDevicePath = DevicePath;
+
+ //
+ // Register Keyboard
+ //
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+
+ //
+ // Register COM1
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 0;
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
+
+ //
+ // Register COM2
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 1;
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+EFI_STATUS
+GetGopDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE PciDeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
+ UINTN GopHandleCount;
+ EFI_HANDLE *GopHandleBuffer;
+
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the GopDevicePath to be PciDevicePath
+ //
+ *GopDevicePath = PciDevicePath;
+ TempPciDevicePath = PciDevicePath;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempPciDevicePath,
+ &PciDeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Try to connect this handle, so that GOP dirver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &GopHandleCount,
+ &GopHandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add all the child handles as possible Console Device
+ //
+ for (Index = 0; Index < GopHandleCount; Index++) {
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, &TempDevicePath);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (CompareMem (
+ PciDevicePath,
+ TempDevicePath,
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+ ) == 0) {
+ //
+ // In current implementation, we only enable one of the child handles
+ // as console device, i.e. sotre one of the child handle's device
+ // path to variable "ConOut"
+ // In futhure, we could select all child handles to be console device
+ //
+
+ *GopDevicePath = TempDevicePath;
+
+ //
+ // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
+ // Add the integrity GOP device path.
+ //
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+#endif
+
+EFI_STATUS
+PreparePciVgaDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI VGA to ConOut.
+ PCI VGA: 03 00 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI VGA is added to ConOut.
+ EFI_STATUS - No PCI VGA device is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+#endif
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+#endif
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+ PCI Serial: 07 00 02
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No PCI Serial device is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePath (
+ BOOLEAN DetectVgaOnly
+ )
+/*++
+
+Routine Description:
+
+ Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+Arguments:
+
+ DetectVgaOnly - Only detect VGA device if it's TRUE.
+
+Returns:
+
+ EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ EFI_STATUS - PCI Device check or Console variable update fail.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Start to check all the PciIo to find all possible device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, &PciIo);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Check for all PCI device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (!DetectVgaOnly) {
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (&Pci)) ||
+ ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {
+ //
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
+ //
+ PrepareLpcBridgeDevicePath (HandleBuffer[Index]);
+ continue;
+ }
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (&Pci)) {
+ //
+ // Add them to ConOut, ConIn, ErrOut.
+ //
+ PreparePciSerialDevicePath (HandleBuffer[Index]);
+ continue;
+ }
+ }
+
+ //
+ // Here we decide which VGA device to enable in PCI bus
+ //
+ if (IS_PCI_VGA (&Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ PreparePciVgaDevicePath (HandleBuffer[Index]);
+ continue;
+ }
+ }
+
+ gBS->FreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PlatformBdsConnectConsole (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+/*++
+
+Routine Description:
+
+ Connect the predefined platform default console device. Always try to find
+ and enable the vga device if have.
+
+Arguments:
+
+ PlatformConsole - Predfined platform default console device array.
+
+Returns:
+
+ EFI_SUCCESS - Success connect at least one ConIn and ConOut
+ device, there must have one ConOut device is
+ active vga device.
+
+ EFI_STATUS - Return the status of
+ BdsLibConnectAllDefaultConsoles ()
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *VarConout;
+ EFI_DEVICE_PATH_PROTOCOL *VarConin;
+ UINTN DevicePathSize;
+
+ //
+ // Connect RootBridge
+ //
+ ConnectRootBridge ();
+
+ VarConout = BdsLibGetVariableAndSize (
+ VarConsoleOut,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+ VarConin = BdsLibGetVariableAndSize (
+ VarConsoleInp,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+ if (VarConout == NULL || VarConin == NULL) {
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+ //
+ DetectAndPreparePlatformPciDevicePath (FALSE);
+
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimue device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ } else {
+ //
+ // Only detect VGA device and add them to ConOut
+ //
+ DetectAndPreparePlatformPciDevicePath (TRUE);
+ }
+
+ //
+ // The ConIn devices connection will start the USB bus, should disable all
+ // Usb legacy support firstly.
+ // Caution: Must ensure the PCI bus driver has been started. Since the
+ // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
+ //
+ Status = DisableUsbLegacySupport();
+
+ //
+ // Connect the all the default console with current cosole variable
+ //
+ Status = BdsLibConnectAllDefaultConsoles ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINTN Index;
+
+ Index = 0;
+
+ //
+ // Here we can get the customized platform connect sequence
+ // Notes: we can connect with new variable which record the
+ // last time boots connect device path sequence
+ //
+ while (gPlatformConnectSequence[Index] != NULL) {
+ //
+ // Build the platform boot option
+ //
+ BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
+ Index++;
+ }
+
+}
+
+VOID
+PlatformBdsGetDriverOption (
+ IN OUT LIST_ENTRY *BdsDriverLists
+ )
+/*++
+
+Routine Description:
+
+ Load the predefined driver option, OEM/IBV can customize this
+ to load their own drivers
+
+Arguments:
+
+ BdsDriverLists - The header of the driver option link list.
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINTN Index;
+
+ Index = 0;
+
+ //
+ // Here we can get the customized platform driver option
+ //
+ while (gPlatformDriverOption[Index] != NULL) {
+ //
+ // Build the platform boot option
+ //
+ BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
+ Index++;
+ }
+
+}
+
+VOID
+PlatformBdsDiagnostics (
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
+ IN BOOLEAN QuietBoot
+ )
+/*++
+
+Routine Description:
+
+ Perform the platform diagnostic, such like test memory. OEM/IBV also
+ can customize this fuction to support specific platform diagnostic.
+
+Arguments:
+
+ MemoryTestLevel - The memory test intensive level
+
+ QuietBoot - Indicate if need to enable the quiet boot
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Here we can decide if we need to show
+ // the diagnostics screen
+ // Notes: this quiet boot code should be remove
+ // from the graphic lib
+ //
+ if (QuietBoot) {
+ EnableQuietBootEx (&gEfiDefaultBmpLogoGuid, mBdsImageHandle);
+ //
+ // Perform system diagnostic
+ //
+ Status = BdsMemoryTest (MemoryTestLevel);
+ if (EFI_ERROR (Status)) {
+ DisableQuietBoot ();
+ }
+
+ return ;
+ }
+ //
+ // Perform system diagnostic
+ //
+ Status = BdsMemoryTest (MemoryTestLevel);
+}
+
+VOID
+PlatformBdsPolicyBehavior (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
+ IN OUT LIST_ENTRY *DriverOptionList,
+ IN OUT LIST_ENTRY *BootOptionList
+ )
+/*++
+
+Routine Description:
+
+ The function will excute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+Arguments:
+
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
+
+ DriverOptionList - The header of the driver option link list
+
+ BootOptionList - The header of the boot option link list
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 Timeout;
+ EFI_EVENT UserInputDurationTime;
+ LIST_ENTRY *Link;
+ BDS_COMMON_OPTION *BootOption;
+ UINTN Index;
+ EFI_INPUT_KEY Key;
+ EFI_TPL OldTpl;
+
+ //
+ // Init the time out value
+ //
+ Timeout = BdsLibGetTimeout ();
+
+ //
+ // Load the driver option as the driver option list
+ //
+ PlatformBdsGetDriverOption (DriverOptionList);
+
+ //
+ // Get current Boot Mode
+ //
+ Status = BdsLibGetBootMode (&PrivateData->BootMode);
+ DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", PrivateData->BootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ ASSERT (PrivateData->BootMode == BOOT_WITH_FULL_CONFIGURATION);
+ //
+ // Connect platform console
+ //
+ Status = PlatformBdsConnectConsole (gPlatformConsole);
+ if (EFI_ERROR (Status)) {
+ //
+ // Here OEM/IBV can customize with defined action
+ //
+ PlatformBdsNoConsoleAction ();
+ }
+ //
+ // Create a 300ms duration event to ensure user has enough input time to enter Setup
+ //
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER,
+ 0,
+ NULL,
+ NULL,
+ &UserInputDurationTime
+ );
+ ASSERT (Status == EFI_SUCCESS);
+ Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
+ ASSERT (Status == EFI_SUCCESS);
+ //
+ // Memory test and Logo show
+ //
+ PlatformBdsDiagnostics (IGNORE, TRUE);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
+ //
+ // Give one chance to enter the setup if we
+ // have the time out
+ //
+ if (Timeout != 0) {
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ }
+
+ //
+ //BdsLibConnectAll ();
+ //BdsLibEnumerateAllBootOption (BootOptionList);
+
+ //
+ // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
+ // checking code in real production tip.
+ //
+ // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
+ // and do enumerate all the default boot options. But in development system board, the boot mode
+ // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
+ // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
+ //
+ Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
+ if (EFI_ERROR(Status)) {
+ //
+ // If cannot find "BootOrder" variable, it may be first boot.
+ // Try to connect all devices and enumerate all boot options here.
+ //
+ BdsLibConnectAll ();
+ BdsLibEnumerateAllBootOption (BootOptionList);
+ }
+
+ //
+ // To give the User a chance to enter Setup here, if user set TimeOut is 0.
+ // BDS should still give user a chance to enter Setup
+ //
+ // Connect first boot option, and then check user input before exit
+ //
+ for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
+ //
+ // skip the header of the link list, becuase it has no boot option
+ //
+ continue;
+ } else {
+ //
+ // Make sure the boot option device path connected, but ignore the BBS device path
+ //
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+ }
+ break;
+ }
+ }
+
+ //
+ // Check whether the user input after the duration time has expired
+ //
+ OldTpl = BdsLibGetCurrentTpl();
+ gBS->RestoreTPL (TPL_APPLICATION);
+ gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
+ gBS->CloseEvent (UserInputDurationTime);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ gBS->RaiseTPL (OldTpl);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Enter Setup if user input
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ }
+
+ return ;
+
+}
+
+VOID
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt succeeds. We don't expect a boot option to
+ return, so the EFI 1.0 specification defines that you will default to an
+ interactive mode and stop processing the BootOrder list in this case. This
+ is alos a platform implementation and can be customized by IBV/OEM.
+
+Arguments:
+
+ Option - Pointer to Boot Option that succeeded to boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ CHAR16 *TmpStr;
+
+ //
+ // If Boot returned with EFI_SUCCESS and there is not in the boot device
+ // select loop then we need to pop up a UI and wait for user input.
+ //
+ TmpStr = Option->StatusString;
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
+ gBS->FreePool (TmpStr);
+ }
+}
+
+VOID
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt fails.
+
+Arguments:
+
+ Option - Pointer to Boot Option that failed to boot.
+
+ Status - Status returned from failed boot.
+
+ ExitData - Exit data returned from failed boot.
+
+ ExitDataSize - Exit data size returned from failed boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ CHAR16 *TmpStr;
+
+ //
+ // If Boot returned with failed status then we need to pop up a UI and wait
+ // for user input.
+ //
+ TmpStr = Option->StatusString;
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
+ gBS->FreePool (TmpStr);
+ }
+
+}
+
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is remained for IBV/OEM to do some platform action,
+ if there no console device can be connected.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Direct return success now.
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConvertSystemTable (
+ IN EFI_GUID *TableGuid,
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+ Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
+ Assumption here:
+ As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
+ So here we just check if the range is E/F seg,
+ and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
+
+Arguments:
+ TableGuid - Guid of the table
+ Table - pointer to the table
+
+Returns:
+ EFI_SUCEESS - Convert Table successfully
+ Other - Failed
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *AcpiHeader;
+ UINTN AcpiTableLen;
+
+ //
+ // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
+ //
+ AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));
+
+ if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
+ if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
+ //
+ // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
+ //
+ AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
+ } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
+ //
+ // If Acpi 2.0 or later, use RSDP Length fied.
+ //
+ AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
+ } else {
+ //
+ // Invalid Acpi Version, return
+ //
+ return EFI_UNSUPPORTED;
+ }
+ Status = ConvertAcpiTable (AcpiTableLen, Table);
+ return Status;
+ }
+
+ //
+ // If matches smbios guid, convert Smbios table.
+ //
+ if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
+ Status = ConvertSmbiosTable (Table);
+ return Status;
+ }
+
+ //
+ // If the table is MP table?
+ //
+ if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
+ Status = ConvertMpsTable (Table);
+ return Status;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+UINT8
+GetBufferCheckSum (
+ IN VOID * Buffer,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+ Caculate buffer checksum (8-bit)
+
+Arguments:
+ Buffer - Pointer to Buffer that to be caculated
+ Length - How many bytes are to be caculated
+
+Returns:
+ Checksum of the buffer
+
+--*/
+{
+ UINT8 CheckSum;
+ UINT8 *Ptr8;
+
+ CheckSum = 0;
+ Ptr8 = (UINT8 *) Buffer;
+
+ while (Length > 0) {
+ CheckSum = (UINT8) (CheckSum + *Ptr8++);
+ Length--;
+ }
+
+ return ((0xFF - CheckSum) + 1);
+}
+
+EFI_STATUS
+ConvertAcpiTable (
+ IN UINTN TableLen,
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+ Convert RSDP of ACPI Table if its location is lower than Address:0x100000
+ Assumption here:
+ As in legacy Bios, ACPI table is required to place in E/F Seg,
+ So here we just check if the range is E/F seg,
+ and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
+
+Arguments:
+ TableLen - Acpi RSDP length
+ Table - pointer to the table
+
+Returns:
+ EFI_SUCEESS - Convert Table successfully
+ Other - Failed
+
+--*/
+{
+ VOID *AcpiTableOri;
+ VOID *AcpiTableNew;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BufferPtr;
+
+
+ AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table));
+ if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES(TableLen),
+ &BufferPtr
+ );
+ ASSERT_EFI_ERROR (Status);
+ AcpiTableNew = (VOID *)(UINTN)BufferPtr;
+ CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
+ } else {
+ AcpiTableNew = AcpiTableOri;
+ }
+ //
+ // Change configuration table Pointer
+ //
+ *Table = AcpiTableNew;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConvertSmbiosTable (
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
+ Assumption here:
+ As in legacy Bios, Smbios table is required to place in E/F Seg,
+ So here we just check if the range is F seg,
+ and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
+Arguments:
+ Table - pointer to the table
+
+Returns:
+ EFI_SUCEESS - Convert Table successfully
+ Other - Failed
+
+--*/
+{
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
+ EFI_STATUS Status;
+ UINT32 SmbiosEntryLen;
+ UINT32 BufferLen;
+ EFI_PHYSICAL_ADDRESS BufferPtr;
+
+ SmbiosTableNew = NULL;
+ SmbiosTableOri = NULL;
+
+ //
+ // Get Smibos configuration Table
+ //
+ SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));
+
+ if ((SmbiosTableOri == NULL) ||
+ ((UINTN)SmbiosTableOri > 0x100000) ||
+ ((UINTN)SmbiosTableOri < 0xF0000)){
+ return EFI_SUCCESS;
+ }
+ //
+ // Relocate the Smibos memory
+ //
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
+ if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
+ SmbiosEntryLen = SmbiosTableOri->EntryPointLength;
+ } else {
+ //
+ // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
+ //
+ SmbiosEntryLen = 0x1F;
+ }
+ BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES(BufferLen),
+ &BufferPtr
+ );
+ ASSERT_EFI_ERROR (Status);
+ SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
+ CopyMem (
+ SmbiosTableNew,
+ SmbiosTableOri,
+ SmbiosEntryLen
+ );
+ //
+ // Get Smbios Structure table address, and make sure the start address is 32-bit align
+ //
+ BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
+ CopyMem (
+ (VOID *)(UINTN)BufferPtr,
+ (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
+ SmbiosTableOri->TableLength
+ );
+ SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
+ SmbiosTableNew->IntermediateChecksum = 0;
+ SmbiosTableNew->IntermediateChecksum =
+ GetBufferCheckSum ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
+ //
+ // Change the SMBIOS pointer
+ //
+ *Table = SmbiosTableNew;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConvertMpsTable (
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
+ Assumption here:
+ As in legacy Bios, MP table is required to place in E/F Seg,
+ So here we just check if the range is E/F seg,
+ and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
+Arguments:
+ Table - pointer to the table
+
+Returns:
+ EFI_SUCEESS - Convert Table successfully
+ Other - Failed
+
+--*/
+{
+ UINT32 Data32;
+ UINT32 FPLength;
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
+ VOID *OemTableOri;
+ VOID *OemTableNew;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BufferPtr;
+
+ //
+ // Get MP configuration Table
+ //
+ MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));
+ if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) &&
+ ((UINTN)MpsFloatingPointerOri >= 0xF0000))){
+ return EFI_SUCCESS;
+ }
+ //
+ // Get Floating pointer structure length
+ //
+ FPLength = MpsFloatingPointerOri->Length * 16;
+ Data32 = FPLength + SYS_TABLE_PAD (FPLength);
+ MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
+ if (MpsTableOri != NULL) {
+ Data32 += MpsTableOri->BaseTableLength;
+ Data32 += MpsTableOri->ExtendedTableLength;
+ if (MpsTableOri->OemTablePointer != 0x00) {
+ Data32 += SYS_TABLE_PAD (Data32);
+ Data32 += MpsTableOri->OemTableSize;
+ }
+ } else {
+ return EFI_SUCCESS;
+ }
+ //
+ // Relocate memory
+ //
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES(Data32),
+ &BufferPtr
+ );
+ ASSERT_EFI_ERROR (Status);
+ MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
+ CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
+ //
+ // If Mp Table exists
+ //
+ if (MpsTableOri != NULL) {
+ //
+ // Get Mps table length, including Ext table
+ //
+ BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
+ MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
+ CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
+
+ if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
+ BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
+ BufferPtr += SYS_TABLE_PAD (BufferPtr);
+ OemTableNew = (VOID *)(UINTN)BufferPtr;
+ OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
+ CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
+ MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
+ }
+ MpsTableNew->Checksum = 0;
+ MpsTableNew->Checksum = GetBufferCheckSum (MpsTableNew, MpsTableOri->BaseTableLength);
+ MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
+ MpsFloatingPointerNew->Checksum = 0;
+ MpsFloatingPointerNew->Checksum = GetBufferCheckSum (MpsFloatingPointerNew, FPLength);
+ }
+ //
+ // Change the pointer
+ //
+ *Table = MpsFloatingPointerNew;
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/Library/DuetBdsLib/BdsPlatform.h b/DuetPkg/Library/DuetBdsLib/BdsPlatform.h new file mode 100644 index 0000000000..ce2a0ba2b8 --- /dev/null +++ b/DuetPkg/Library/DuetBdsLib/BdsPlatform.h @@ -0,0 +1,312 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+--*/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Smbios.h>
+#include <IndustryStandard/LegacyBiosMpTable.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Library/PlatformBdsLib.h>
+#include <Library/GraphicsLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <Protocol/PciIo.h>
+
+#include <Guid/Bmp.h>
+#include <Guid/Acpi.h>
+#include <Guid/Smbios.h>
+#include <Guid/Mps.h>
+#include <Guid/HobList.h>
+#include <Guid/PciExpressBaseAddress.h>
+#include <Guid/GlobalVariable.h>
+
+extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[];
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH gUartDeviceNode;
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
+//
+//
+//
+#define VarConsoleInpDev L"ConInDev"
+#define VarConsoleInp L"ConIn"
+#define VarConsoleOutDev L"ConOutDev"
+#define VarConsoleOut L"ConOut"
+#define VarErrorOutDev L"ErrOutDev"
+#define VarErrorOut L"ErrOut"
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+ { \
+ HARDWARE_DEVICE_PATH, \
+ HW_PCI_DP, \
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8), \
+ (Func), \
+ (Dev) \
+ }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), \
+ EISA_PNP_ID((PnpId)), \
+ 0 \
+ }
+
+#define gPciRootBridge \
+ PNPID_DEVICE_PATH_NODE(0x0A03)
+
+#define gPciIsaBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+ PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+ PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_UART_DP, \
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8), \
+ 0, \
+ 115200, \
+ 8, \
+ 1, \
+ 1 \
+ }
+
+#define gPcAnsiTerminal \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_VENDOR_DP, \
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), \
+ DEVICE_PATH_MESSAGING_PC_ANSI \
+ }
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+ END_DEVICE_PATH_LENGTH, \
+ 0 \
+ }
+
+#define PCI_CLASS_SCC 0x07
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_16550 0x02
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+
+#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF
+#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )
+//
+// Platform Root Bridge
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IsaBridge;
+ ACPI_HID_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IsaBridge;
+ ACPI_HID_DEVICE_PATH IsaSerial;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH VgaDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PciBridge;
+ PCI_DEVICE_PATH SerialDevice;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;
+
+//
+// the short form device path for Usb keyboard
+//
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0;
+
+//
+// Platform BDS Functions
+//
+VOID
+PlatformBdsInit (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
+ )
+;
+
+VOID
+PlatformBdsPolicyBehavior (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
+ IN LIST_ENTRY *DriverOptionList,
+ IN LIST_ENTRY *BootOptionList
+ )
+;
+
+VOID
+PlatformBdsGetDriverOption (
+ IN LIST_ENTRY *BdsDriverLists
+ )
+;
+
+EFI_STATUS
+BdsMemoryTest (
+ EXTENDMEM_COVERAGE_LEVEL Level
+ )
+;
+
+EFI_STATUS
+PlatformBdsShowProgress (
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ CHAR16 *Title,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ UINTN Progress,
+ UINTN PreviousValue
+ )
+;
+
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+;
+
+VOID
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+;
+
+VOID
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+;
+
+EFI_STATUS
+ProcessCapsules (
+ EFI_BOOT_MODE BootMode
+ )
+;
+
+EFI_STATUS
+PlatformBdsConnectConsole (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+;
+
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ )
+;
+
+EFI_STATUS
+ConvertMpsTable (
+ IN OUT VOID **Table
+ )
+;
+
+EFI_STATUS
+ConvertSmbiosTable (
+ IN OUT VOID **Table
+ )
+;
+
+EFI_STATUS
+ConvertAcpiTable (
+ IN UINTN TableLen,
+ IN OUT VOID **Table
+ )
+;
+
+EFI_STATUS
+ConvertSystemTable (
+ IN EFI_GUID *TableGuid,
+ IN OUT VOID **Table
+ )
+;
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ )
+;
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/DuetPkg/Library/DuetBdsLib/PlatformBds.inf b/DuetPkg/Library/DuetBdsLib/PlatformBds.inf new file mode 100644 index 0000000000..12d507b5d6 --- /dev/null +++ b/DuetPkg/Library/DuetBdsLib/PlatformBds.inf @@ -0,0 +1,64 @@ +#/*++
+#
+# Copyright (c) 2006 - 2007, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# PlatformBds.inf
+#
+# Abstract:
+#
+# Component description file for Bds module.
+#
+#--*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DuetBds
+ FILE_GUID = A6F691AC-31C8-4444-854C-E2C1A6950F92
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+
+[Sources.common]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Nt32Pkg/Nt32Pkg.dec
+ DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ GraphicsLib
+ GenericBdsLib
+ HobLib
+ UefiLib
+ DevicePathLib
+
+[Guids]
+ gEfiDefaultBmpLogoGuid
+ gEfiGlobalVariableGuid
+ gEfiPciExpressBaseAddressGuid
+ gEfiAcpi20TableGuid
+ gEfiMpsTableGuid
+ gEfiSmbiosTableGuid
+ gEfiAcpiTableGuid
\ No newline at end of file diff --git a/DuetPkg/Library/DuetBdsLib/PlatformData.c b/DuetPkg/Library/DuetBdsLib/PlatformData.c new file mode 100644 index 0000000000..e1a0cde3d4 --- /dev/null +++ b/DuetPkg/Library/DuetBdsLib/PlatformData.c @@ -0,0 +1,157 @@ +/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ PlatformData.c
+
+Abstract:
+
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+--*/
+
+#include "BdsPlatform.h"
+
+//
+// Predefined platform default time out value
+//
+UINT16 gPlatformBootTimeOutDefault = 3;
+
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH gUartDeviceNode = gUart;
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
+
+//
+// Predefined platform root bridge
+//
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
+ gPciRootBridge,
+ gEndEntire
+};
+
+EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
+ NULL
+};
+
+USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+ },
+ 0xffff, // VendorId
+ 0xffff, // ProductId
+ CLASS_HID, // DeviceClass
+ SUBCLASS_BOOT, // DeviceSubClass
+ PROTOCOL_KEYBOARD // DeviceProtocol
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+/*
+//
+// Platform specific Dummy ISA keyboard device path
+//
+PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH gDummyIsaKeyboardDevicePath = {
+ gPciRootBridge,
+ gPciIsaBridge,
+ gPnpPs2Keyboard,
+ gEndEntire
+};
+
+//
+// Platform specific Dummy ISA serial device path
+//
+PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH gDummyIsaSerialDevicePath = {
+ gPciRootBridge,
+ gPciIsaBridge,
+ gPnp16550ComPort,
+ gUart,
+ gPcAnsiTerminal,
+ gEndEntire
+};
+
+//
+// Platform specific Dummy PCI VGA device path
+//
+PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH gDummyPciVgaDevicePath = {
+ gPciRootBridge,
+ PCI_DEVICE_PATH_NODE(0, 0x2),
+ gEndEntire
+};
+
+//
+// Platform specific Dummy PCI serial device path
+//
+PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH gDummyPciSerialDevicePath = {
+ gPciRootBridge,
+ gP2PBridge,
+ PCI_DEVICE_PATH_NODE(0, 0x0),
+ gUart,
+ gPcAnsiTerminal,
+ gEndEntire
+};
+*/
+//
+// Predefined platform default console device path
+//
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ //
+ // need update dynamically
+ //
+// {
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaSerialDevicePath,
+// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+// },
+// {
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaKeyboardDevicePath,
+// (CONSOLE_IN | STD_ERROR)
+// },
+// {
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciVgaDevicePath,
+// CONSOLE_OUT
+// },
+// {
+// (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciSerialDevicePath,
+// (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+// },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL*) &gUsbClassKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform specific driver option
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
+
diff --git a/DuetPkg/PcRtc/Ia32/RealTimeClock.c b/DuetPkg/PcRtc/Ia32/RealTimeClock.c new file mode 100644 index 0000000000..dc2a79b948 --- /dev/null +++ b/DuetPkg/PcRtc/Ia32/RealTimeClock.c @@ -0,0 +1,170 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Ia32PcRtc.c
+
+Abstract:
+
+--*/
+#include "RealTimeClock.h"
+
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ Capabilities - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetTime (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcSetTime (Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enabled - TODO: add argument description
+ Pending - TODO: add argument description
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enabled - TODO: add argument description
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+InitializeRealTimeClock (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle;
+
+
+ EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);
+
+ Status = PcRtcInit (&mModuleGlobal);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;
+ SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;
+ SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;
+ SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;
+
+ NewHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewHandle,
+ &gEfiRealTimeClockArchProtocolGuid,
+ NULL,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/DuetPkg/PcRtc/Ia32RealTimeClock.dxs b/DuetPkg/PcRtc/Ia32RealTimeClock.dxs new file mode 100644 index 0000000000..ff9f52fb7a --- /dev/null +++ b/DuetPkg/PcRtc/Ia32RealTimeClock.dxs @@ -0,0 +1,29 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Ia32PcRtc.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+
+DEPENDENCY_START
+ EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/PcRtc/Ipf/IpfPcRtc.c b/DuetPkg/PcRtc/Ipf/IpfPcRtc.c new file mode 100644 index 0000000000..ef2260b214 --- /dev/null +++ b/DuetPkg/PcRtc/Ipf/IpfPcRtc.c @@ -0,0 +1,185 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IpfPcRtc.c
+
+Abstract:
+ Register the extended SAL infrastructure.
+
+ Make the EFI RT APIs call extended SAL calls via the RT lib wrappers.
+ We can not do this on IA-32 as RT lib wrappers call via rRT.
+
+--*/
+
+#include "RealTimeClock.h"
+
+//
+// Don't use directly after virtual address have been registered.
+//
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;
+
+SAL_RETURN_REGS
+PcRtcEsalServicesClassCommonEntry (
+ IN UINT64 FunctionId,
+ IN UINT64 Arg2,
+ IN UINT64 Arg3,
+ IN UINT64 Arg4,
+ IN UINT64 Arg5,
+ IN UINT64 Arg6,
+ IN UINT64 Arg7,
+ IN UINT64 Arg8,
+ IN SAL_EXTENDED_SAL_PROC ExtendedSalProc,
+ IN BOOLEAN VirtualMode,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ Main entry for Extended SAL Reset Services
+
+Arguments:
+
+ FunctionId Function Id which needed to be called.
+ Arg2 EFI_RESET_TYPE, whether WARM of COLD reset
+ Arg3 Last EFI_STATUS
+ Arg4 Data Size of UNICODE STRING passed in ARG5
+ Arg5 Unicode String which CHAR16*
+
+Returns:
+
+ SAL_RETURN_REGS
+
+--*/
+// TODO: Arg6 - add argument and description to function comment
+// TODO: Arg7 - add argument and description to function comment
+// TODO: Arg8 - add argument and description to function comment
+// TODO: ExtendedSalProc - add argument and description to function comment
+// TODO: VirtualMode - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+{
+ EFI_STATUS EfiStatus;
+ SAL_RETURN_REGS ReturnVal;
+
+ switch (FunctionId) {
+ case GetTime:
+ EfiStatus = PcRtcGetTime ((EFI_TIME *) Arg2, (EFI_TIME_CAPABILITIES *) Arg3, Global);
+ break;
+
+ case SetTime:
+ EfiStatus = PcRtcSetTime ((EFI_TIME *) Arg2, Global);
+ break;
+
+ case GetWakeupTime:
+ EfiStatus = PcRtcGetWakeupTime ((BOOLEAN *) Arg2, (BOOLEAN *) Arg3, (EFI_TIME *) Arg4, Global);
+ break;
+
+ case SetWakeupTime:
+ EfiStatus = PcRtcSetWakeupTime ((BOOLEAN) Arg2, (EFI_TIME *) Arg3, Global);
+ break;
+
+ case InitializeThreshold:
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
+ break;
+
+ case BumpThresholdCount:
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
+ break;
+
+ case GetThresholdCount:
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
+ break;
+
+ case GetRtcFreq:
+ EfiStatus = EFI_SAL_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ EfiStatus = EFI_SAL_INVALID_ARGUMENT;
+ break;;
+ }
+
+ ReturnVal.Status = EfiStatus;
+ return ReturnVal;
+}
+
+EFI_STATUS
+EFIAPI
+InitializePcRtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_TIME Time;
+ EFI_TIME_CAPABILITIES Capabilities;
+ EFI_STATUS EfiStatus;
+
+ EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);
+
+ EfiInitializeLock (&mModuleGlobal.RtcLock, EFI_TPL_HIGH_LEVEL);
+
+ EfiStatus = PcRtcInit (&mModuleGlobal);
+ if (EFI_ERROR (EfiStatus)) {
+ return EfiStatus;
+ }
+
+ RegisterEsalClass (
+ &gEfiExtendedSalRtcServicesProtocolGuid,
+ &mModuleGlobal,
+ PcRtcEsalServicesClassCommonEntry,
+ GetTime,
+ PcRtcEsalServicesClassCommonEntry,
+ SetTime,
+ PcRtcEsalServicesClassCommonEntry,
+ GetWakeupTime,
+ PcRtcEsalServicesClassCommonEntry,
+ SetWakeupTime,
+ PcRtcEsalServicesClassCommonEntry,
+ GetRtcFreq,
+ PcRtcEsalServicesClassCommonEntry,
+ InitializeThreshold,
+ PcRtcEsalServicesClassCommonEntry,
+ BumpThresholdCount,
+ PcRtcEsalServicesClassCommonEntry,
+ GetThresholdCount,
+ NULL
+ );
+ //
+ // the following code is to initialize the RTC fields in case the values read
+ // back from CMOS are invalid at the first time.
+ //
+ EfiStatus = PcRtcGetTime (&Time, &Capabilities, &mModuleGlobal);
+ if (EFI_ERROR (EfiStatus)) {
+ Time.Second = RTC_INIT_SECOND;
+ Time.Minute = RTC_INIT_MINUTE;
+ Time.Hour = RTC_INIT_HOUR;
+ Time.Day = RTC_INIT_DAY;
+ Time.Month = RTC_INIT_MONTH;
+ Time.Year = RTC_INIT_YEAR;
+ PcRtcSetTime (&Time, &mModuleGlobal);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/PcRtc/IpfRealTimeClock.dxs b/DuetPkg/PcRtc/IpfRealTimeClock.dxs new file mode 100644 index 0000000000..4d05b4f8a3 --- /dev/null +++ b/DuetPkg/PcRtc/IpfRealTimeClock.dxs @@ -0,0 +1,28 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IpfPcRtc.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (ExtendedSalGuid)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+
+DEPENDENCY_START
+ EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/PcRtc/RealTimeClock.c b/DuetPkg/PcRtc/RealTimeClock.c new file mode 100644 index 0000000000..b677cc5c95 --- /dev/null +++ b/DuetPkg/PcRtc/RealTimeClock.c @@ -0,0 +1,1065 @@ +/*++
+
+Copyright (c) 2005 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcRtc.c
+
+Abstract:
+
+ RTC Architectural Protocol GUID as defined in EFI 2.0
+
+--*/
+
+#include "RealTimeClock.h"
+
+BOOLEAN
+DayValid (
+ IN EFI_TIME *Time
+ );
+
+BOOLEAN
+IsLeapYear (
+ IN EFI_TIME *Time
+ );
+
+BOOLEAN
+IsWithinOneDay (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ );
+
+INTN
+CompareHMS (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ );
+
+UINT8
+RtcRead (
+ IN UINT8 Address
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Address - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ return IoRead8 (PCAT_RTC_DATA_REGISTER);
+}
+
+INTN
+CompareHMS (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ )
+/*++
+
+Routine Description:
+
+ Compare the Hour, Minute and Second of the 'From' time and the 'To' time.
+ Only compare H/M/S in EFI_TIME and ignore other fields here.
+
+Arguments:
+
+ From - the first time
+ To - the second time
+
+Returns:
+
+ >0 : The H/M/S of the 'From' time is later than those of 'To' time
+ ==0 : The H/M/S of the 'From' time is same as those of 'To' time
+ <0 : The H/M/S of the 'From' time is earlier than those of 'To' time
+
+--*/
+
+{
+ if ((From->Hour > To->Hour) ||
+ ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||
+ ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {
+ return 1;
+ } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+VOID
+RtcWrite (
+ IN UINT8 Address,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Address - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);
+}
+
+EFI_STATUS
+PcRtcInit (
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Global - TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_A RegisterA;
+ RTC_REGISTER_B RegisterB;
+ RTC_REGISTER_C RegisterC;
+ RTC_REGISTER_D RegisterD;
+ UINT8 Century;
+ EFI_TIME Time;
+
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ EfiAcquireLock (&Global->RtcLock);
+
+ //
+ // Initialize RTC Register
+ //
+ // Make sure Division Chain is properly configured,
+ // or RTC clock won't "tick" -- time won't increment
+ //
+ RegisterA.Data = RTC_INIT_REGISTER_A;
+ RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);
+
+ //
+ // Read Register B
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ //
+ // Clear RTC flag register
+ //
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
+
+ //
+ // Clear RTC register D
+ //
+ RegisterD.Data = RTC_INIT_REGISTER_D;
+ RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Global->RtcLock);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ Time.Second = RtcRead (RTC_ADDRESS_SECONDS);
+ Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);
+ Time.Hour = RtcRead (RTC_ADDRESS_HOURS);
+ Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time.Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time.Year = RtcRead (RTC_ADDRESS_YEAR);
+
+ ConvertRtcTimeToEfiTime (&Time, RegisterB);
+
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
+ } else {
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
+ }
+
+ Time.Year = (UINT16) (Century * 100 + Time.Year);
+
+ //
+ // Set RTC configuration after get original time
+ //
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);
+
+ //
+ // Release RTC Lock.
+ //
+ EfiReleaseLock (&Global->RtcLock);
+
+ //
+ // Validate time fields
+ //
+ Status = RtcTimeFieldsValid (&Time);
+ if (EFI_ERROR (Status)) {
+ Time.Second = RTC_INIT_SECOND;
+ Time.Minute = RTC_INIT_MINUTE;
+ Time.Hour = RTC_INIT_HOUR;
+ Time.Day = RTC_INIT_DAY;
+ Time.Month = RTC_INIT_MONTH;
+ Time.Year = RTC_INIT_YEAR;
+ }
+ //
+ // Reset time value according to new RTC configuration
+ //
+ PcRtcSetTime (&Time, Global);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcRtcGetTime (
+ OUT EFI_TIME *Time,
+ IN EFI_TIME_CAPABILITIES *Capabilities,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+ Returns:
+--*/
+// TODO: Time - add argument and description to function comment
+// TODO: Capabilities - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+ UINTN BufferSize;
+
+ //
+ // Check parameters for null pointer
+ //
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ EfiAcquireLock (&Global->RtcLock);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Global->RtcLock);
+ return Status;
+ }
+ //
+ // Read Register B
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS);
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+
+ ConvertRtcTimeToEfiTime (Time, RegisterB);
+
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
+ } else {
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
+ }
+
+ Time->Year = (UINT16) (Century * 100 + Time->Year);
+
+ //
+ // Release RTC Lock.
+ //
+ EfiReleaseLock (&Global->RtcLock);
+
+ //
+ // Get the variable that containts the TimeZone and Daylight fields
+ //
+ Time->TimeZone = Global->SavedTimeZone;
+ Time->Daylight = Global->Daylight;
+
+ BufferSize = sizeof (INT16) + sizeof (UINT8);
+
+ //
+ // Make sure all field values are in correct range
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Fill in Capabilities if it was passed in
+ //
+ if (Capabilities) {
+ Capabilities->Resolution = 1;
+ //
+ // 1 hertz
+ //
+ Capabilities->Accuracy = 50000000;
+ //
+ // 50 ppm
+ //
+ Capabilities->SetsToZero = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcRtcSetTime (
+ IN EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+ Returns:
+--*/
+// TODO: Time - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_TIME RtcTime;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure that the time fields are valid
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ EfiAcquireLock (&Global->RtcLock);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Global->RtcLock);
+ return Status;
+ }
+ //
+ // Read Register B, and inhibit updates of the RTC
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+ RegisterB.Bits.SET = 1;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
+
+ RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);
+ RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);
+ RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);
+ RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);
+ RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);
+ RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+ Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80));
+ }
+
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);
+
+ //
+ // Allow updates of the RTC registers
+ //
+ RegisterB.Bits.SET = 0;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ //
+ // Release RTC Lock.
+ //
+ EfiReleaseLock (&Global->RtcLock);
+
+ //
+ // Set the variable that containts the TimeZone and Daylight fields
+ //
+ Global->SavedTimeZone = Time->TimeZone;
+ Global->Daylight = Time->Daylight;
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: Enabled - add argument and description to function comment
+// TODO: Pending - add argument and description to function comment
+// TODO: Time - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ RTC_REGISTER_B RegisterB;
+ RTC_REGISTER_C RegisterC;
+ UINT8 Century;
+
+ //
+ // Check paramters for null pointers
+ //
+ if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {
+ return EFI_INVALID_PARAMETER;
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ EfiAcquireLock (&Global->RtcLock);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Global->RtcLock);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Read Register B and Register C
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
+
+ //
+ // Get the Time/Date/Daylight Savings values.
+ //
+ *Enabled = RegisterB.Bits.AIE;
+ if (*Enabled) {
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+ } else {
+ Time->Second = 0;
+ Time->Minute = 0;
+ Time->Hour = 0;
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);
+ }
+
+ ConvertRtcTimeToEfiTime (Time, RegisterB);
+
+ if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+ Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
+ } else {
+ Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
+ }
+
+ Time->Year = (UINT16) (Century * 100 + Time->Year);
+
+ //
+ // Release RTC Lock.
+ //
+ EfiReleaseLock (&Global->RtcLock);
+
+ //
+ // Make sure all field values are in correct range
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ *Pending = RegisterC.Bits.AF;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcSetWakeupTime (
+ IN BOOLEAN Enable,
+ OUT EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: Enable - add argument and description to function comment
+// TODO: Time - add argument and description to function comment
+// TODO: Global - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_TIME RtcTime;
+ RTC_REGISTER_B RegisterB;
+ UINT8 Century;
+ EFI_TIME_CAPABILITIES Capabilities;
+
+ if (Enable) {
+
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure that the time fields are valid
+ //
+ Status = RtcTimeFieldsValid (Time);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Just support set alarm time within 24 hours
+ //
+ PcRtcGetTime (&RtcTime, &Capabilities, Global);
+ if (!IsWithinOneDay (&RtcTime, Time)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Make a local copy of the time and date
+ //
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+
+ }
+ //
+ // Acquire RTC Lock to make access to RTC atomic
+ //
+ EfiAcquireLock (&Global->RtcLock);
+
+ //
+ // Wait for up to 0.1 seconds for the RTC to be updated
+ //
+ Status = RtcWaitToUpdate (100000);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Global->RtcLock);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Read Register B, and inhibit updates of the RTC
+ //
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+ RegisterB.Bits.SET = 1;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ if (Enable) {
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
+
+ //
+ // Set RTC alarm time
+ //
+ RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);
+ RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);
+ RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);
+
+ RegisterB.Bits.AIE = 1;
+
+ } else {
+ RegisterB.Bits.AIE = 0;
+ }
+ //
+ // Allow updates of the RTC registers
+ //
+ RegisterB.Bits.SET = 0;
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+ //
+ // Release RTC Lock.
+ //
+ EfiReleaseLock (&Global->RtcLock);
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+BcdToDecimal (
+ IN UINT8 BcdValue
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: BcdValue - add argument and description to function comment
+{
+ UINTN High;
+ UINTN Low;
+
+ High = BcdValue >> 4;
+ Low = BcdValue - (High << 4);
+
+ return (UINT8) (Low + (High * 10));
+}
+
+EFI_STATUS
+RtcTestCenturyRegister (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ UINT8 Century;
+ UINT8 Temp;
+
+ Century = RtcRead (RTC_ADDRESS_CENTURY);
+ //
+ // RtcWrite (RTC_ADDRESS_CENTURY, 0x00);
+ //
+ Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);
+ if (Temp == 0x19 || Temp == 0x20) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+VOID
+ConvertRtcTimeToEfiTime (
+ IN EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: Time - add argument and description to function comment
+// TODO: RegisterB - add argument and description to function comment
+{
+ BOOLEAN PM;
+
+ if ((Time->Hour) & 0x80) {
+ PM = TRUE;
+ } else {
+ PM = FALSE;
+ }
+
+ Time->Hour = (UINT8) (Time->Hour & 0x7f);
+
+ if (RegisterB.Bits.DM == 0) {
+ Time->Year = BcdToDecimal ((UINT8) Time->Year);
+ Time->Month = BcdToDecimal (Time->Month);
+ Time->Day = BcdToDecimal (Time->Day);
+ Time->Hour = BcdToDecimal (Time->Hour);
+ Time->Minute = BcdToDecimal (Time->Minute);
+ Time->Second = BcdToDecimal (Time->Second);
+ }
+ //
+ // If time is in 12 hour format, convert it to 24 hour format
+ //
+ if (RegisterB.Bits.MIL == 0) {
+ if (PM && Time->Hour < 12) {
+ Time->Hour = (UINT8) (Time->Hour + 12);
+ }
+
+ if (!PM && Time->Hour == 12) {
+ Time->Hour = 0;
+ }
+ }
+
+ Time->Nanosecond = 0;
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Time->Daylight = 0;
+}
+
+EFI_STATUS
+RtcWaitToUpdate (
+ UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+Returns:
+--*/
+// TODO: Timeout - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ RTC_REGISTER_A RegisterA;
+ RTC_REGISTER_D RegisterD;
+
+ //
+ // See if the RTC is functioning correctly
+ //
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+
+ if (RegisterD.Bits.VRT == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Wait for up to 0.1 seconds for the RTC to be ready.
+ //
+ Timeout = (Timeout / 10) + 1;
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ while (RegisterA.Bits.UIP == 1 && Timeout > 0) {
+ MicroSecondDelay (10);
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+ Timeout--;
+ }
+
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+ if (Timeout == 0 || RegisterD.Bits.VRT == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RtcTimeFieldsValid (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+ Returns:
+--*/
+// TODO: Time - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (Time->Year < 1998 ||
+ Time->Year > 2099 ||
+ Time->Month < 1 ||
+ Time->Month > 12 ||
+ (!DayValid (Time)) ||
+ Time->Hour > 23 ||
+ Time->Minute > 59 ||
+ Time->Second > 59 ||
+ Time->Nanosecond > 999999999 ||
+ (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
+ (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+DayValid (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+
+ INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ if (Time->Day < 1 ||
+ Time->Day > DayOfMonth[Time->Month - 1] ||
+ (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
+ ) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+IsLeapYear (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ if (Time->Year % 4 == 0) {
+ if (Time->Year % 100 == 0) {
+ if (Time->Year % 400 == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+VOID
+ConvertEfiTimeToRtcTime (
+ IN EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB,
+ IN UINT8 *Century
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+Returns:
+--*/
+// TODO: Time - add argument and description to function comment
+// TODO: RegisterB - add argument and description to function comment
+// TODO: Century - add argument and description to function comment
+{
+ BOOLEAN PM;
+
+ PM = TRUE;
+ //
+ // Adjust hour field if RTC in in 12 hour mode
+ //
+ if (RegisterB.Bits.MIL == 0) {
+ if (Time->Hour < 12) {
+ PM = FALSE;
+ }
+
+ if (Time->Hour >= 13) {
+ Time->Hour = (UINT8) (Time->Hour - 12);
+ } else if (Time->Hour == 0) {
+ Time->Hour = 12;
+ }
+ }
+ //
+ // Set the Time/Date/Daylight Savings values.
+ //
+ *Century = DecimaltoBcd ((UINT8) (Time->Year / 100));
+
+ Time->Year = (UINT16) (Time->Year % 100);
+
+ if (RegisterB.Bits.DM == 0) {
+ Time->Year = DecimaltoBcd ((UINT8) Time->Year);
+ Time->Month = DecimaltoBcd (Time->Month);
+ Time->Day = DecimaltoBcd (Time->Day);
+ Time->Hour = DecimaltoBcd (Time->Hour);
+ Time->Minute = DecimaltoBcd (Time->Minute);
+ Time->Second = DecimaltoBcd (Time->Second);
+ }
+ //
+ // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
+ //
+ if (RegisterB.Bits.MIL == 0 && PM) {
+ Time->Hour = (UINT8) (Time->Hour | 0x80);
+ }
+}
+
+BOOLEAN
+IsWithinOneDay (
+ IN EFI_TIME *From,
+ IN EFI_TIME *To
+ )
+/*++
+
+Routine Description:
+
+ Judge whether two days are adjacent.
+
+Arguments:
+
+ From - the first day
+ To - the second day
+
+Returns:
+
+ TRUE - The interval of two days are within one day.
+ FALSE - The interval of two days exceed ony day or parameter error.
+
+--*/
+{
+ UINT8 DayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ BOOLEAN Adjacent = FALSE;
+
+ if (From->Year == To->Year) {
+ if (From->Month == To->Month) {
+ if ((From->Day + 1) == To->Day) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ } else if (From->Day == To->Day) {
+ if ((CompareHMS(From, To) <= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {
+ if ((From->Month == 2) && !IsLeapYear(From)) {
+ if (From->Day == 28) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ } else if (From->Day == DayOfMonth[From->Month - 1]) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+ }
+ } else if (((From->Year + 1) == To->Year) &&
+ (From->Month == 12) &&
+ (From->Day == 31) &&
+ (To->Month == 1) &&
+ (To->Day == 1)) {
+ if ((CompareHMS(From, To) >= 0)) {
+ Adjacent = TRUE;
+ }
+ }
+
+ return Adjacent;
+}
+
+UINT8
+DecimaltoBcd (
+ IN UINT8 DecValue
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+Returns:
+
+--*/
+// TODO: DecValue - add argument and description to function comment
+{
+ UINTN High;
+ UINTN Low;
+
+ High = DecValue / 10;
+ Low = DecValue - (High * 10);
+
+ return (UINT8) (Low + (High << 4));
+}
diff --git a/DuetPkg/PcRtc/RealTimeClock.h b/DuetPkg/PcRtc/RealTimeClock.h new file mode 100644 index 0000000000..f157813cf7 --- /dev/null +++ b/DuetPkg/PcRtc/RealTimeClock.h @@ -0,0 +1,491 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcRtc.h
+
+Abstract:
+
+ Include for real time clock driver
+
+Revision History
+
+
+--*/
+
+#ifndef _RTC_H_
+#define _RTC_H_
+
+#include <FrameworkDxe.h>
+
+#include <Protocol/RealTimeClock.h>
+
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseMemoryLib.h>
+
+typedef struct {
+ EFI_LOCK RtcLock;
+ UINT16 SavedTimeZone;
+ UINT8 Daylight;
+} PC_RTC_MODULE_GLOBALS;
+
+#define PCAT_RTC_ADDRESS_REGISTER 0x70
+#define PCAT_RTC_DATA_REGISTER 0x71
+
+//
+// Dallas DS12C887 Real Time Clock
+//
+#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
+#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
+#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
+#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
+#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
+#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
+#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
+#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
+#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
+#define RTC_ADDRESS_REGISTER_B 11 // R/W
+#define RTC_ADDRESS_REGISTER_C 12 // RO
+#define RTC_ADDRESS_REGISTER_D 13 // RO
+#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
+//
+// Date and time initial values.
+// They are used if the RTC values are invalid during driver initialization
+//
+#define RTC_INIT_SECOND 0
+#define RTC_INIT_MINUTE 0
+#define RTC_INIT_HOUR 0
+#define RTC_INIT_DAY 1
+#define RTC_INIT_MONTH 1
+#define RTC_INIT_YEAR 2001
+
+//
+// Register initial values
+//
+#define RTC_INIT_REGISTER_A 0x26
+#define RTC_INIT_REGISTER_B 0x02
+#define RTC_INIT_REGISTER_D 0x0
+
+#pragma pack(1)
+//
+// Register A
+//
+typedef struct {
+ UINT8 RS : 4; // Rate Selection Bits
+ UINT8 DV : 3; // Divisor
+ UINT8 UIP : 1; // Update in progress
+} RTC_REGISTER_A_BITS;
+
+typedef union {
+ RTC_REGISTER_A_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_A;
+
+//
+// Register B
+//
+typedef struct {
+ UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled
+ UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode
+ UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format
+ UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output
+ UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled
+ UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled
+ UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled
+ UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited
+} RTC_REGISTER_B_BITS;
+
+typedef union {
+ RTC_REGISTER_B_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_B;
+
+//
+// Register C
+//
+typedef struct {
+ UINT8 Reserved : 4; // Read as zero. Can not be written.
+ UINT8 UF : 1; // Update End Interrupt Flag
+ UINT8 AF : 1; // Alarm Interrupt Flag
+ UINT8 PF : 1; // Periodic Interrupt Flag
+ UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE
+} RTC_REGISTER_C_BITS;
+
+typedef union {
+ RTC_REGISTER_C_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_C;
+
+//
+// Register D
+//
+typedef struct {
+ UINT8 Reserved : 7; // Read as zero. Can not be written.
+ UINT8 VRT : 1; // Valid RAM and Time
+} RTC_REGISTER_D_BITS;
+
+typedef union {
+ RTC_REGISTER_D_BITS Bits;
+ UINT8 Data;
+} RTC_REGISTER_D;
+
+#pragma pack()
+
+EFI_STATUS
+PcRtcInit (
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PcRtcSetTime (
+ IN EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PcRtcGetTime (
+ OUT EFI_TIME *Time,
+ IN EFI_TIME_CAPABILITIES *Capabilities,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ Capabilities - TODO: add argument description
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PcRtcSetWakeupTime (
+ IN BOOLEAN Enable,
+ OUT EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enable - TODO: add argument description
+ Time - TODO: add argument description
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PcRtcGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enabled - TODO: add argument description
+ Pending - TODO: add argument description
+ Time - TODO: add argument description
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+InitializePcRtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ SystemTable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT8
+BcdToDecimal (
+ IN UINT8 BcdValue
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ BcdValue - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RtcTimeFieldsValid (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT8
+DecimaltoBcd (
+ IN UINT8 DecValue
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ DecValue - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+ConvertEfiTimeToRtcTime (
+ IN EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB,
+ IN UINT8 *Century
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ RegisterB - TODO: add argument description
+ Century - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RtcTestCenturyRegister (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+ConvertRtcTimeToEfiTime (
+ IN EFI_TIME *Time,
+ IN RTC_REGISTER_B RegisterB
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ RegisterB - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RtcWaitToUpdate (
+ UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Timeout - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT8
+RtcSaveContext (
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+RtcRestoreContext (
+ IN UINT8 SavedAddressRegister,
+ IN PC_RTC_MODULE_GLOBALS *Global
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SavedAddressRegister - TODO: add argument description
+ Global - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/DuetPkg/PcRtc/RealTimeClock.inf b/DuetPkg/PcRtc/RealTimeClock.inf new file mode 100644 index 0000000000..0a9059422c --- /dev/null +++ b/DuetPkg/PcRtc/RealTimeClock.inf @@ -0,0 +1,63 @@ +#/*++
+#
+# Copyright (c) 2005, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# Abstract:
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RealTimeClock
+ FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeRealTimeClock
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ DuetPkg/DuetPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+ IoLib
+ TimerLib
+ BaseMemoryLib
+
+[Sources.common]
+ RealTimeClock.c
+ RealTimeClock.h
+
+[Sources.ia32]
+ Ia32/RealTimeClock.c
+
+[Sources.x64]
+ x64/RealTimeClock.c
+
+[Sources.ipf]
+ Ipf/RealTimeClock.c
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiMetronomeArchProtocolGuid
+ gEfiCpuIoProtocolGuid
+ gEfiRealTimeClockArchProtocolGuid
+
+[Depex]
+ gEfiCpuArchProtocolGuid AND gEfiMetronomeArchProtocolGuid AND gEfiCpuIoProtocolGuid
\ No newline at end of file diff --git a/DuetPkg/PcRtc/x64/RealTimeClock.c b/DuetPkg/PcRtc/x64/RealTimeClock.c new file mode 100644 index 0000000000..4f4410eb21 --- /dev/null +++ b/DuetPkg/PcRtc/x64/RealTimeClock.c @@ -0,0 +1,170 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ x64PcRtc.c
+
+Abstract:
+
+--*/
+
+#include "RealTimeClock.h"
+
+static PC_RTC_MODULE_GLOBALS mModuleGlobal;
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+ Capabilities - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetTime (
+ IN EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcSetTime (Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enabled - TODO: add argument description
+ Pending - TODO: add argument description
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Enabled - TODO: add argument description
+ Time - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);
+}
+
+EFI_STATUS
+EFIAPI
+InitializeRealTimeClock (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Arguments:
+
+
+
+Returns:
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle;
+
+ EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);
+
+ Status = PcRtcInit (&mModuleGlobal);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SystemTable->RuntimeServices->GetTime = PcRtcEfiGetTime;
+ SystemTable->RuntimeServices->SetTime = PcRtcEfiSetTime;
+ SystemTable->RuntimeServices->GetWakeupTime = PcRtcEfiGetWakeupTime;
+ SystemTable->RuntimeServices->SetWakeupTime = PcRtcEfiSetWakeupTime;
+
+ NewHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewHandle,
+ &gEfiRealTimeClockArchProtocolGuid,
+ NULL,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/DuetPkg/PcRtc/x64RealTimeClock.dxs b/DuetPkg/PcRtc/x64RealTimeClock.dxs new file mode 100644 index 0000000000..3497da0635 --- /dev/null +++ b/DuetPkg/PcRtc/x64RealTimeClock.dxs @@ -0,0 +1,29 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ x64PcRtc.dxs
+
+Abstract:
+ Dependency expression source file.
+
+--*/
+
+
+#include "EfiDepex.h"
+
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+
+DEPENDENCY_START
+ EFI_CPU_ARCH_PROTOCOL_GUID AND EFI_METRONOME_ARCH_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c new file mode 100644 index 0000000000..286c03ef4c --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c @@ -0,0 +1,845 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DeviceIo.c
+
+Abstract:
+
+ EFI PC-AT PCI Device IO driver
+
+--*/
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_STATUS
+DeviceIoConstructor (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINT16 PrimaryBus,
+ IN UINT16 SubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+
+ Handle - Handle of PCI RootBridge IO instance
+ PciRootBridgeIo - PCI RootBridge IO instance
+ DevicePath - Device Path of PCI RootBridge IO instance
+ PrimaryBus - Primary Bus
+ SubordinateBus - Subordinate Bus
+
+Returns:
+
+ EFI_SUCCESS - This driver is added to ControllerHandle.
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
+ Others - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ //
+ // Initialize the Device IO device instance.
+ //
+ Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
+ Private->Handle = Handle;
+ Private->PciRootBridgeIo = PciRootBridgeIo;
+ Private->DevicePath = DevicePath;
+ Private->PrimaryBus = PrimaryBus;
+ Private->SubordinateBus = SubordinateBus;
+
+ Private->DeviceIo.Mem.Read = DeviceIoMemRead;
+ Private->DeviceIo.Mem.Write = DeviceIoMemWrite;
+ Private->DeviceIo.Io.Read = DeviceIoIoRead;
+ Private->DeviceIo.Io.Write = DeviceIoIoWrite;
+ Private->DeviceIo.Pci.Read = DeviceIoPciRead;
+ Private->DeviceIo.Pci.Write = DeviceIoPciWrite;
+ Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;
+ Private->DeviceIo.Map = DeviceIoMap;
+ Private->DeviceIo.Unmap = DeviceIoUnmap;
+ Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;
+ Private->DeviceIo.Flush = DeviceIoFlush;
+ Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;
+
+ //
+ // Install protocol interfaces for the Device IO device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiDeviceIoProtocolGuid,
+ &Private->DeviceIo,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width > MMIO_COPY_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Width >= MMIO_COPY_UINT8) {
+ Width = Width - MMIO_COPY_UINT8;
+ Status = Private->PciRootBridgeIo->CopyMem (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ (UINT64) Buffer,
+ Address,
+ Count
+ );
+ } else {
+ Status = Private->PciRootBridgeIo->Mem.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width > MMIO_COPY_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Width >= MMIO_COPY_UINT8) {
+ Width = Width - MMIO_COPY_UINT8;
+ Status = Private->PciRootBridgeIo->CopyMem (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ (UINT64) Buffer,
+ Count
+ );
+ } else {
+ Status = Private->PciRootBridgeIo->Mem.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Io.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Io.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading PCI configuration space of device
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Pci.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing PCI configuration space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Pci.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendPciDevicePath (
+ IN DEVICE_IO_PRIVATE_DATA *Private,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN OUT UINT16 *BridgePrimaryBus,
+ IN OUT UINT16 *BridgeSubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Append a PCI device path node to another device path.
+
+Arguments:
+
+ Private - A pointer to DEVICE_IO_PRIVATE_DATA instance.
+ Bus - PCI bus number of the device.
+ Device - PCI device number of the device.
+ Function - PCI function number of the device.
+ DevicePath - Original device path which will be appended a PCI device path node.
+ BridgePrimaryBus - Primary bus number of the bridge.
+ BridgeSubordinateBus - Subordinate bus number of the bridge.
+
+Returns:
+
+ Pointer to the appended PCI device path.
+
+--*/
+{
+ UINT16 ThisBus;
+ UINT8 ThisDevice;
+ UINT8 ThisFunc;
+ UINT64 Address;
+ PCI_TYPE01 PciBridge;
+ PCI_TYPE01 *PciPtr;
+ EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
+ PCI_DEVICE_PATH PciNode;
+
+ PciPtr = &PciBridge;
+ for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
+ for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
+ for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
+ Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
+ ZeroMem (PciPtr, sizeof (PCI_TYPE01));
+ Private->DeviceIo.Pci.Read (
+ &Private->DeviceIo,
+ IO_UINT32,
+ Address,
+ 1,
+ &(PciPtr->Hdr.VendorId)
+ );
+ if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
+ break;
+ }
+ if (PciPtr->Hdr.VendorId == 0xffff) {
+ continue;
+ }
+
+ Private->DeviceIo.Pci.Read (
+ &Private->DeviceIo,
+ IO_UINT32,
+ Address,
+ sizeof (PCI_TYPE01) / sizeof (UINT32),
+ PciPtr
+ );
+ if (IS_PCI_BRIDGE (PciPtr)) {
+ if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
+
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+ PciNode.Device = ThisDevice;
+ PciNode.Function = ThisFunc;
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+ *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
+ *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
+ return ReturnDevicePath;
+ }
+ }
+
+ if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ break;
+ }
+ }
+ }
+ }
+
+ ZeroMem (&PciNode, sizeof (PciNode));
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+ PciNode.Device = Device;
+ PciNode.Function = Function;
+
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+ *BridgePrimaryBus = 0xffff;
+ *BridgeSubordinateBus = 0xffff;
+ return ReturnDevicePath;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINT64 Address,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Address - The PCI configuration space address of the device whose Device Path
+ is going to be returned.
+ PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.
+ Memory for the Device Path is allocated from the pool.
+
+Returns:
+
+ EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.
+ EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+{
+ DEVICE_IO_PRIVATE_DATA *Private;
+ UINT16 PrimaryBus;
+ UINT16 SubordinateBus;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Func;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
+ Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
+ Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
+
+ if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *PciDevicePath = Private->DevicePath;
+ PrimaryBus = Private->PrimaryBus;
+ SubordinateBus = Private->SubordinateBus;
+ do {
+ *PciDevicePath = AppendPciDevicePath (
+ Private,
+ Bus,
+ Device,
+ Func,
+ *PciDevicePath,
+ &PrimaryBus,
+ &SubordinateBus
+ );
+ if (*PciDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } while (PrimaryBus != 0xffff);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_OPERATION_TYPE Operation,
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Operation - Indicates if the bus master is going to read or write to system memory.
+ HostAddress - The system memory address to map to the device.
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ DeviceAddress - The resulting map address for the bus master device to use to access the
+ hosts HostAddress.
+ Mapping - A resulting value to pass to Unmap().
+
+Returns:
+
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = Private->PciRootBridgeIo->Map (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+ (VOID *) (UINTN) (*HostAddress),
+ NumberOfBytes,
+ DeviceAddress,
+ Mapping
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Mapping - The mapping value returned from Map().
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped.
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Status = Private->PciRootBridgeIo->Unmap (
+ Private->PciRootBridgeIo,
+ Mapping
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Type - The type allocation to perform.
+ MemoryType - The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ Pages - The number of pages to allocate.
+ PhysicalAddress - A pointer to store the base address of the allocated range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were allocated.
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
+ this platform.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+
+ HostAddress = *PhysicalAddress;
+
+ if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
+ Type = AllocateMaxAddress;
+ HostAddress = MAX_COMMON_BUFFER;
+ }
+
+ Status = gBS->AllocatePages (
+ Type,
+ MemoryType,
+ Pages,
+ &HostAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ *PhysicalAddress = HostAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+ IN EFI_DEVICE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes any posted write data to the device.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+
+ EFI_SUCCESS - The buffers were flushed.
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN EFI_PHYSICAL_ADDRESS HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Pages - The number of pages to free.
+ HostAddress - The base address of the range to free.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were freed.
+ EFI_NOT_FOUND - The requested memory pages were not allocated with
+ AllocateBuffer().
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
+
+--*/
+{
+ if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return gBS->FreePages (HostAddress, Pages);
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h new file mode 100644 index 0000000000..71d3a41e28 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h @@ -0,0 +1,449 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DeviceIo.h
+
+Abstract:
+
+ Private Data definition for Device IO driver
+
+--*/
+
+#ifndef _DEVICE_IO_H
+#define _DEVICE_IO_H
+
+
+
+#define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 'e', 'v', 'I')
+
+#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_DEVICE_IO_PROTOCOL DeviceIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT16 PrimaryBus;
+ UINT16 SubordinateBus;
+} DEVICE_IO_PRIVATE_DATA;
+
+#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
+
+EFI_STATUS
+DeviceIoConstructor (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINT16 PrimaryBus,
+ IN UINT16 SubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+
+ Handle - Handle of PCI RootBridge IO instance
+ PciRootBridgeIo - PCI RootBridge IO instance
+ DevicePath - Device Path of PCI RootBridge IO instance
+ PrimaryBus - Primary Bus
+ SubordinateBus - Subordinate Bus
+
+Returns:
+
+ EFI_SUCCESS - This driver is added to ControllerHandle.
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
+ Others - This driver does not support this device.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading PCI configuration space of device
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing PCI configuration space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINT64 Address,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Append a PCI device path node to another device path.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO_PROTOCOL.
+ Address - PCI bus,device, function.
+ PciDevicePath - PCI device path.
+
+Returns:
+
+ Pointer to the appended PCI device path.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_OPERATION_TYPE Operation,
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Operation - Indicates if the bus master is going to read or write to system memory.
+ HostAddress - The system memory address to map to the device.
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ DeviceAddress - The resulting map address for the bus master device to use to access the
+ hosts HostAddress.
+ Mapping - A resulting value to pass to Unmap().
+
+Returns:
+
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Mapping - The mapping value returned from Map().
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped.
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Type - The type allocation to perform.
+ MemoryType - The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ Pages - The number of pages to allocate.
+ HostAddress - A pointer to store the base address of the allocated range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were allocated.
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
+ this platform.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+ IN EFI_DEVICE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes any posted write data to the device.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+
+ EFI_SUCCESS - The buffers were flushed.
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN EFI_PHYSICAL_ADDRESS HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Pages - The number of pages to free.
+ HostAddress - The base address of the range to free.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were freed.
+ EFI_NOT_FOUND - The requested memory pages were not allocated with
+ AllocateBuffer().
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
+
+--*/
+;
+
+#endif
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c new file mode 100644 index 0000000000..0cbf047254 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c @@ -0,0 +1,734 @@ +/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Read (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Write (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Mapping. For IA-32 it is always 0.
+
+--*/
+{
+ *IoPortMapping = 0;
+ *MemoryPortMapping = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCI_CONFIG_ACCESS_CF8 Pci;
+ PCI_CONFIG_ACCESS_CF8 PciAligned;
+ UINT32 InStride;
+ UINT32 OutStride;
+ UINTN PciData;
+ UINTN PciDataStride;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT64 PciExpressRegAddr;
+ BOOLEAN UsePciExpressAccess;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) >= EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ UsePciExpressAccess = FALSE;
+
+ CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+ if (PciAddress.ExtendedRegister > 0xFF) {
+ //
+ // Check PciExpressBaseAddress
+ //
+ if ((PrivateData->PciExpressBaseAddress == 0) ||
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ UsePciExpressAccess = TRUE;
+ }
+ } else {
+ if (PciAddress.ExtendedRegister != 0) {
+ Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
+ } else {
+ Pci.Bits.Reg = PciAddress.Register;
+ }
+ //
+ // Note: We can also use PciExpress access here, if wanted.
+ //
+ }
+
+ if (!UsePciExpressAccess) {
+ Pci.Bits.Func = PciAddress.Function;
+ Pci.Bits.Dev = PciAddress.Device;
+ Pci.Bits.Bus = PciAddress.Bus;
+ Pci.Bits.Reserved = 0;
+ Pci.Bits.Enable = 1;
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // To read a byte of PCI config space you load 0xcf8 and
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ //
+ PciDataStride = Pci.Bits.Reg & 0x03;
+
+ while (Count) {
+ PciAligned = Pci;
+ PciAligned.Bits.Reg &= 0xfc;
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;
+ EfiAcquireLock(&PrivateData->PciLock);
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+ if (Write) {
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);
+ } else {
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);
+ }
+ EfiReleaseLock(&PrivateData->PciLock);
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+ PciDataStride = (PciDataStride + InStride) % 4;
+ Pci.Bits.Reg += InStride;
+ Count -= 1;
+ }
+ } else {
+ //
+ // Access PCI-Express space by using memory mapped method.
+ //
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+ (PciAddress.Bus << 20) |
+ (PciAddress.Device << 15) |
+ (PciAddress.Function << 12);
+ if (PciAddress.ExtendedRegister != 0) {
+ PciExpressRegAddr += PciAddress.ExtendedRegister;
+ } else {
+ PciExpressRegAddr += PciAddress.Register;
+ }
+ while (Count) {
+ if (Write) {
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ } else {
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ }
+
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+ PciExpressRegAddr += InStride;
+ Count -= 1;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+VOID
+ScanPciBus(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,
+ VOID *Context
+ )
+
+{
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Func;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+
+ //
+ // Loop through all busses
+ //
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+ //
+ // Loop 32 devices per bus
+ //
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {
+ //
+ // Loop through 8 functions per device
+ //
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+ //
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the VendorID from this PCI Device's Confioguration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+
+ //
+ // If VendorId = 0xffff, there does not exist a device at this
+ // location. For each device, if there is any function on it,
+ // there must be 1 function at Function 0. So if Func = 0, there
+ // will be no more functions in the same device, so we can break
+ // loop to deal with the next device.
+ //
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+ break;
+ }
+
+ if (PciHeader.Hdr.VendorId != 0xffff) {
+
+ //
+ // Read the HeaderType to determine if this is a multi-function device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+ //
+ // Call the callback function for the device that was found
+ //
+ Callback(
+ IoDev,
+ MinBus, MaxBus,
+ MinDevice, MaxDevice,
+ MinFunc, MaxFunc,
+ Bus,
+ Device,
+ Func,
+ Context
+ );
+
+ //
+ // If this is not a multi-function device, we can leave the loop
+ // to deal with the next device.
+ //
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static
+VOID
+CheckForRom (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+ PCI_TYPE01 *PciBridgeHeader;
+ UINT32 Register;
+ UINT32 RomBar;
+ UINT32 RomBarSize;
+ EFI_PHYSICAL_ADDRESS RomBuffer;
+ UINT32 MaxRomSize;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
+ PCI_DATA_STRUCTURE Pcir;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
+ BOOLEAN LastImage;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Save the contents of the PCI Configuration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+ if (IS_PCI_BRIDGE(&PciHeader)) {
+
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+ //
+ // See if the PCI-PCI Bridge has its secondary interface enabled.
+ //
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+ //
+ // Disable the Prefetchable Memory Window
+ //
+ Register = 0x00000000;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+ Register = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+ //
+ // Program Memory Window to the PCI Root Bridge Memory Window
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+ //
+ // Enable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Recurse on the Secondary Bus Number
+ //
+ ScanPciBus(
+ IoDev,
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, Context
+ );
+ }
+ } else {
+
+ //
+ // Check if an Option ROM Register is present and save the Option ROM Window Register
+ //
+ RomBar = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+ //
+ // Make sure the size of the ROM is between 0 and 16 MB
+ //
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+ //
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+ //
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+ RomBar = RomBar + 1;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ RomBar = RomBar - 1;
+
+ //
+ // Enable the Memory decode for the PCI Device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Follow the chain of images to determine the size of the Option ROM present
+ // Keep going until the last image is found by looking at the Indicator field
+ // or the size of an image is 0, or the size of all the images is bigger than the
+ // size of the window programmed into the PPB.
+ //
+ RomBarSize = 0;
+ do {
+
+ LastImage = TRUE;
+
+ ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize,
+ sizeof(EfiRomHeader),
+ &EfiRomHeader
+ );
+
+ Pcir.ImageLength = 0;
+
+ if (EfiRomHeader.Signature == 0xaa55) {
+
+ ZeroMem (&Pcir, sizeof(Pcir));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset,
+ sizeof(Pcir),
+ &Pcir
+ );
+
+ if ((Pcir.Indicator & 0x80) == 0x00) {
+ LastImage = FALSE;
+ }
+
+ RomBarSize += Pcir.ImageLength * 512;
+ }
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+ if (RomBarSize > 0) {
+
+ //
+ // Allocate a memory buffer for the Option ROM contents.
+ //
+ Status = gBS->AllocatePages(
+ AllocateAnyPages,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(RomBarSize),
+ &RomBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Copy the contents of the Option ROM to the memory buffer
+ //
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+ &TempPciOptionRomDescriptors
+ );
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {
+ CopyMem(
+ TempPciOptionRomDescriptors,
+ mPciOptionRomTable.PciOptionRomDescriptors,
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+ );
+
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+ }
+
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
+
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
+
+ mPciOptionRomTable.PciOptionRomCount++;
+ }
+ }
+
+ //
+ // Disable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register &= (~0x02);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ }
+ }
+ }
+
+ //
+ // Restore the PCI Configuration Header
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+static
+VOID
+SaveCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+ UINT16 Command;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+ //
+ // Clear the memory enable bit
+ //
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+static
+VOID
+RestoreCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ UINT64 RootWindowBase;
+ UINT64 RootWindowLimit;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
+
+ if (mPciOptionRomTableInstalled == FALSE) {
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+ mPciOptionRomTableInstalled = TRUE;
+ }
+
+ Status = IoDev->Configuration(IoDev, &Descriptors);
+ if (EFI_ERROR (Status) || Descriptors == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MinBus = 0xffff;
+ MaxBus = 0xffff;
+ RootWindowBase = 0;
+ RootWindowLimit = 0;
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ //
+ // Find bus range
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ MinBus = (UINT16)Descriptors->AddrRangeMin;
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;
+ }
+ //
+ // Find memory descriptors that are not prefetchable
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+ //
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+ //
+ if (Descriptors->AddrRangeMax < 0x100000000) {
+ //
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+ //
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+ RootWindowBase = Descriptors->AddrRangeMin;
+ RootWindowLimit = Descriptors->AddrRangeMax;
+ }
+ }
+ }
+ Descriptors ++;
+ }
+
+ //
+ // Make sure a bus range was found
+ //
+ if (MinBus == 0xffff || MaxBus == 0xffff) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure a non-prefetchable memory region was found
+ //
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Round the Base and Limit values to 1 MB boudaries
+ //
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+ //
+ // Make sure that the size of the rounded window is greater than zero
+ //
+ if (RootWindowLimit <= RootWindowBase) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate buffer to save the Command register from all the PCI devices
+ //
+ Context.CommandRegisterBuffer = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+ &Context.CommandRegisterBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+ //
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ SaveCommandRegister, &Context
+ );
+
+ //
+ // Recursively scan all the busses for PCI Option ROMs
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MinBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, &Context
+ );
+
+ //
+ // Restore the Command register in all the PCI devices
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ RestoreCommandRegister, &Context
+ );
+
+ //
+ // Free the buffer used to save all the Command register values
+ //
+ gBS->FreePool(Context.CommandRegisterBuffer);
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c new file mode 100644 index 0000000000..9979d47c4e --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c @@ -0,0 +1,459 @@ +/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "pci22.h"
+#include "SalProc.h"
+
+#include EFI_GUID_DEFINITION (SalSystemTable)
+
+//
+// Might be good to put this in an include file, but people may start
+// using it! They should always access the EFI abstraction that is
+// contained in this file. Just a little information hiding.
+//
+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
+
+//
+// Macro's with casts make this much easier to use and read.
+//
+#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))
+
+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
+ ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
+
+//
+// Local variables for performing SAL Proc calls
+//
+static PLABEL mSalProcPlabel;
+static CALL_SAL_PROC mGlobalSalProc;
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ *Buffer.ui8 = PORT_TO_MEM8(Address);
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = PORT_TO_MEM16(Address);
+ *Buffer.ui8 = (UINT8)(Data16 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
+ } else {
+ *Buffer.ui16 = PORT_TO_MEM16(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = PORT_TO_MEM32(Address);
+ *Buffer.ui8 = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = PORT_TO_MEM32(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ PORT_TO_MEM8(Address) = *Buffer.ui8;
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = *Buffer.ui8;
+ Data16 = Data16 | (*(Buffer.ui8+1) << 8);
+ PORT_TO_MEM16(Address) = Data16;
+ } else {
+ PORT_TO_MEM16(Address) = *Buffer.ui16;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = *Buffer.ui8;
+ Data32 = Data32 | (*(Buffer.ui8+1) << 8);
+ Data32 = Data32 | (*(Buffer.ui8+2) << 16);
+ Data32 = Data32 | (*(Buffer.ui8+3) << 24);
+ PORT_TO_MEM32(Address) = Data32;
+ } else {
+ PORT_TO_MEM32(Address) = *Buffer.ui32;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Map from the SAL System Table.
+
+--*/
+{
+ SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;
+ SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;
+ EFI_STATUS Status;
+
+ //
+ // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
+ //
+ *MemoryPortMapping = 0x8000000000000000;
+
+ Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // BugBug: Add code to test checksum on the Sal System Table
+ //
+ if (SalSystemTable->Entry0.Type != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
+ mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;
+ mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
+
+ //
+ // The SalSystemTable pointer includes the Type 0 entry.
+ // The SalMemDesc is Type 1 so it comes next.
+ //
+ SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
+ while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
+ if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
+ *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
+ *IoPortMapping |= 0x8000000000000000;
+ return EFI_SUCCESS;
+ }
+ SalMemDesc++;
+ }
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT UINT8 *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ UINTN InStride;
+ UINTN OutStride;
+ UINT64 Address;
+ DEFIO_PCI_ADDR *Defio;
+ PTR Buffer;
+ UINT32 Data32;
+ UINT16 Data16;
+ rArg Return;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( UserAddress & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Defio = (DEFIO_PCI_ADDR *)&UserAddress;
+
+ if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = EFI_PCI_ADDRESS_IA64(
+ This->SegmentNumber,
+ Defio->Bus,
+ Defio->Device,
+ Defio->Function,
+ Defio->Register
+ );
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // SalProc takes care of reading the proper register depending on stride
+ //
+
+ EfiAcquireLock(&PrivateData->PciLock);
+
+ while (Count) {
+
+ if(Write) {
+
+ if (Buffer.ui & 0x3) {
+ Data32 = (*(Buffer.ui8+0) << 0);
+ Data32 |= (*(Buffer.ui8+1) << 8);
+ Data32 |= (*(Buffer.ui8+2) << 16);
+ Data32 |= (*(Buffer.ui8+3) << 24);
+ } else {
+ Data32 = *Buffer.ui32;
+ }
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
+ Address, 1 << Width, Data32, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
+ Address, 1 << Width, 0, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *Buffer.ui8 = (UINT8)Return.p1;
+ break;
+ case EfiPciWidthUint16:
+ if (Buffer.ui & 0x1) {
+ Data16 = (UINT16)Return.p1;
+ *(Buffer.ui8 + 0) = Data16 & 0xff;
+ *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
+ } else {
+ *Buffer.ui16 = (UINT16)Return.p1;
+ }
+ break;
+ case EfiPciWidthUint32:
+ if (Buffer.ui & 0x3) {
+ Data32 = (UINT32)Return.p1;
+ *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = (UINT32)Return.p1;
+ }
+ break;
+ }
+ }
+
+ Address += InStride;
+ Buffer.buf += OutStride;
+ Count -= 1;
+ }
+
+ EfiReleaseLock(&PrivateData->PciLock);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c new file mode 100644 index 0000000000..ff53bb5c78 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c @@ -0,0 +1,1018 @@ +/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridge.c
+
+Abstract:
+
+ EFI PC-AT PCI Root Bridge Controller
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_CPU_IO_PROTOCOL *gCpuIo;
+
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initializes the PCI Root Bridge Controller
+
+Arguments:
+ ImageHandle -
+ SystemTable -
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN PciSegmentIndex;
+ UINTN PciRootBridgeIndex;
+ UINTN PrimaryBusIndex;
+ UINTN NumberOfPciRootBridges;
+ UINTN NumberOfPciDevices;
+ UINTN Device;
+ UINTN Function;
+ UINT16 VendorId;
+ PCI_TYPE01 PciConfigurationHeader;
+ UINT64 Address;
+ UINT64 Value;
+ UINT64 Base;
+ UINT64 Limit;
+
+ //
+ // Initialize gCpuIo now since the chipset init code requires it.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &gCpuIo);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize variables required to search all PCI segments for PCI devices
+ //
+ PciSegmentIndex = 0;
+ PciRootBridgeIndex = 0;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+
+ while (PciSegmentIndex <= PCI_MAX_SEGMENT) {
+
+ PrivateData = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
+ &PrivateData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));
+
+ //
+ // Initialize the signature of the private data structure
+ //
+ PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->Handle = NULL;
+ PrivateData->DevicePath = NULL;
+ InitializeListHead (&PrivateData->MapInfo);
+
+ //
+ // Initialize the PCI root bridge number and the bus range for that root bridge
+ //
+ PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
+ PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex;
+ PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex;
+
+ PrivateData->IoBase = 0xffffffff;
+ PrivateData->MemBase = 0xffffffff;
+ PrivateData->Mem32Base = 0xffffffffffffffff;
+ PrivateData->Pmem32Base = 0xffffffffffffffff;
+ PrivateData->Mem64Base = 0xffffffffffffffff;
+ PrivateData->Pmem64Base = 0xffffffffffffffff;
+
+ //
+ // The default mechanism for performing PCI Configuration cycles is to
+ // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.
+ // IPF uses SAL calls to perform PCI COnfiguration cycles
+ //
+ PrivateData->PciAddress = 0xCF8;
+ PrivateData->PciData = 0xCFC;
+
+ //
+ // Get the physical I/O base for performing PCI I/O cycles
+ // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
+ // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
+ //
+ Status = PcatRootBridgeIoGetIoPortMapping (
+ &PrivateData->PhysicalIoBase,
+ &PrivateData->PhysicalMemoryBase
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Get PCI Express Base Address
+ //
+ PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
+ if (PrivateData->PciExpressBaseAddress != 0) {
+ DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
+ }
+
+ //
+ // Create a lock for performing PCI Configuration cycles
+ //
+ EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
+
+ //
+ // Initialize the attributes for this PCI root bridge
+ //
+ PrivateData->Attributes = 0;
+
+ //
+ // Build the EFI Device Path Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Scan all the PCI devices on the primary bus of the PCI root bridge
+ //
+ for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+ for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
+
+ //
+ // Compute the PCI configuration address of the PCI device to probe
+ //
+ Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);
+
+ //
+ // Read the Vendor ID from the PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint16,
+ Address,
+ sizeof (VendorId),
+ &VendorId
+ );
+ if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
+ //
+ // If the PCI Configuration Read fails, or a PCI device does not exist, then
+ // skip this entire PCI device
+ //
+ break;
+ }
+ if (VendorId == 0xffff) {
+ //
+ // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
+ //
+ continue;
+ }
+
+ //
+ // Read the entire PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PciConfigurationHeader) / sizeof (UINT32),
+ &PciConfigurationHeader
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
+ //
+ break;
+ }
+
+ //
+ // Increment the number of PCI device found on the primary bus of the PCI root bridge
+ //
+ NumberOfPciDevices++;
+
+ //
+ // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
+ //
+ if (PciConfigurationHeader.Hdr.Command & 0x20) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ //
+ // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
+ //
+ if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
+ //
+ // Get the Bus range that the PPB is decoding
+ //
+ if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
+ //
+ // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
+ // current subordinate bus number, then update the PCI root bridge's subordinate bus number
+ //
+ PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
+ }
+
+ //
+ // Get the I/O range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
+ if (Value == 0x01) {
+ Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
+ Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
+ }
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = Limit;
+ }
+ }
+
+ //
+ // Get the Memory range that the PPB is decoding
+ //
+ Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+
+ //
+ // Get the Prefetchable Memory range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
+ if (Value == 0x01) {
+ Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
+ Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
+ }
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (Value == 0x00) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ }
+ if (Value == 0x01) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ }
+ }
+
+ //
+ // Look at the PPB Configuration for legacy decoding attributes
+ //
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+ }
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ } else {
+ //
+ // Parse the BARs of the PCI device to determine what I/O Ranges,
+ // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
+ //
+ if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
+ Status = PcatPciRootBridgeParseBars (
+ PrivateData,
+ PciConfigurationHeader.Hdr.Command,
+ PrimaryBusIndex,
+ Device,
+ Function
+ );
+ }
+
+ //
+ // See if the PCI device is an IDE controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ }
+
+ //
+ // See if the PCI device is a legacy VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI device is a standard VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI Device is a PCI - ISA or PCI - EISA
+ // or ISA_POSITIVIE_DECODE Bridge device
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
+ if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+ }
+ }
+
+ //
+ // If this device is not a multi function device, then skip the rest of this PCI device
+ //
+ if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
+ break;
+ }
+ }
+ }
+
+ //
+ // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
+ // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
+ // bus number + 1.
+ //
+ PrimaryBusIndex = PrivateData->SubordinateBus + 1;
+
+ //
+ // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
+ // exists.
+ //
+ if (NumberOfPciDevices > 0) {
+
+ //
+ // Adjust the I/O range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & 0x7f) {
+ PrivateData->IoBase = 0;
+ if (PrivateData->IoLimit < 0xffff) {
+ PrivateData->IoLimit = 0xffff;
+ }
+ }
+
+ //
+ // Adjust the Memory range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+
+ //
+ // Build ACPI descriptors for the resources on the PCI Root Bridge
+ //
+ Status = ConstructConfiguration(PrivateData);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create the handle for this PCI Root Bridge
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Contruct DeviceIoProtocol
+ //
+ Status = DeviceIoConstructor (
+ PrivateData->Handle,
+ &PrivateData->Io,
+ PrivateData->DevicePath,
+ (UINT16)PrivateData->PrimaryBus,
+ (UINT16)PrivateData->SubordinateBus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
+ //
+ Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
+
+ //
+ // Increment the index for the next PCI Root Bridge
+ //
+ PciRootBridgeIndex++;
+
+ } else {
+
+ //
+ // If no PCI Root Bridges were found on the current PCI segment, then exit
+ //
+ if (NumberOfPciRootBridges == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ }
+
+ //
+ // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
+ // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
+ // Otherwise, the search is continued on the next PCI Root Bridge
+ //
+ if (PrimaryBusIndex > PCI_MAX_BUS) {
+ PciSegmentIndex++;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+ } else {
+ NumberOfPciRootBridges++;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+Done:
+ //
+ // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
+ //
+ if (PrivateData) {
+ if (PrivateData->DevicePath) {
+ gBS->FreePool(PrivateData->DevicePath);
+ }
+ gBS->FreePool (PrivateData);
+ }
+
+ //
+ // If no PCI Root Bridges were discovered, then return the error condition from scanning the
+ // first PCI Root Bridge
+ //
+ if (PciRootBridgeIndex == 0) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConstructConfiguration(
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+
+{
+ EFI_STATUS Status;
+ UINT8 NumConfig;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+ EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;
+
+ NumConfig = 0;
+ PrivateData->Configuration = NULL;
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ NumConfig++;
+ }
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ NumConfig++;
+ }
+
+ if ( NumConfig == 0 ) {
+
+ //
+ // If there is no resource request
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration++;
+
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+ }
+
+ //
+ // If there is at least one type of resource request,
+ // allocate a acpi resource node
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ Configuration->SpecificFlag = 0;
+ Configuration->AddrRangeMin = PrivateData->PrimaryBus;
+ Configuration->AddrRangeMax = PrivateData->SubordinateBus;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+ //
+ // Deal with io aperture
+ //
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ Configuration->SpecificFlag = 1; //non ISA range
+ Configuration->AddrRangeMin = PrivateData->IoBase;
+ Configuration->AddrRangeMax = PrivateData->IoLimit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem32 aperture
+ //
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //Nonprefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem32Base;
+ Configuration->AddrRangeMax = PrivateData->Mem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem32 aperture
+ //
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x6; //prefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem32Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem64 aperture
+ //
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //nonprefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem64Base;
+ Configuration->AddrRangeMax = PrivateData->Mem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem64 aperture
+ //
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x06; //prefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem64Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // put the checksum
+ //
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeBarExisted (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT64 Address,
+ OUT UINT32 *OriginalValue,
+ OUT UINT32 *Value
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 AllOnes;
+ EFI_TPL OldTpl;
+
+ //
+ // Preserve the original value
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ AllOnes = 0xffffffff;
+
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ Value
+ );
+
+ //
+ //Write back the original value
+ //
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if ( *Value == 0 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT16 Command,
+ IN UINTN Bus,
+ IN UINTN Device,
+ IN UINTN Function
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Address;
+ UINT32 OriginalValue;
+ UINT32 Value;
+ UINT32 OriginalUpperValue;
+ UINT32 UpperValue;
+ UINT64 Mask;
+ UINTN Offset;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Limit;
+
+ for (Offset = 0x10; Offset < 0x28; Offset += 4) {
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalValue,
+ &Value
+ );
+
+ if (!EFI_ERROR (Status )) {
+ if ( Value & 0x01 ) {
+ if (Command & 0x0001) {
+ //
+ //Device I/Os
+ //
+ Mask = 0xfffffffc;
+ Base = OriginalValue & Mask;
+ Length = ((~(Value & Mask)) & Mask) + 0x04;
+ if (!(Value & 0xFFFF0000)){
+ Length &= 0x0000FFFF;
+ }
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = (UINT32)Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = (UINT32)Limit;
+ }
+ }
+ }
+
+ } else {
+
+ if (Command & 0x0002) {
+
+ Mask = 0xfffffff0;
+ Base = OriginalValue & Mask;
+ Length = Value & Mask;
+
+ if ((Value & 0x07) != 0x04) {
+ Length = ((~Length) + 1) & 0xffffffff;
+ } else {
+ Offset += 4;
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalUpperValue,
+ &UpperValue
+ );
+
+ Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);
+ Length = Length | LShiftU64((UINT64)UpperValue,32);
+ Length = (~Length) + 1;
+ }
+
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+
+ switch (Value &0x07) {
+ case 0x00: ////memory space; anywhere in 32 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+ break;
+ case 0x04: //memory space; anywhere in 64 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem64Base > Base) {
+ PrivateData->Mem64Base = Base;
+ }
+ if (PrivateData->Mem64Limit < Limit) {
+ PrivateData->Mem64Limit = Limit;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ )
+/*++
+
+Routine Description:
+ This routine is to get PciExpress Base Address for this RootBridge
+
+Arguments:
+ HostBridgeNumber - The number of HostBridge
+ RootBridgeNumber - The number of RootBridge
+
+Returns:
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
+
+--*/
+{
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
+ UINTN BufferSize;
+ UINT32 Index;
+ UINT32 Number;
+ VOID *HobList;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ //
+ // Get Hob List from configuration table
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ //
+ // Get PciExpressAddressInfo Hob
+ //
+ PciExpressBaseAddressInfo = NULL;
+ BufferSize = 0;
+ GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);
+ if (GuidHob.Raw != NULL) {
+ PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
+ BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
+ } else {
+ return 0;
+ }
+
+ //
+ // Search the PciExpress Base Address in the Hob for current RootBridge
+ //
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
+ for (Index = 0; Index < Number; Index++) {
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
+ }
+ }
+
+ //
+ // Do not find the PciExpress Base Address in the Hob
+ //
+ return 0;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h new file mode 100644 index 0000000000..50bd9b43b2 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h @@ -0,0 +1,215 @@ +/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridge.h
+
+Abstract:
+
+ The driver for the host to pci bridge (root bridge).
+
+--*/
+
+#ifndef _PCAT_PCI_ROOT_BRIDGE_H_
+#define _PCAT_PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DeviceIo.h>
+#include <Protocol/CpuIo.h>
+
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+
+#include <Guid/PciOptionRomTable.h>
+#include <Guid/HobList.h>
+#include <Guid/PciExpressBaseAddress.h>
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+//
+// Driver Instance Data Prototypes
+//
+#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE EFI_SIGNATURE_32('p', 'c', 'r', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_CPU_IO_PROTOCOL *CpuIo;
+
+ UINT32 RootBridgeNumber;
+ UINT32 PrimaryBus;
+ UINT32 SubordinateBus;
+
+ UINT64 MemBase; // Offsets host to bus memory addr.
+ UINT64 MemLimit; // Max allowable memory access
+
+ UINT64 IoBase; // Offsets host to bus io addr.
+ UINT64 IoLimit; // Max allowable io access
+
+ UINT64 PciAddress;
+ UINT64 PciData;
+
+ UINT64 PhysicalMemoryBase;
+ UINT64 PhysicalIoBase;
+
+ EFI_LOCK PciLock;
+
+ UINT64 Attributes;
+
+ UINT64 Mem32Base;
+ UINT64 Mem32Limit;
+ UINT64 Pmem32Base;
+ UINT64 Pmem32Limit;
+ UINT64 Mem64Base;
+ UINT64 Mem64Limit;
+ UINT64 Pmem64Base;
+ UINT64 Pmem64Limit;
+
+ UINT64 PciExpressBaseAddress;
+
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+
+ LIST_ENTRY MapInfo;
+} PCAT_PCI_ROOT_BRIDGE_INSTANCE;
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+ CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define VOLATILE volatile
+//
+// Private data types
+//
+typedef union {
+ UINT8 VOLATILE *buf;
+ UINT8 VOLATILE *ui8;
+ UINT16 VOLATILE *ui16;
+ UINT32 VOLATILE *ui32;
+ UINT64 VOLATILE *ui64;
+ UINTN VOLATILE ui;
+} PTR;
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+ LIST_ENTRY Link;
+ MAP_INFO * Map;
+} MAP_INFO_INSTANCE;
+
+typedef
+VOID
+(*EFI_PCI_BUS_SCAN_CALLBACK) (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *Context
+ );
+
+typedef struct {
+ UINT16 *CommandRegisterBuffer;
+ UINT32 PpbMemoryWindow;
+} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;
+
+//
+// Driver Protocol Constructor Prototypes
+//
+EFI_STATUS
+ConstructConfiguration(
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
+ );
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT16 Command,
+ IN UINTN Bus,
+ IN UINTN Device,
+ IN UINTN Function
+ );
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ );
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
+ IN UINTN RootBridgeNumber,
+ IN BOOLEAN IsPciExpress
+ );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN UINTN SegmentNumber
+ );
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ );
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ );
+
+//
+// Driver entry point prototype
+//
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+extern EFI_CPU_IO_PROTOCOL *gCpuIo;
+
+#endif
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c new file mode 100644 index 0000000000..ab1b5d8c56 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c @@ -0,0 +1,87 @@ +/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeDevicePath.c
+
+Abstract:
+
+ EFI PCAT PCI Root Bridge Device Path Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Static device path declarations for this driver.
+//
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0A03),
+ 0
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
+ IN UINTN RootBridgeNumber,
+ IN BOOLEAN IsPciExpress
+ )
+/*++
+
+Routine Description:
+
+ Construct the device path protocol
+
+Arguments:
+
+ Protocol - protocol to initialize
+
+Returns:
+
+ None
+
+--*/
+{
+ ACPI_HID_DEVICE_PATH *AcpiDevicePath;
+
+ *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));
+
+ AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);
+
+ AcpiDevicePath->UID = (UINT32)RootBridgeNumber;
+
+ if (IsPciExpress) {
+ AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c new file mode 100644 index 0000000000..abb6acbd96 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c @@ -0,0 +1,1054 @@ +/*++
+
+Copyright (c) 2005 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Protocol Member Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+STATIC
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN UINTN SegmentNumber
+ )
+/*++
+
+Routine Description:
+
+ Contruct the Pci Root Bridge Io protocol
+
+Arguments:
+
+ Protocol - protocol to initialize
+
+Returns:
+
+ None
+
+--*/
+{
+ Protocol->ParentHandle = NULL;
+
+ Protocol->PollMem = PcatRootBridgeIoPollMem;
+ Protocol->PollIo = PcatRootBridgeIoPollIo;
+
+ Protocol->Mem.Read = PcatRootBridgeIoMemRead;
+ Protocol->Mem.Write = PcatRootBridgeIoMemWrite;
+
+ Protocol->Io.Read = PcatRootBridgeIoIoRead;
+ Protocol->Io.Write = PcatRootBridgeIoIoWrite;
+
+ Protocol->CopyMem = PcatRootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = PcatRootBridgeIoPciRead;
+ Protocol->Pci.Write = PcatRootBridgeIoPciWrite;
+
+ Protocol->Map = PcatRootBridgeIoMap;
+ Protocol->Unmap = PcatRootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer;
+
+ Protocol->Flush = PcatRootBridgeIoFlush;
+
+ Protocol->GetAttributes = PcatRootBridgeIoGetAttributes;
+ Protocol->SetAttributes = PcatRootBridgeIoSetAttributes;
+
+ Protocol->Configuration = PcatRootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = (UINT32)SegmentNumber;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINTN Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ if ( Delay != 0 ) {
+
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+ if ( Remainder !=0 ) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while ( NumberOfTicks ) {
+
+ gBS->Stall (10);
+
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINTN Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay != 0) {
+
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+ if ( Remainder !=0 ) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while ( NumberOfTicks ) {
+
+ gBS->Stall(10);
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+BOOLEAN
+PcatRootBridgeMemAddressValid (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
+ return TRUE;
+ }
+ if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address += PrivateData->PhysicalMemoryBase;
+
+ In.buf = Buffer;
+ Out.buf = (VOID *)(UINTN) Address;
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+ }
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address += PrivateData->PhysicalMemoryBase;
+
+ In.buf = (VOID *)(UINTN) Address;
+ Out.buf = Buffer;
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)1 << Width;
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count-1) * Stride;
+ DestAddress = DestAddress + (Count-1) * Stride;
+ }
+
+ for (Index = 0;Index < Count;Index++) {
+ Status = PcatRootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = PcatRootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ MAP_INFO *MapInfo;
+ MAP_INFO_INSTANCE *MapInstance;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if ( HostAddress == NULL || NumberOfBytes == NULL ||
+ DeviceAddress == NULL || Mapping == NULL ) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ //
+ // Initialize the return values to their defaults
+ //
+ *Mapping = NULL;
+
+ //
+ // Make sure that Operation is valid
+ //
+ if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Most PCAT like chipsets can not handle performing DMA above 4GB.
+ // If any part of the DMA transfer being mapped is above 4GB, then
+ // map the DMA transfer to a buffer below 4GB.
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+ if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {
+
+ //
+ // Common Buffer operations can not be remapped. If the common buffer
+ // if above 4GB, then it is not possible to generate a mapping, so return
+ // an error.
+ //
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ // called later.
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(MAP_INFO),
+ &MapInfo
+ );
+ if (EFI_ERROR (Status)) {
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // Return a pointer to the MAP_INFO structure in Mapping
+ //
+ *Mapping = MapInfo;
+
+ //
+ // Initialize the MAP_INFO structure
+ //
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
+ MapInfo->HostAddress = PhysicalAddress;
+ MapInfo->MappedHostAddress = 0x00000000ffffffff;
+
+ //
+ // Allocate a buffer below 4GB to map the transfer to.
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ MapInfo->NumberOfPages,
+ &MapInfo->MappedHostAddress
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // If this is a read operation from the Bus Master's point of view,
+ // then copy the contents of the real buffer into the mapped buffer
+ // so the Bus Master can read the contents of the real buffer.
+ //
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+
+ Status =gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(MAP_INFO_INSTANCE),
+ &MapInstance
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ MapInstance->Map=MapInfo;
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+ InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
+
+ //
+ // The DeviceAddress is the address of the maped buffer below 4GB
+ //
+ *DeviceAddress = MapInfo->MappedHostAddress;
+ } else {
+ //
+ // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+ //
+ *DeviceAddress = PhysicalAddress;
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+
+{
+ MAP_INFO *MapInfo;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ LIST_ENTRY *Link;
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+ //
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ //
+ if (Mapping != NULL) {
+ //
+ // Get the MAP_INFO structure from Mapping
+ //
+ MapInfo = (MAP_INFO *)Mapping;
+
+ for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
+ if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
+ break;
+ }
+
+ if (Link == &PrivateData->MapInfo) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList(Link);
+ ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
+ gBS->FreePool((MAP_INFO_INSTANCE*)Link);
+
+ //
+ // If this is a write operation from the Bus Master's point of view,
+ // then copy the contents of the mapped buffer into the real buffer
+ // so the processor can read the contents of the real buffer.
+ //
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+ //
+ // Free the mapped buffer and the MAP_INFO structure.
+ //
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+ gBS->FreePool (Mapping);
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // Validate Attributes
+ //
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for invalid inputs
+ //
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ //
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Limit allocations to memory below 4GB
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
+
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+
+{
+
+ if( HostAddress == NULL ){
+ return EFI_INVALID_PARAMETER;
+ }
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+
+{
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported, OPTIONAL
+ OUT UINT64 *Attributes
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Supported is an OPTIONAL parameter. See if it is NULL
+ //
+ if (Supported) {
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ *Supported = PrivateData->Attributes;
+ }
+
+ //
+ // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
+ //
+
+ if (Attributes) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ if (Attributes & (~PrivateData->Attributes)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ *Resources = PrivateData->Configuration;
+
+ return EFI_SUCCESS;
+}
+
+//
+// Internal function
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+/*++
+
+Routine Description:
+
+ Private service to provide the memory read/write
+
+Arguments:
+
+ Width of the Memory Access
+ Count of the number of accesses to perform
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS - Successful transaction
+ EFI_INVALID_PARAMETER - Unsupported width and address combination
+
+--*/
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+
+ Width = Width & 0x03;
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui8 = *Out.ui8;
+ MemoryFence();
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui16 = *Out.ui16;
+ MemoryFence();
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui32 = *Out.ui32;
+ MemoryFence();
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf b/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf new file mode 100644 index 0000000000..fa0596db13 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf @@ -0,0 +1,70 @@ +#/*++
+#
+# Copyright (c) 2005 - 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# Abstract:
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcatPciRootBridge
+ FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializePcatPciRootBridge
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DuetPkg/DuetPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ DebugLib
+ BaseMemoryLib
+ DevicePathLib
+ HobLib
+
+[Sources.common]
+ PcatPciRootBridge.h
+ PcatPciRootBridge.c
+ PcatPciRootBridgeDevicePath.c
+ PcatPciRootBridgeIo.c
+ DeviceIo.h
+ DeviceIo.c
+
+[Sources.ia32]
+ ia32\PcatIo.c
+
+[Sources.x64]
+ x64\PcatIo.c
+
+[Sources.ipf]
+ Ipf\PcatIo.c
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDeviceIoProtocolGuid
+ gEfiPciExpressBaseAddressGuid
+ gEfiCpuIoProtocolGuid
+
+[Guids]
+ gEfiPciOptionRomTableGuid
\ No newline at end of file diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c new file mode 100644 index 0000000000..830dcbb8c7 --- /dev/null +++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c @@ -0,0 +1,732 @@ +/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Read (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Write (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Mapping. For IA-32 it is always 0.
+
+--*/
+{
+ *IoPortMapping = 0;
+ *MemoryPortMapping = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCI_CONFIG_ACCESS_CF8 Pci;
+ PCI_CONFIG_ACCESS_CF8 PciAligned;
+ UINT32 InStride;
+ UINT32 OutStride;
+ UINTN PciData;
+ UINTN PciDataStride;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT64 PciExpressRegAddr;
+ BOOLEAN UsePciExpressAccess;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) >= EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ UsePciExpressAccess = FALSE;
+
+ EfiCopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+ if (PciAddress.ExtendedRegister > 0xFF) {
+ //
+ // Check PciExpressBaseAddress
+ //
+ if ((PrivateData->PciExpressBaseAddress == 0) ||
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ UsePciExpressAccess = TRUE;
+ }
+ } else {
+ if (PciAddress.ExtendedRegister != 0) {
+ Pci.Reg = PciAddress.ExtendedRegister & 0xFF;
+ } else {
+ Pci.Reg = PciAddress.Register;
+ }
+ //
+ // Note: We can also use PciExpress access here, if wanted.
+ //
+ }
+
+ if (!UsePciExpressAccess) {
+ Pci.Func = PciAddress.Function;
+ Pci.Dev = PciAddress.Device;
+ Pci.Bus = PciAddress.Bus;
+ Pci.Reserved = 0;
+ Pci.Enable = 1;
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // To read a byte of PCI config space you load 0xcf8 and
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ //
+ PciDataStride = Pci.Reg & 0x03;
+
+ while (Count) {
+ PciAligned = Pci;
+ PciAligned.Reg &= 0xfc;
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;
+ EfiAcquireLock(&PrivateData->PciLock);
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+ if (Write) {
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);
+ } else {
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);
+ }
+ EfiReleaseLock(&PrivateData->PciLock);
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+ PciDataStride = (PciDataStride + InStride) % 4;
+ Pci.Reg += InStride;
+ Count -= 1;
+ }
+ } else {
+ //
+ // Access PCI-Express space by using memory mapped method.
+ //
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+ (PciAddress.Bus << 20) |
+ (PciAddress.Device << 15) |
+ (PciAddress.Function << 12);
+ if (PciAddress.ExtendedRegister != 0) {
+ PciExpressRegAddr += PciAddress.ExtendedRegister;
+ } else {
+ PciExpressRegAddr += PciAddress.Register;
+ }
+ while (Count) {
+ if (Write) {
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ } else {
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ }
+
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+ PciExpressRegAddr += InStride;
+ Count -= 1;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+VOID
+ScanPciBus(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,
+ VOID *Context
+ )
+
+{
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Func;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+
+ //
+ // Loop through all busses
+ //
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+ //
+ // Loop 32 devices per bus
+ //
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {
+ //
+ // Loop through 8 functions per device
+ //
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+ //
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the VendorID from this PCI Device's Confioguration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+
+ //
+ // If VendorId = 0xffff, there does not exist a device at this
+ // location. For each device, if there is any function on it,
+ // there must be 1 function at Function 0. So if Func = 0, there
+ // will be no more functions in the same device, so we can break
+ // loop to deal with the next device.
+ //
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+ break;
+ }
+
+ if (PciHeader.Hdr.VendorId != 0xffff) {
+
+ //
+ // Read the HeaderType to determine if this is a multi-function device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+ //
+ // Call the callback function for the device that was found
+ //
+ Callback(
+ IoDev,
+ MinBus, MaxBus,
+ MinDevice, MaxDevice,
+ MinFunc, MaxFunc,
+ Bus,
+ Device,
+ Func,
+ Context
+ );
+
+ //
+ // If this is not a multi-function device, we can leave the loop
+ // to deal with the next device.
+ //
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static
+VOID
+CheckForRom (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+ PCI_TYPE01 *PciBridgeHeader;
+ UINT32 Register;
+ UINT32 RomBar;
+ UINT32 RomBarSize;
+ EFI_PHYSICAL_ADDRESS RomBuffer;
+ UINT32 MaxRomSize;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
+ PCI_DATA_STRUCTURE Pcir;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
+ BOOLEAN LastImage;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Save the contents of the PCI Configuration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+ if (IS_PCI_BRIDGE(&PciHeader)) {
+
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+ //
+ // See if the PCI-PCI Bridge has its secondary interface enabled.
+ //
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+ //
+ // Disable the Prefetchable Memory Window
+ //
+ Register = 0x00000000;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+ Register = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+ //
+ // Program Memory Window to the PCI Root Bridge Memory Window
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+ //
+ // Enable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Recurse on the Secondary Bus Number
+ //
+ ScanPciBus(
+ IoDev,
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, Context
+ );
+ }
+ } else {
+
+ //
+ // Check if an Option ROM Register is present and save the Option ROM Window Register
+ //
+ RomBar = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+ //
+ // Make sure the size of the ROM is between 0 and 16 MB
+ //
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+ //
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+ //
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+ RomBar = RomBar + 1;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ RomBar = RomBar - 1;
+
+ //
+ // Enable the Memory decode for the PCI Device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Follow the chain of images to determine the size of the Option ROM present
+ // Keep going until the last image is found by looking at the Indicator field
+ // or the size of an image is 0, or the size of all the images is bigger than the
+ // size of the window programmed into the PPB.
+ //
+ RomBarSize = 0;
+ do {
+
+ LastImage = TRUE;
+
+ EfiZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize,
+ sizeof(EfiRomHeader),
+ &EfiRomHeader
+ );
+
+ Pcir.ImageLength = 0;
+
+ if (EfiRomHeader.Signature == 0xaa55) {
+
+ EfiZeroMem (&Pcir, sizeof(Pcir));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset,
+ sizeof(Pcir),
+ &Pcir
+ );
+
+ if ((Pcir.Indicator & 0x80) == 0x00) {
+ LastImage = FALSE;
+ }
+
+ RomBarSize += Pcir.ImageLength * 512;
+ }
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+ if (RomBarSize > 0) {
+
+ //
+ // Allocate a memory buffer for the Option ROM contents.
+ //
+ Status = gBS->AllocatePages(
+ AllocateAnyPages,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(RomBarSize),
+ &RomBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Copy the contents of the Option ROM to the memory buffer
+ //
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+ &TempPciOptionRomDescriptors
+ );
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {
+ EfiCopyMem(
+ TempPciOptionRomDescriptors,
+ mPciOptionRomTable.PciOptionRomDescriptors,
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+ );
+
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+ }
+
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
+
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
+
+ mPciOptionRomTable.PciOptionRomCount++;
+ }
+ }
+
+ //
+ // Disable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register &= (~0x02);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ }
+ }
+ }
+
+ //
+ // Restore the PCI Configuration Header
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+static
+VOID
+SaveCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+ UINT16 Command;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+ //
+ // Clear the memory enable bit
+ //
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+static
+VOID
+RestoreCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ UINT64 RootWindowBase;
+ UINT64 RootWindowLimit;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
+
+ if (mPciOptionRomTableInstalled == FALSE) {
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+ mPciOptionRomTableInstalled = TRUE;
+ }
+
+ Status = IoDev->Configuration(IoDev, &Descriptors);
+ if (EFI_ERROR (Status) || Descriptors == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MinBus = 0xffff;
+ MaxBus = 0xffff;
+ RootWindowBase = 0;
+ RootWindowLimit = 0;
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ //
+ // Find bus range
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ MinBus = (UINT16)Descriptors->AddrRangeMin;
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;
+ }
+ //
+ // Find memory descriptors that are not prefetchable
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+ //
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+ //
+ if (Descriptors->AddrRangeMax < 0x100000000) {
+ //
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+ //
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+ RootWindowBase = Descriptors->AddrRangeMin;
+ RootWindowLimit = Descriptors->AddrRangeMax;
+ }
+ }
+ }
+ Descriptors ++;
+ }
+
+ //
+ // Make sure a bus range was found
+ //
+ if (MinBus == 0xffff || MaxBus == 0xffff) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure a non-prefetchable memory region was found
+ //
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Round the Base and Limit values to 1 MB boudaries
+ //
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+ //
+ // Make sure that the size of the rounded window is greater than zero
+ //
+ if (RootWindowLimit <= RootWindowBase) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate buffer to save the Command register from all the PCI devices
+ //
+ Context.CommandRegisterBuffer = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+ &Context.CommandRegisterBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+ //
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ SaveCommandRegister, &Context
+ );
+
+ //
+ // Recursively scan all the busses for PCI Option ROMs
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MinBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, &Context
+ );
+
+ //
+ // Restore the Command register in all the PCI devices
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ RestoreCommandRegister, &Context
+ );
+
+ //
+ // Free the buffer used to save all the Command register values
+ //
+ gBS->FreePool(Context.CommandRegisterBuffer);
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.c b/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.c new file mode 100644 index 0000000000..bf00b02146 --- /dev/null +++ b/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.c @@ -0,0 +1,146 @@ +/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ RtPlatformStatusCode.c
+
+Abstract:
+
+ Contains NT32 specific implementations required to use status codes.
+
+--*/
+
+//
+// Statements that include other files.
+//
+#include "Tiano.h"
+#include "EfiCommonLib.h"
+#include "EfiRuntimeLib.h"
+#include "EfiStatusCode.h"
+#include "EfiHobLib.h"
+#include "RtMemoryStatusCodeLib.h"
+#include "BsDataHubStatusCodeLib.h"
+
+//
+// Consumed protocols
+//
+#include EFI_ARCH_PROTOCOL_CONSUMER (StatusCode)
+
+//
+// GUID definitions
+//
+#include EFI_GUID_DEFINITION (Hob)
+
+//
+// Globals only work at BootService Time. NOT at Runtime!
+//
+EFI_REPORT_STATUS_CODE mPeiReportStatusCode;
+
+//
+// Function implementations
+//
+EFI_RUNTIMESERVICE
+EFI_STATUS
+EFIAPI
+RtPlatformReportStatusCode (
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID * CallerId,
+ IN EFI_STATUS_CODE_DATA * Data OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Call all status code listeners in the MonoStatusCode.
+
+Arguments:
+
+ Same as ReportStatusCode service
+
+Returns:
+
+ EFI_SUCCESS Always returns success.
+
+--*/
+{
+ RtMemoryReportStatusCode (CodeType, Value, Instance, CallerId, Data);
+ if (EfiAtRuntime ()) {
+ //
+ // For now all we do is post code at runtime
+ //
+ return EFI_SUCCESS;
+ }
+
+ BsDataHubReportStatusCode (CodeType, Value, Instance, CallerId, Data);
+
+ //
+ // Call back into PEI to get status codes. This is because SecMain contains
+ // status code that reports to Win32.
+ //
+ if (mPeiReportStatusCode != NULL) {
+ return mPeiReportStatusCode (CodeType, Value, Instance, CallerId, Data);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_BOOTSERVICE
+VOID
+EFIAPI
+RtPlatformInitializeStatusCode (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the status code listeners.
+
+Arguments:
+
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ VOID *Pointer;
+
+ RtMemoryInitializeStatusCode (ImageHandle, SystemTable);
+ BsDataHubInitializeStatusCode (ImageHandle, SystemTable);
+
+ //
+ // Play any prior status codes to the data hub.
+ //
+ PlaybackStatusCodes (BsDataHubReportStatusCode);
+
+ //
+ // If PEI has a ReportStatusCode callback find it and use it before StdErr
+ // is connected.
+ //
+ mPeiReportStatusCode = NULL;
+
+ Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ if (!EFI_ERROR (Status)) {
+ Status = GetNextGuidHob (&HobList, &gEfiStatusCodeRuntimeProtocolGuid, &Pointer, NULL);
+ if (!EFI_ERROR (Status)) {
+ mPeiReportStatusCode = (EFI_REPORT_STATUS_CODE) (*(UINTN *) Pointer);
+ }
+ }
+}
diff --git a/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.inf b/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.inf new file mode 100644 index 0000000000..d142cebab8 --- /dev/null +++ b/DuetPkg/RtPlatformStatusCode/RtPlatformStatusCode.inf @@ -0,0 +1,47 @@ +#/*++
+#
+# Copyright (c) 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# RtPlatformStatusCode.inf
+#
+# Abstract:
+#
+# Library selecting the listeners for the platform
+#
+#--*/
+
+[defines]
+BASE_NAME = RtPlatformStatusCodeLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ RtPlatformStatusCode.c
+
+[includes.common]
+ $(EDK_SOURCE)\Foundation\Framework
+ $(EDK_SOURCE)\Foundation
+ $(EDK_SOURCE)\Foundation\Efi
+ .
+ $(EDK_SOURCE)\Sample\Platform\Generic\RuntimeDxe\StatusCode\Lib\Include
+ $(EDK_SOURCE)\Foundation\Include
+ $(EDK_SOURCE)\Foundation\Efi\Include
+ $(EDK_SOURCE)\Foundation\Framework\Include
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Core\Dxe
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+
+[libraries.common]
+ HobLib
+ RtMemoryStatusCodeLib
+ BsDataHubStatusCodeLib
+
+[nmake.common]
|