summaryrefslogtreecommitdiff
path: root/Core/CORE_DXE
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_DXE
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/CORE_DXE')
-rw-r--r--Core/CORE_DXE/AmiDxeInit.c427
-rw-r--r--Core/CORE_DXE/BDS.c1607
-rw-r--r--Core/CORE_DXE/Bds.unibin0 -> 5908 bytes
-rw-r--r--Core/CORE_DXE/BdsBoard.c1074
-rw-r--r--Core/CORE_DXE/BootOptions.c2842
-rw-r--r--Core/CORE_DXE/CORE_DXE.cif13
-rw-r--r--Core/CORE_DXE/CORE_DXE.mak189
-rw-r--r--Core/CORE_DXE/CORE_DXE.sdl1169
-rw-r--r--Core/CORE_DXE/CORE_DXESrc.cif75
-rw-r--r--Core/CORE_DXE/CORE_DXESrc.mak155
-rw-r--r--Core/CORE_DXE/CORE_DXESrc.sdl57
-rw-r--r--Core/CORE_DXE/ConSplitter/ConSplit.c2387
-rw-r--r--Core/CORE_DXE/ConSplitter/ConSplit.h553
-rw-r--r--Core/CORE_DXE/ConSplitter/ConSplitter.cif12
-rw-r--r--Core/CORE_DXE/ConSplitter/ConSplitter.sdl26
-rw-r--r--Core/CORE_DXE/ConSplitter/In.c1159
-rw-r--r--Core/CORE_DXE/ConSplitter/Out.c1323
-rw-r--r--Core/CORE_DXE/CoreSectionExtraction.c1367
-rw-r--r--Core/CORE_DXE/DataHub.c681
-rw-r--r--Core/CORE_DXE/DebugImageInfo.c262
-rw-r--r--Core/CORE_DXE/DebugImageInfo.h129
-rw-r--r--Core/CORE_DXE/DebugMask.c399
-rw-r--r--Core/CORE_DXE/DebugMask.h122
-rw-r--r--Core/CORE_DXE/DevicePath.h470
-rw-r--r--Core/CORE_DXE/DevicePathFromText.c3310
-rw-r--r--Core/CORE_DXE/DevicePathToText.c2083
-rw-r--r--Core/CORE_DXE/DiskIo.c978
-rw-r--r--Core/CORE_DXE/Dispatcher.c1351
-rw-r--r--Core/CORE_DXE/DriverSupport.c931
-rw-r--r--Core/CORE_DXE/DxeCore.h2542
-rw-r--r--Core/CORE_DXE/DxeMain.c1065
-rw-r--r--Core/CORE_DXE/DxePerf.c813
-rw-r--r--Core/CORE_DXE/DxeProtocolNotify.c334
-rw-r--r--Core/CORE_DXE/EfiPerf.h99
-rw-r--r--Core/CORE_DXE/Ffs.c266
-rw-r--r--Core/CORE_DXE/FrameworkHii/FrameworkHii.cif10
-rw-r--r--Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl15
-rw-r--r--Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c369
-rw-r--r--Core/CORE_DXE/FrameworkHii/HIIDB.c3511
-rw-r--r--Core/CORE_DXE/FwVol.c589
-rw-r--r--Core/CORE_DXE/FwVolAttrib.c244
-rw-r--r--Core/CORE_DXE/FwVolBlock.c790
-rw-r--r--Core/CORE_DXE/FwVolBlock.h314
-rw-r--r--Core/CORE_DXE/FwVolDriver.h772
-rw-r--r--Core/CORE_DXE/FwVolRead.c993
-rw-r--r--Core/CORE_DXE/FwVolWrite.c102
-rw-r--r--Core/CORE_DXE/GC.c2249
-rw-r--r--Core/CORE_DXE/GenericSio.c3645
-rw-r--r--Core/CORE_DXE/Image.c1710
-rw-r--r--Core/CORE_DXE/Image.h400
-rw-r--r--Core/CORE_DXE/ImageFile.c639
-rw-r--r--Core/CORE_DXE/InstallConfigurationTable.c230
-rw-r--r--Core/CORE_DXE/Library.c811
-rw-r--r--Core/CORE_DXE/Library.h531
-rw-r--r--Core/CORE_DXE/LinkedList.h1
-rw-r--r--Core/CORE_DXE/Notify.c344
-rw-r--r--Core/CORE_DXE/Page.c1685
-rw-r--r--Core/CORE_DXE/Partition/ElTorito.c470
-rw-r--r--Core/CORE_DXE/Partition/ElTorito.h264
-rw-r--r--Core/CORE_DXE/Partition/Gpt.c606
-rw-r--r--Core/CORE_DXE/Partition/Gpt.h161
-rw-r--r--Core/CORE_DXE/Partition/Mbr.c407
-rw-r--r--Core/CORE_DXE/Partition/Mbr.h171
-rw-r--r--Core/CORE_DXE/Partition/Partition.c1006
-rw-r--r--Core/CORE_DXE/Partition/Partition.cif16
-rw-r--r--Core/CORE_DXE/Partition/Partition.h188
-rw-r--r--Core/CORE_DXE/Partition/Partition.sdl4
-rw-r--r--Core/CORE_DXE/SetWatchdogTimer.c84
-rw-r--r--Core/CORE_DXE/Stall.c79
-rw-r--r--Core/CORE_DXE/USFontPack.c315
-rw-r--r--Core/CORE_DXE/UefiHii/HiAccessConfig.c322
-rw-r--r--Core/CORE_DXE/UefiHii/Hii.chmbin0 -> 60152 bytes
-rw-r--r--Core/CORE_DXE/UefiHii/HiiConfig.c1263
-rw-r--r--Core/CORE_DXE/UefiHii/HiiDatabase.c1814
-rw-r--r--Core/CORE_DXE/UefiHii/HiiFont.c1035
-rw-r--r--Core/CORE_DXE/UefiHii/HiiFontEx.c1332
-rw-r--r--Core/CORE_DXE/UefiHii/HiiPrivate.h885
-rw-r--r--Core/CORE_DXE/UefiHii/HiiString.c1609
-rw-r--r--Core/CORE_DXE/UefiHii/UefiHii.cif18
-rw-r--r--Core/CORE_DXE/UefiHii/UefiHii.sdl15
-rw-r--r--Core/CORE_DXE/UefiHii/UefiHiiUtils.c750
-rw-r--r--Core/CORE_DXE/UefiHii/hii21ExportConfig.c1143
-rw-r--r--Core/CORE_DXE/UnicodeCollation.c637
-rw-r--r--Core/CORE_DXE/dependency.c451
-rw-r--r--Core/CORE_DXE/event.c867
-rw-r--r--Core/CORE_DXE/exec.h209
-rw-r--r--Core/CORE_DXE/execdata.c50
-rw-r--r--Core/CORE_DXE/gcd.c2472
-rw-r--r--Core/CORE_DXE/gcd.h54
-rw-r--r--Core/CORE_DXE/hand.h339
-rw-r--r--Core/CORE_DXE/handle.c1703
-rw-r--r--Core/CORE_DXE/hob.c530
-rw-r--r--Core/CORE_DXE/imem.h214
-rw-r--r--Core/CORE_DXE/locate.c777
-rw-r--r--Core/CORE_DXE/memdata.c41
-rw-r--r--Core/CORE_DXE/pool.c620
-rw-r--r--Core/CORE_DXE/timer.c386
-rw-r--r--Core/CORE_DXE/tpl.c198
98 files changed, 73729 insertions, 0 deletions
diff --git a/Core/CORE_DXE/AmiDxeInit.c b/Core/CORE_DXE/AmiDxeInit.c
new file mode 100644
index 0000000..dbd41b5
--- /dev/null
+++ b/Core/CORE_DXE/AmiDxeInit.c
@@ -0,0 +1,427 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/EDK/DxeMain/AmiDxeInit.c 24 5/05/11 3:47p Artems $
+//
+// $Revision: 24 $
+//
+// $Date: 5/05/11 3:47p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/EDK/DxeMain/AmiDxeInit.c $
+//
+// 24 5/05/11 3:47p Artems
+// Added DevicePathToText and DevicePathFromText protocols
+//
+// 23 2/05/11 4:09p Artems
+// EDK library functions CopyMem and ZeroMem moved to EdkLib.c
+//
+// 22 9/29/10 8:05a Felixp
+// Enhancement: Initialization of the library TheImageHandle variable is
+// added.
+//
+// 21 4/22/10 10:43p Felixp
+// Install dummy instance of the security protocol when
+// INSTALL_DUMMY_SECURITY_PROTOCOL SDL token is set to "on".
+//
+// 20 2/23/10 10:01p Felixp
+// Updated to use CORE_COMBINED_VERSION token.
+//
+// 19 11/13/09 4:31p Felixp
+// Buffer overflow protection is added (calls to Sprintf replaced with
+// Sprintf_s).
+//
+// 18 7/30/09 4:04p Felixp
+// Bug fix:
+// Symptoms: memory corruption during DXE Core initialization.
+// Details: the corruption was caused by the HOBs created in AmiDxeInit1.
+// The HOB creation moved to an earlier point (before HOB data is used by
+// CoreInitializeMemoryServices).
+//
+// 17 5/04/09 3:10p Felixp
+// Creation of CPU HOB moved from AmiPeiInit.c to AmiDxeInit.c
+//
+// 16 3/05/09 4:39p Oleksiyy
+// EIP 18486: 3 GUID EXTENSION HOBs created.
+// Code clean up performed.
+//
+// 15 4/18/08 6:28p Felixp
+// checkpoint(0x60) removed. Corresponsing status code (DXE_CORE_ENTRY is
+// now reported at the and of DXE IPL using status code infrastructure
+//
+// 14 3/12/08 12:44p Felixp
+// Progress/Error codes reporting added
+//
+// 13 2/21/08 5:05p Felixp
+// FirmwareRevision field of the EFI system table is updated to use
+// CORE_BUILD_NUMBER.
+//
+// 12 9/05/07 4:22p Felixp
+// FirmwareVendor field of the EFI_SYSTEM_TABLE was initialized with a
+// pointer to boot time memory. However, this is a runtime field.
+// File updated to allocate runtime memory for the field.
+//
+// 11 10/12/06 9:43p Felixp
+//
+// 10 10/12/06 6:51p Felixp
+// UEFI2.0 support: DevicePathUtilities protocol added
+//
+// 9 10/07/06 10:24a Felixp
+// UIEFI2.0 support.
+// Updated to EDK 20060904
+//
+// 8 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 7 5/23/06 4:16a Felixp
+//
+// 6 5/22/06 11:57a Felixp
+//
+// 5 5/22/06 12:12a Felixp
+// Vendor & Revision fields of ST initialized
+//
+// 4 5/20/06 9:37p Felixp
+// checkpoint 0x60 added
+// debug message for drivers startting/stopping
+// clean up
+//
+// 3 5/19/06 10:46p Felixp
+// Updated to EDK 03.16.06
+// Cleanup
+//
+// 2 4/30/06 9:41p Felixp
+//
+// 1 3/13/06 2:00a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmiDxeInit.c
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include<EFI.h>
+#include<Protocol/Decompress.h>
+#include<Protocol/DriverBinding.h>
+#include<Protocol/DevicePathUtilities.h>
+#include<Protocol/DevicePathToText.h>
+#include<Protocol/DevicePathFromText.h>
+#include<Protocol/Security.h>
+#include<AmiDxeLib.h>
+#include<AmiHobs.h>
+#include<Token.h>
+#include<Guid/PeiFlushInstructionCache.h>
+#include<Guid/PeiPeCoffLoader.h>
+#include<Guid/PeiTransferControl.h>
+
+
+EFI_GUID gEfiPeiFlushInstructionCacheGuid = EFI_PEI_FLUSH_INSTRUCTION_CACHE_GUID;
+EFI_GUID gEfiPeiPeCoffLoaderGuid = EFI_PEI_PE_COFF_LOADER_GUID;
+EFI_GUID gEfiPeiTransferControlGuid = EFI_PEI_TRANSFER_CONTROL_GUID;
+EFI_GUID gEfiStatusCodeSpecificDataGuid = EFI_STATUS_CODE_SPECIFIC_DATA_GUID;
+typedef VOID (*INIT_PARTS)(VOID* p1, VOID*p2);
+VOID InitParts(VOID* p1, VOID*p2);
+extern EFI_SYSTEM_TABLE *gST;
+
+extern EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL EfiDevicePathFromTextProtocol;
+extern EFI_DEVICE_PATH_TO_TEXT_PROTOCOL EfiDevicePathToTextProtocol;
+
+///////////////////////////////////////////////////////////////
+////===================== Print Protocol ==================.
+#define EFI_PRINT_PROTOCOL_GUID \
+ { 0xdf2d868e, 0x32fc, 0x4cf0, 0x8e, 0x6b, 0xff, 0xd9, 0x5d, 0x13, 0x43, 0xd0 }
+
+typedef struct _EFI_PRINT_PROTOCOL EFI_PRINT_PROTOCOL;
+
+typedef UINTN (EFIAPI *EFI_VSPRINT)(
+ OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize,
+ IN CHAR16 *FormatString, IN va_list Marker
+);
+
+struct _EFI_PRINT_PROTOCOL{
+ EFI_VSPRINT VSPrint;
+};
+
+EFI_GUID guidPrint = EFI_PRINT_PROTOCOL_GUID;
+EFI_PRINT_PROTOCOL Print = {&Swprintf_s_va_list};
+
+////===================== Decompress Protocol ==================.
+EFI_GUID guidDecompress = EFI_DECOMPRESS_PROTOCOL_GUID;
+EFI_STATUS DecomprGetInfo (
+ IN VOID *This,
+ IN VOID *Source, IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize, OUT UINT32 *ScratchSize
+)
+{
+ return GetInfo(Source,SourceSize,DestinationSize,ScratchSize);
+}
+
+EFI_STATUS DecomprDecompress (
+ IN VOID *This,
+ IN VOID* Source, IN UINT32 SourceSize,
+ IN OUT VOID* Destination, IN UINT32 DestinationSize,
+ IN OUT VOID* Scratch, IN UINT32 ScratchSize
+)
+{
+ return Decompress(Source,SourceSize,Destination,DestinationSize,Scratch,ScratchSize);
+}
+
+EFI_DECOMPRESS_PROTOCOL DecompressInterface = {&DecomprGetInfo, &DecomprDecompress};
+EFI_DECOMPRESS_PROTOCOL *pDecompressInterface=&DecompressInterface;
+
+////===================== Device Path Utilities Protocol ==================
+EFI_DEVICE_PATH_UTILITIES_PROTOCOL DevicePathUtilitiesInstance =
+{
+ (EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)DPLength,
+ (EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)DPCopy,
+ (EFI_DEVICE_PATH_UTILS_APPEND_PATH)DPAdd,
+ (EFI_DEVICE_PATH_UTILS_APPEND_NODE)DPAddNode,
+ (EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)DPAddInstance,
+ (EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)DPNextInstance,
+ (EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)DPIsMultiInstance,
+ (EFI_DEVICE_PATH_UTILS_CREATE_NODE)DPCreateNode
+};
+
+////===================== Security Architectural Protocol =================
+EFI_STATUS FileAuthenticationState(
+ IN EFI_SECURITY_ARCH_PROTOCOL *This,
+ IN UINT32 AuthenticationStatus,
+ IN EFI_DEVICE_PATH_PROTOCOL *File
+)
+{
+ if (File==NULL) return EFI_INVALID_PARAMETER;
+ return EFI_SUCCESS;
+}
+
+EFI_SECURITY_ARCH_PROTOCOL Security = {FileAuthenticationState};
+
+///////////////////////////////////////////////////////////////
+extern EFI_GUID gEfiTianoDecompressProtocolGuid;
+extern VOID *mHobStart;
+extern EFI_HANDLE gDxeCoreImageHandle;
+
+extern EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache;
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;
+extern EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl;
+extern BOOLEAN const InstallDummySecurityProtocol;
+
+VOID *CoreAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize, CONST IN VOID *Buffer
+);
+
+typedef struct{
+ EFI_GUID *pGuid;
+ VOID* pInterface;
+} DXE_MAIN_INTERFACES;
+
+DXE_MAIN_INTERFACES DxeMainInterfaces[] =
+{
+ {&gEfiPeiFlushInstructionCacheGuid,&mFlushInstructionCache},
+ {&gEfiPeiPeCoffLoaderGuid,&mPeCoffLoader},
+ {&gEfiPeiTransferControlGuid,&mTransferControl},
+ {NULL,NULL}
+};
+
+EFI_STATUS CreateHob ( IN UINT16 Type, IN UINT16 Length, IN OUT VOID **Hob ){
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+ EFI_PHYSICAL_ADDRESS FreeMemory;
+
+ if (mHobStart == NULL) return EFI_NOT_AVAILABLE_YET;
+ if (Hob == NULL) return EFI_INVALID_PARAMETER;
+
+ // first entry in the HOB list is the HOB handoff table
+ HandOffHob = mHobStart;
+ // make sure Hob length is a multiple of 8 bytes.
+ Length = (UINT16)((Length + 0x7) & (~0x7));
+ // calculate the amount of free memory
+ FreeMemory = HandOffHob->EfiFreeMemoryTop
+ - HandOffHob->EfiFreeMemoryBottom;
+ if (FreeMemory < Length) return EFI_OUT_OF_RESOURCES;
+
+ // add a HOB to the end of the HOB list
+ *Hob = (VOID*)(UINTN) HandOffHob->EfiEndOfHobList;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length;
+ ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0;
+
+ // move a new end of the HOB list past the newly created HOB
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length);
+ HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ // initialize the new end HOB and update the pointer to the bottom of free memory
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+ HobEnd++;
+ HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ return EFI_SUCCESS;
+}
+
+VOID AmiDxeInit0()
+{
+ DXE_MAIN_INTERFACES *p;
+ EFI_HOB_CPU *CpuHob;
+
+ //Create CPU HOB
+ // NOTE: It is responsibility of CPU and/or NB PEIM to make sure
+ // CPU HOB exists and contains valid data.
+ // The HOB created here is just to prevent system from hanging
+ // in case CPU HOB has not been created.
+ // If CPU HOB already exists, the HOB crated here will be ignored
+ // by DXE Core because it uses only the first instance of the HOB.
+ CreateHob(EFI_HOB_TYPE_CPU, sizeof(EFI_HOB_CPU), &CpuHob);
+ CpuHob->SizeOfMemorySpace=32;
+ CpuHob->SizeOfIoSpace=16;
+ CpuHob->Reserved[0]=0;
+ CpuHob->Reserved[1]=0;
+ CpuHob->Reserved[2]=0;
+ CpuHob->Reserved[3]=0;
+ CpuHob->Reserved[4]=0;
+ CpuHob->Reserved[5]=0;
+
+ // =========== Initialize DxeMain Pointers
+ for(p=DxeMainInterfaces; p->pGuid; p++)
+ {
+ PEIM_HOB *PeimHob;
+ CreateHob(EFI_HOB_TYPE_GUID_EXTENSION, sizeof(PEIM_HOB),&PeimHob);
+ PeimHob->Header.Name = *p->pGuid;
+ PeimHob->DxeEntryPoint= p->pInterface;
+ }
+}
+
+VOID AmiDxeInit1()
+{
+ InitAmiLib(gDxeCoreImageHandle,gST);
+
+ // =========== Initialize System Table Fields
+ gST->FirmwareVendor = CoreAllocateRuntimeCopyPool(
+ sizeof( CONVERT_TO_WSTRING(CORE_VENDOR)), CONVERT_TO_WSTRING(CORE_VENDOR)
+ );
+ gST->FirmwareRevision = CORE_COMBINED_VERSION;
+}
+
+VOID AmiDxeInit2()
+{
+ VOID *p=mHobStart;
+ EFI_HANDLE Handle = NULL;
+
+// TheImageHandle is a library variable, which is initialized in the InitAmiLib library function
+// However, in our case InitAmiLib has been called too early (from AmiDxeInit1), before
+// gDxeCoreImageHandle has beeen initialized. It is initialized now.
+// Let's update TheImageHandle variable.
+ TheImageHandle = gDxeCoreImageHandle;
+ // =========== Initialize modules inherited from PEI ======================= //
+#ifndef EFIx64 //no code sharing between PEI and DXE in x64 mode
+ for(p = mHobStart; !EFI_ERROR(FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION,&p)); )
+ {
+ PEIM_HOB *pHob = (PEIM_HOB*)p;
+ static EFI_GUID guidAmiPeimHob = AMI_PEIM_HOB_GUID;
+ if (guidcmp(&pHob->Header.Name,&guidAmiPeimHob)) continue;
+ pHob->DxeEntryPoint(gDxeCoreImageHandle,gST);
+ }
+#endif
+ // ========================================================================== //
+ gST->BootServices->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &guidDecompress, &DecompressInterface,
+ &gEfiTianoDecompressProtocolGuid, &DecompressInterface,
+ &guidPrint, &Print,
+ &gEfiDevicePathUtilitiesProtocolGuid, &DevicePathUtilitiesInstance,
+ &gEfiDevicePathFromTextProtocolGuid, &EfiDevicePathFromTextProtocol,
+ &gEfiDevicePathToTextProtocolGuid, &EfiDevicePathToTextProtocol,
+ NULL
+ );
+ if (InstallDummySecurityProtocol)
+ gST->BootServices->InstallMultipleProtocolInterfaces(
+ &Handle, &gEfiSecurityArchProtocolGuid, &Security, NULL
+ );
+ InitParts(gDxeCoreImageHandle,gST);
+}
+
+EFI_STATUS AmiResetNotAvailableYet(
+ IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize, IN CHAR16 *ResetData OPTIONAL
+)
+{
+ ERROR_CODE(DXE_RESET_NOT_AVAILABLE,EFI_ERROR_MINOR);
+ return EFI_NOT_AVAILABLE_YET;;
+}
+
+VOID AmiReportArhcProtocolMissingError(){
+ ERROR_CODE(DXE_ARCH_PROTOCOL_NOT_AVAILABLE,EFI_ERROR_MAJOR);
+}
+
+//GUID definitions
+
+/// Library routines
+#ifdef EFI_DEBUG
+#define EFI_D_ERROR 0x80000000 // Error
+#define EFI_DBUG_MASK (EFI_D_ERROR)
+#define EFI_D_LOAD 0x00000004 // Load events
+UINTN gErrorLevel=EFI_DBUG_MASK | EFI_D_LOAD;
+
+VOID
+EfiDebugAssert (
+ IN CHAR8 *FileName,
+ IN INTN LineNumber,
+ IN CHAR8 *Description
+ )
+ {
+ Trace(TRACE_ALWAYS,"ASSERT in %s on %i: %s\n",FileName, LineNumber, Description);
+ EFI_DEADLOOP()
+ }
+
+VOID
+EfiDebugVPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ IN va_list ArgList
+ )
+ {
+ if (!gST) return;
+#if EFI_SPECIFICATION_VERSION<0x20000
+ if (!(gST->RuntimeServices && gST->RuntimeServices->ReportStatusCode)) return;
+#endif
+ if (!(gErrorLevel & ErrorLevel)) return;
+ PrintDebugMessageVaList(ErrorLevel, Format, ArgList);
+ }
+
+CHAR8* GetDriverName(EFI_DRIVER_BINDING_PROTOCOL *pDriver)
+{
+ static char sName[0x100];
+ if ( !GetImageName(pDriver->DriverBindingHandle,sName)
+ && !GetImageName(pDriver->ImageHandle,sName)
+ ) Sprintf_s(sName,sizeof(sName),"Unknown");
+ return sName;
+}
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/BDS.c b/Core/CORE_DXE/BDS.c
new file mode 100644
index 0000000..f3302c2
--- /dev/null
+++ b/Core/CORE_DXE/BDS.c
@@ -0,0 +1,1607 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BDS.c 3 7/15/14 9:54p Chienhsieh $
+//
+// $Revision: 3 $
+//
+// $Date: 7/15/14 9:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BDS.c $
+//
+// 3 7/15/14 9:54p Chienhsieh
+// Update rev.125 for EIP172950, Core updates for UEFI Variable Technical
+// Advisory implement.
+//
+// 125 5/09/14 2:44p Artems
+// [TAG] EIP166565
+// [Category] Improvement
+// [Description] Removed runtime-access attribute from the variables
+// MemoryTypeInformation
+// and PreviousMemoryTypeInformation
+// [Files] BDS.c
+//
+// 2 11/21/12 4:21a Wesleychen
+// Update for SCT test (EIP104956).
+//
+// 117 10/29/12 4:03p Artems
+// [TAG] EIP104956
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] UEFI 2.3.1 SCT test failed in Generic\EfiCompliant case.
+// The VariableAttribute of ErrOut is not correct.
+// [RootCause] System variable ErrOut was saved without EFI_NON_VOLATILE
+// attribute
+// [Solution] Added missing attribute
+// [Files] Bds.c
+//
+// 116 10/08/12 6:56p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] build error with message invalid Code page
+// [RootCause] Presence of special characters in debug comment
+// [Solution] Removed special characters
+// [Files] BDS.c
+//
+// 115 7/20/12 10:33a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Improved debug output for SaveMemoryInformation
+// function
+// [Files] BDS.c
+//
+// 114 5/30/12 4:59p Felixp
+// SaveMemoryTypeInformation is updated to never decrease the memory type
+// usage values
+// to workaround Windows 7 and Windows 8 bug.
+//
+// 113 5/30/12 3:12p Felixp
+// [TAG] EIP90941
+// [Category] Bug Fix
+// [Symptom] "System resume from S4 would have problem when iRST
+// setting changed and system did S4.
+// [RootCause] SaveMemoryTypeInformation has been called twice.
+// [Solution] The function is updated to perform processing only during
+// the first call.
+//
+// 112 5/23/12 11:42a Artems
+// [TAG] EIP N/A
+// [Category] Spec Update
+// [Description] Replaced FirmwareVolume protocol with FirmwareVolume2
+// protocol
+// [Files] bootoptions.h BDS.c
+//
+// 111 4/12/12 11:12a Felixp
+// [TAG] EIP85611
+// [Category] Improvement
+// [Description] Memory map is not consistent between
+// second and third boots if system has been reset from the Setup
+// during the very first boot.
+// [Files] Bds.c, CORE_DXE.sdl
+//
+// 110 12/05/11 2:18p Felixp
+// // 109 11/21/11 11:03a Felixp
+// // [TAG] EIP69841
+// // [Category] Improvement
+// // [Description] Improvements in the Memory Type Information
+// processing
+// // to properly handle first boot.
+//
+// 109 11/21/11 11:03a Felixp
+// [TAG] EIP69841
+// [Category] Improvement
+// [Description] Improvements in the Memory Type Information processing
+// to properly handle S4 resume during the fast boot.
+//
+// 108 11/09/11 3:19p Oleksiyy
+// [TAG] EIP64296
+// [Category] New Feature
+// [Description] Creation and filling of Firmware Performance Data Table
+// is added.
+// [Files] AcpiCore.c, AmiDxeLib.h, BDS.c, DxeMain.c, EfiLib.c,
+// Image.c, S3Resume.c and FirmPerfDataTab.h
+//
+// 107 11/01/11 1:55p Felixp
+// [TAG] EIP 69841 and 71719
+// [Category] Improvement
+// [Description] The AMI customizations are removed from the DXE memory
+// manager.
+// They are replaced with the Memory Type Information HOB used in Tiano
+// projects.
+// This is done to reduces number of descriptors in the memory map
+// and to workaround Windows bug (Windows can't handle memory allocations
+// that happen after the start of the OS loader).
+// [Files] CORE_DXE.sdl, Page.c, BDS.c, DxeIpl.c
+//
+// 106 11/01/11 1:42p Felixp
+// Improvement: Support for logging of the performance information during
+// legacy boot.
+//
+// 105 10/20/11 6:59p Artems
+// Function ConnectConsoles moved to FastBoot module
+//
+// 104 3/16/11 11:41p Felixp
+// Editorial: Several spelling errors in the comments are fixed
+//
+// 103 2/25/11 12:51p Artems
+// EIP 53767 - Velocity boot time above 5 seconds. Added provision to skip
+// USB keyboard initialization
+//
+// 102 2/15/11 6:52p Artems
+// Add possibility to modify ConnectConsoles function list with SDL tokens
+//
+// 101 12/03/10 10:26a Felixp
+//
+// 100 12/03/10 10:23a Felixp
+//
+// 99 12/03/10 10:23a Felixp
+// Bug fix in InitConVars: console-related fields of the systems table
+// were not initialized on headless systems.
+//
+// 98 10/15/10 12:02p Felixp
+// Bug fix in ConnectConsoles function
+//
+// 97 10/01/10 8:02a Felixp
+// ThisImageHandle variabled added (for compatibility with existing
+// modules)
+// Clean up
+//
+// 96 9/29/10 9:21a Felixp
+// Enhancement(EIP 39464) : Implementation of the BdsEntry function is
+// changed.
+// The BdsEntry is now a dispatching function that calls a collection of
+// functions
+// formed by the BDS_CONTROL_FLOW eLink.
+//
+// 95 6/29/10 11:06p Felixp
+// New Boot Options Maintenance Infrastructure.
+// See AMI_Aptio_4.x_Boot_Options_Maintenance_Infrastructure_Porting_Guide
+// _NDA.doc for details.
+//
+// 94 5/07/10 6:00p Felixp
+// Improvement in ConnectDevicePath (EIP 38132): Null pointer check of the
+// input parameter is added
+//
+// 93 3/22/10 10:20a Artems
+// EIP 35562 Fixed boot variable name - hex digits should be in upper case
+//
+// 92 2/03/10 4:34p Oleksiyy
+// Minor bug fix (typecasting)
+//
+// 91 2/02/10 5:45p Felixp
+// Fast Boot related code is removed from BDS. It is now part of the stand
+// alone FastBoot eModule.
+//
+// 90 10/28/09 12:19p Felixp
+// Minor bug fix: check for a NULL pointer is added to the
+// CreateLegacyBootOption function(EIP 28577).
+//
+// 89 10/09/09 6:06p Felixp
+// UEFI 2.1 - related changes (suppot Framework and UEFI HII).
+//
+// 88 10/09/09 11:58a Felixp
+// Code that sets ConOutDev variable is removed. It is not needed. The
+// variable is set by the ConSplitter driver.
+//
+// 87 8/04/09 1:28p Felixp
+// Bug fix: in BuildBootOptionName function.
+// Symptoms: Systems with several boot devices where occasionally handing
+// towards the end of the BDS phase.
+//
+// 86 7/10/09 5:58p Felixp
+// New Boot Option Maintenance Ifrastructure is added
+//
+// 85 7/08/09 8:36a Felixp
+// Bug fix (EIP 23027): Update NVRAM instance of LegacyDevOrder variable
+// when it's modified by the AdjustLegacyDevOrder function.
+//
+// 84 6/26/09 3:08p Felixp
+// ConnectDefaultConOut updated:
+// 1. AGP support is removed
+// 2. Improved on-board device detection logic
+// (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE attribut is used).
+//
+// 83 5/22/09 9:52a Felixp
+// Minor improvements in AdjustLegacyDevOrder function
+//
+// 82 5/21/09 5:20p Felixp
+// Bug fix in BuildBootOptionName function
+//
+// 81 1/20/09 10:57p Felixp
+//
+// 80 1/20/09 3:30p Felixp
+// Bug fix. EIP 16566. Order of legacy devices within BBS group is reset
+// when configuration changes.
+// Symptoms: Order of legacy devices within BBS group is sometimes reset
+// when bootable devices are added (enabled) or removed (disabled).
+// Here is one of the ways to reproduce the problem:
+// 1. Make sure the following bootable devices are plugged into the
+// system:
+// - Bootable network device (onboard or offboard)
+// - USB flash drive emulated as hard drive
+// - IDE or SATA hard drive
+// 2. Boot to setup.
+// 3. Enable PXE boot using "Lunch PXE OpRom" option on the "Advanced"
+// page.
+// 4. Save the settings, reboot the system, and enter the setup.
+// 5. On the "Boot" page, update "Hard Driver BBS Priorities" to set USB
+// drive as a first boot device.
+// 6. Disable PXE boot using "Lunch PXE OpRom" option on the "Advanced"
+// page.
+// 7. Save the settings, reboot the system, and enter the setup.
+// 8. Enter "Hard Driver BBS Priorities" menu on the "Boot" page.
+// USB drive priority has been reset( it is no longer the first boot
+// device).
+// Details: BDS used index within BBS table to match saved priorities with
+// available boot devices.
+// However, when list of boot devices changes, BBS index may also change.
+// For example, when network boot is enabled, boot option for a network
+// device
+// is inserted into the BBS table prior to the USB drive boot option.
+// As a result, index of the USB drive boot option increases by one
+// and matching against saved boor priority fails.
+// BDS code is updated to save more information about legacy boot devices.
+// For every legacy boot device BDS saves
+// checksum of the device name into the NVRAM (along with device index).
+// When index matching fails, BDS uses saved checksum to find updated BBS
+// index
+// of the boot option.
+//
+// 79 1/14/09 3:52p Felixp
+// BDS updated to signal beginning of the driver connection cycle by
+// installing the protocol.
+//
+// 78 1/05/09 3:02p Felixp
+// Bug fix. EIP 17217
+// Problems during video card switching.
+// Symptoms: Some systems were hanging during after replacement
+// of the video card.
+//
+// 77 11/03/08 5:21p Felixp
+// Do no re-create boot option for the built-in Shell, if Shell is not
+// included into the ROM
+//
+// 76 10/29/08 12:52p Felixp
+// RunDrivers updates: ignore non-active driver options; perform reconnect
+// once
+//
+// 74 10/22/08 4:24p Felixp
+//
+// 73 10/22/08 11:35a Felixp
+// 1. Code to recreate deleted boot option for the built-in Shell is
+// added(EIP 15524).
+// 2. Processing of the DriverOrder list is added
+// 3. Clean up
+//
+// 72 10/21/08 5:56p Felixp
+// Multi-language support added to UEFI boot options implementation
+//
+// 71 10/21/08 3:30p Felixp
+// BuildBootOptionName function improvements and bug fixes
+//
+// 70 10/17/08 3:46p Yakovlevs
+// Support for UEFI boot options added
+//
+// 69 10/10/08 4:25p Felixp
+// - Improved handling of console devices
+// - Clean up
+//
+// 68 10/09/08 5:07p Felixp
+// Bug fixes:
+// - Support for systems with no console devices.
+// If no console input or output devices are available,
+// system table is populated with the fake ConIn/ConOut handles
+// and protocol interface pointers.
+// This prevents potential failures caused by the NULL pointers in the
+// system table.
+// - Early Console device initialization during the first boot(EIP 13459).
+// During the very first boot after the firmware update,
+// console devices were initialized towards the end of the boot.
+// The logic has been updated to initialize default console devices
+// at the beginning of the BDS connection cycle.
+// - Serial Redirection could not be enabled, if
+// it was disabled by default(EIP 15565)
+//
+// 67 9/30/08 11:07p Felixp
+// Performance measurement support: callback to publish performance data
+// for OS usage added (the callback is generated by TSE).
+//
+// 66 6/06/08 11:00a Felixp
+// 1. Performance measurement support is added
+// 2. Support for boot with minimal configuration is added
+// 3. Code is reformatted in accordance with the coding standards
+//
+// 65 5/06/08 10:07a Felixp
+//
+// 64 12/17/07 4:07p Felixp
+// Signal protocol event before handing control over to TSE
+//
+// 63 11/08/07 4:51p Felixp
+// Code updated to compile and work without CSM.
+//
+// 62 10/26/07 2:36p Felixp
+// New FW based load file protocl is added.
+// This protocol is used to load FW based EFI applications such as built
+// in Shell.
+//
+// 61 10/17/07 11:28a Felixp
+// Update in InitBbs routine: Delete LegacyDevOrder when no legacy devices
+// are found.
+// This fixes hang in AMITSE when no bootable devices are present.
+//
+// 60 8/31/07 1:55p Felixp
+// Updated to support new location of AMIPostMgr.h. It is moved from
+// Core/em/AMITSE into Include/Protocol
+//
+// 59 8/07/07 2:36p Felixp
+// Additionanal Status Codes added
+//
+// 58 4/10/07 9:34a Felixp
+//
+// 55 3/18/07 2:30p Felixp
+// Initialization of Lang & LangCodes variables removed
+// (it is done in Setup now)
+//
+// 54 2/28/07 7:32p Felixp
+//
+// 52 2/26/07 6:12p Felixp
+// Bug fix in SetBbsPriorities.
+//
+// 51 2/13/07 9:18a Felixp
+// MRE Handshake protocol renamed to AMI POST Manager protocol
+// (MreHandshake.h removed from Core Protocols and added to AMITSE module
+// as AMIPostMgr.h)
+//
+// 50 2/12/07 1:45p Felixp
+// 1. Correct handling of disabled legacy BBS options
+// 2. Name of the legacy device removed from legacy boot option because it
+// is not needed (AMITSE does not use it)
+// 3. Clean up in ConnectDevicePath
+//
+// 49 12/29/06 3:00p Felixp
+// Console initialization logic changed
+//
+// 48 10/30/06 6:03p Felixp
+// Updated to be complient with HII Spec. 0.92 (used to be 0.91)
+//
+// 47 10/13/06 4:43p Felixp
+// Beep when ConIn available
+//
+// 46 10/13/06 9:27a Felixp
+// Patch for disconnected FDD moved to a proper place
+//
+// 45 10/12/06 9:42a Felixp
+// UEFI2.0 compliance: use CreateReadyToBootEvent instead of CreateEvent
+//
+// 44 9/29/06 3:52p Pavell
+// Added processing and dispatching capsule
+//
+// 42 5/23/06 4:17a Felixp
+// Patch for disconnection of the Floppy Controller added
+//
+// 41 5/19/06 10:45p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 40 3/13/06 10:07a Felixp
+//
+// 39 12/22/05 11:25a Felixp
+//
+// 38 11/08/05 4:07a Felixp
+// Support for TSE notifications added
+//
+// 37 11/07/05 10:34a Felixp
+// Boot with minimum configuration suuport
+//
+// 36 9/29/05 4:36p Robert
+//
+// 35 8/25/05 11:47a Felixp
+// Code added to start Standard ConIn devices (PS2, USB) early
+//
+// 34 8/25/05 11:41a Felixp
+//
+// 33 8/22/05 5:29p Felixp
+// Invoke dispatcher before boot
+//
+// 32 7/29/05 6:52p Felixp
+// improvement in InitBbs: correct handling of LegacyDevOrder shorter then
+// 6 bytes
+//
+// 3 7/20/05 8:03p Felixp
+// workaround for password support
+//
+// 28 7/15/05 7:16p Felixp
+// CONSOLE_DEVICES_STARTED_PROTOCOL_GUID added.
+// BDS uses it to notify Splitter that Console Devices have been started.
+// Once Splitter receives notification, it will install ConIn and ConOut
+// in System Table
+//
+// 27 7/14/05 12:10a Felixp
+// BBS support
+//
+// 25 5/24/05 2:55p Felixp
+// Boot menu logic moved to SetupEngine.
+// Now BDS just gives control to MREHandshake
+//
+// 24 4/28/05 1:06p Felixp
+// bug fix in InitConVars
+//
+// 23 4/25/05 12:12p Felixp
+// AddBootOption - loader options can now be passed
+//
+// 21 4/08/05 3:02p Felixp
+// SignalReadyToBoot added
+//
+// 20 4/08/05 7:39a Felixp
+// Boot Menu implemented
+//
+// 19 4/02/05 3:24p Felixp
+//
+// 18 3/28/05 7:03p Felixp
+// DrawBmp function added
+//
+// 15 3/17/05 7:51p Felixp
+// pBootScript->CloseTable commented out
+//
+// 14 3/15/05 2:55p Felixp
+// 1. Code to initialize global EFI variables added
+// 2. Code to Close boot script table and save the address to NVRAM added
+//
+// 13 2/14/05 10:40a Felixp
+// Off-board video started before on-board
+//
+// 12 2/11/05 6:05p Felixp
+// Code optimized by using DPAddNode instead of DPAdd
+// Logic to set video card priorities added(from hi ti lo):
+// AGP->on board PCI ->off board PCI
+//
+// 11 2/07/05 5:21p Felixp
+// function GetEfiVariable moved to AmiDxeLib
+//
+// 10 2/03/05 8:07p Felixp
+// ConnectDevicePath change: now last node connected recursively
+//
+// 9 2/03/05 7:58p Felixp
+//
+// 8 2/03/05 7:45p Felixp
+// Logic to initialize Console variables added
+//
+// 7 2/01/05 4:24p Felixp
+// 1 .ConnectDevicePath fixed (before it didn't connect last node in the
+// device path)
+// 2. REAY to BOOT event signaled
+//
+// 6 1/25/05 3:27p Felixp
+// if GSE absent restart shell if it returns
+//
+// 5 1/19/05 7:01p Felixp
+//
+// 3 1/18/05 3:21p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 2 1/10/05 5:10p Felixp
+// Patches for Intel CSM and Intel Terminal driver disabled
+//
+// 28 12/23/04 9:29a Felixp
+// ArchProtocols moved to Include\Protocols
+//
+// 27 12/21/04 4:53p Markw
+// Modified device path defines for consistency.
+//
+// 26 12/21/04 4:21p Markw
+// Renamed hardware device path definition for consistency.
+//
+// 21 12/01/04 3:24p Felixp
+// GSE support added
+//
+// 20 8/03/04 6:46p Felixp
+// SetVariable for "Lang" and "LangCodes" moved to do it before all
+// drivers are connected
+//
+// 15 7/16/04 3:57p Felixp
+// Changes to support both 7f and ff values for the device path end type
+//
+// 1 3/30/04 3:26p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: BDS.c
+//
+// Description: Implementation of the BDS architectural protocol
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include "BootOptions.h"
+#include <Protocol/BDS.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h >
+#include <Protocol/LoadedImage.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/AMIPostMgr.h>
+#include <Protocol/LoadFile.h>
+#include <DXE.h>
+#include <HOB.h>
+#include <Guid/MemoryTypeInformation.h>
+
+/**************************** TYPES ***********************************/
+
+/***************** FUNCTION DECLARATIONS *****************************/
+//this funciton is created from InitList.c template file during build process
+VOID InitParts2(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable);
+
+//Local functions
+VOID BdsEntry (IN EFI_BDS_ARCH_PROTOCOL *This);
+
+EFI_STATUS FwLoadFile (
+ IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+);
+
+/**************************** CONSTANTS *******************************/
+#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \
+ {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93}
+// {3AA83745-9454-4f7a-A7C0-90DBD02FAB8E}
+#define BDS_CONNECT_DRIVERS_PROTOCOL_GUID \
+ { 0x3aa83745, 0x9454, 0x4f7a, { 0xa7, 0xc0, 0x90, 0xdb, 0xd0, 0x2f, 0xab, 0x8e } }
+// {8DB699CC-BC81-41e2-AAC6-D81D5300D759}
+#define PARTITION_VARIABLE_GUID\
+ { 0x8db699cc, 0xbc81, 0x41e2, { 0xaa, 0xc6, 0xd8, 0x1d, 0x53, 0x0, 0xd7, 0x59 } }
+// {5023B95C-DB26-429b-A648-BD47664C8012}
+#define AMI_MEDIA_DEVICE_PATH_GUID \
+ { 0x5023b95c, 0xdb26, 0x429b, { 0xa6, 0x48, 0xbd, 0x47, 0x66, 0x4c, 0x80, 0x12 } }
+
+extern EFI_GUID gEfiBdsArchProtocolGuid; // = EFI_BDS_ARCH_PROTOCOL_GUID;
+extern EFI_GUID gEfiDevicePathProtocolGuid ;//= EFI_DEVICE_PATH_PROTOCOL_GUID;
+extern EFI_GUID gEfiFirmwareVolume2ProtocolGuid; // = EFI_FIRMWARE_VOLUME_PROTOCOL_GUID;
+extern EFI_GUID gEfiLoadedImageProtocolGuid; //=EFI_LOADED_IMAGE_PROTOCOL_GUID;
+extern EFI_GUID gEfiPciIoProtocolGuid; // = EFI_PCI_IO_PROTOCOL_GUID;
+extern EFI_GUID gEfiBlockIoProtocolGuid;
+extern EFI_GUID gEfiLoadFileProtocolGuid;
+extern EFI_GUID gEfiSimpleFileSystemProtocolGuid;
+//defined in BdsBoard.c
+extern EFI_GUID SetupEnterProtocolGuid;
+extern EFI_GUID SecondBootOptionProtocolGuid;
+extern EFI_GUID BeforeBootProtocolGuid;
+extern EFI_GUID BeforeLegacyBootProtocolGuid;
+extern EFI_GUID *DefaultAppFfsGuidPtr;
+
+extern BDS_CONTROL_FLOW_FUNCTION *BdsControlFlowFunctions[];
+extern CHAR8 *BdsControlFlowFunctionNames[];
+
+EFI_GUID EfiVariableGuid = EFI_GLOBAL_VARIABLE;
+EFI_GUID AmiPostMgrProtocolGuid=AMI_POST_MANAGER_PROTOCOL_GUID;
+EFI_GUID ConInStartedProtocolGuid = CONSOLE_IN_DEVICES_STARTED_PROTOCOL_GUID;
+EFI_GUID ConOutStartedProtocolGuid = CONSOLE_OUT_DEVICES_STARTED_PROTOCOL_GUID;
+EFI_GUID BdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID;
+EFI_GUID BdsConnectDriversProtocolGuid = BDS_CONNECT_DRIVERS_PROTOCOL_GUID;
+EFI_GUID PartitionVariableGuid = PARTITION_VARIABLE_GUID;
+
+EFI_BDS_ARCH_PROTOCOL BDS = {&BdsEntry};
+
+/**************************** VARIABLES *******************************/
+//externals defined in BdsBoard.c
+extern UINT16 DefaultTimeout;
+extern BOOLEAN QuietBoot;
+extern STRING_REF StrToken[];
+
+// Global Variables
+EFI_LOAD_FILE_PROTOCOL FwLoadFileInterface = {FwLoadFile};
+
+struct {
+ VENDOR_DEVICE_PATH Media;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FwLoadFileDp = {
+ {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
+ sizeof(VENDOR_DEVICE_PATH)
+ },
+ AMI_MEDIA_DEVICE_PATH_GUID
+ },
+ {
+ END_DEVICE_PATH, END_ENTIRE_SUBTYPE,
+ sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+EFI_HANDLE LpcHandle = NULL;
+EFI_DEVICE_PATH_PROTOCOL *LpcDevicePath = NULL;
+
+VOID ConnectDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *pPath)
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ if (pPath == NULL) return;
+ while (TRUE)
+ {
+ EFI_DEVICE_PATH_PROTOCOL *pLastPath=NULL, *pFirstNode = pPath;
+ if (isEndNode(pPath))
+ {
+ if (pPath->SubType == END_ENTIRE_SUBTYPE) break;
+ pPath++;
+ continue;
+ }
+ while(TRUE){
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINT8 SubType;
+
+ pPath = pFirstNode;
+
+ //LocateDevicePath can not work with multi-instance device paths.
+ //Prepare single instance device path and call LocateDevicePath
+ Dp = DPGetEndNode(pPath);
+ SubType = Dp->SubType;
+ Dp->SubType=END_ENTIRE_SUBTYPE;
+ Status = pBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &pPath, &Handle);
+ Dp->SubType=SubType;
+ if (EFI_ERROR(Status)) break;
+
+ if (isEndNode(pPath))
+ {
+ //Last time let's do it recursively
+ pBS->ConnectController(Handle,NULL,NULL,TRUE);
+ break;
+ }
+ if (pPath==pLastPath) break;
+ pLastPath = pPath;
+ if (EFI_ERROR(pBS->ConnectController(Handle,NULL,pPath,FALSE))) break;
+ }
+ while (!isEndNode(pPath))
+ pPath = NEXT_NODE(pPath);
+ }
+}
+
+EFI_DEVICE_PATH_PROTOCOL* AddDevicePath(EFI_DEVICE_PATH_PROTOCOL *pDp1, EFI_DEVICE_PATH_PROTOCOL *pDp2)
+{
+ if (!pDp2) return pDp1;
+ if (!pDp1)
+ {
+ return DPCopy(pDp2);
+ }
+ else
+ {
+ pDp2 = DPAddInstance(pDp1,pDp2);
+ pBS->FreePool(pDp1);
+ return pDp2;
+ }
+}
+
+EFI_STATUS GetPciHandlesByClass(
+ UINT8 Class, UINT8 SubClass, UINTN *NumberOfHandles, EFI_HANDLE **HandleBuffer
+){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+
+ if (!NumberOfHandles || !HandleBuffer) return EFI_INVALID_PARAMETER;
+ //Get a list of all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciIoProtocolGuid, NULL, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return Status;
+ *NumberOfHandles = 0;
+ for(i=0; i<Number; i++)
+ {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 PciClass[4];
+ Status=pBS->HandleProtocol(Handle[i],&gEfiPciIoProtocolGuid,&PciIo);
+ if (EFI_ERROR(Status)) continue;
+ Status=PciIo->Pci.Read(PciIo, EfiPciIoWidthUint32, PCI_REV_ID_OFFSET, 1, &PciClass);
+ if( PciClass[3]==Class && PciClass[2]==SubClass)
+ Handle[(*NumberOfHandles)++] = Handle[i];
+ }
+ if (*NumberOfHandles == 0){
+ pBS->FreePool(Handle);
+ return EFI_NOT_FOUND;
+ }
+ *HandleBuffer = Handle;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS InitSystemVariable(
+ IN CHAR16 *NameStr, IN UINTN DataSize, IN VOID *Data
+)
+{
+ UINTN Size = 0;
+ EFI_STATUS Status;
+ Status = pRS->GetVariable(NameStr, &EfiVariableGuid, NULL, &Size, NULL);
+ if (Status==EFI_NOT_FOUND)
+ {
+ return pRS->SetVariable(
+ NameStr, &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize, Data);
+ }
+ return EFI_SUCCESS;
+}
+
+static EFI_HANDLE *RootHandles;
+static UINTN NumberOfHandles;
+VOID ConnectEverything()
+{
+ UINTN i;
+ for(i=0; i<NumberOfHandles; i++) pBS->ConnectController(RootHandles[i],NULL,NULL,TRUE);
+/////////////////////////////////////////
+//TODO: Ugly patch for the Floppy Controller. Find the better place for it!
+// It is necessary to Disconnect Floppy Device Handle when Floppy Drive is not connected.
+// This is necessary to disable Floppy Device in the Super I/O
+// and eliminate BBS Floppy boot option.
+// It was previously done (In Core 4.0) by the Floppy Controller driver.
+// However, EDK DXE Core (DxeMain) crashes during the
+// DisconnectController operation performed from within the Start function.
+// Because of that, the Floppy Controller driver code is commented out
+// and this patch is created.
+// If you remove this code, you should also remove
+// LpcHandle & LpcDevicePath global variables.
+// They are only used to implement this patch.
+ if (LpcDevicePath)
+ {
+ EFI_HANDLE Handle;
+ ACPI_HID_DEVICE_PATH FloppyCtrl = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0x0604),0
+ };
+ EFI_DEVICE_PATH_PROTOCOL *ChildDp=DPAddNode(LpcDevicePath, &FloppyCtrl.Header);
+ EFI_STATUS Status=pBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &ChildDp, &Handle);
+ if (!EFI_ERROR(Status) && isEndNode(ChildDp))
+ {
+ VOID* pDummy;
+ Status = pBS->HandleProtocol(Handle,&gEfiBlockIoProtocolGuid,&pDummy);
+ if (EFI_ERROR(Status)) pBS->DisconnectController(LpcHandle,NULL,Handle);
+ }
+ }
+}
+VOID DisconnectEverything()
+{
+ UINTN i;
+ for(i=0; i<NumberOfHandles; i++) pBS->DisconnectController(RootHandles[i],NULL,NULL);
+}
+
+VOID ReadyToBoot(UINT16 OptionNumber)
+{
+ //signal EFI_EVENT_SIGNAL_READY_TO_BOOT
+ EFI_EVENT ReadToBootEvent;
+ EFI_STATUS Status;
+ if (OptionNumber!= (UINT16)-1)
+ pRS->SetVariable(
+ L"BootCurrent", &EfiVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(OptionNumber), &OptionNumber
+ );
+ Status = CreateReadyToBootEvent(
+ TPL_CALLBACK, NULL, NULL, &ReadToBootEvent
+ );
+ if (!EFI_ERROR(Status)) {
+ pBS->SignalEvent(ReadToBootEvent);
+ pBS->CloseEvent(ReadToBootEvent);
+ }
+}
+
+#if CSM_SUPPORT
+EFI_STATUS BootLegacy(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT16 Number)
+{
+ UINTN i, Old=-1, New, Priority=-1;
+ BBS_BBS_DEVICE_PATH *BbsEntry = (BBS_BBS_DEVICE_PATH*)Dp;
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *HddInfo;
+ BBS_TABLE *BbsTable;
+
+ // Legacy Boot
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);
+ if(EFI_ERROR(Status)) return Status;
+ LegacyBios->GetBbsInfo(LegacyBios, &HddCount, &HddInfo, &BbsCount, &BbsTable);
+ if (!BbsCount) return EFI_NOT_FOUND;
+ for(i=0; i<BbsCount; i++)
+ {
+ if ( // !BbsTable[i].StatusFlags.Enabled
+ /*||*/ BbsTable[i].BootPriority==BBS_IGNORE_ENTRY
+ || BbsTable[i].BootPriority==BBS_DO_NOT_BOOT_FROM
+ ) continue;
+ if (!BbsTable[i].BootPriority && Old==-1) Old=i;
+ if ( BbsTable[i].DeviceType==BbsEntry->DeviceType
+ && BbsTable[i].BootPriority < Priority
+ )
+ {
+ Priority = BbsTable[i].BootPriority;
+ New = i;
+ }
+ }
+ if (Old!=-1) BbsTable[Old].BootPriority=BbsTable[New].BootPriority;
+ BbsTable[New].BootPriority=0;
+ ReadyToBoot(Number);
+ return LegacyBios->LegacyBoot(LegacyBios,(BBS_BBS_DEVICE_PATH*)Dp,0,0);
+}
+#endif
+
+EFI_STATUS BootEfi(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT16 Number, VOID *pOptions, UINT32 Size)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ Status=pBS->LoadImage(TRUE, TheImageHandle, Dp, NULL, 0, &Handle);
+ if (EFI_ERROR(Status)) return Status;
+ Status=pBS->HandleProtocol(Handle,&gEfiLoadedImageProtocolGuid,&Image);
+ if (!EFI_ERROR(Status) && Size)
+ {
+ Image->LoadOptionsSize = Size;
+ Image->LoadOptions = pOptions;
+ }
+ ReadyToBoot(Number);
+ return pBS->StartImage(Handle, NULL, NULL);
+}
+
+EFI_STATUS Boot(EFI_LOAD_OPTION *BootOption, UINT16 Number, UINTN Size)
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)
+ ( //skip the header
+ (UINT8*)(BootOption+1)
+ //skip the string
+ +(Wcslen((CHAR16*)(BootOption+1))+1)*sizeof(CHAR16)
+ );
+ if (Dp->Type!=BBS_DEVICE_PATH)
+ {
+ UINT8 *pOptions = (UINT8*)Dp+BootOption->FilePathListLength;
+ Status=BootEfi(Dp,Number,pOptions, (UINT32)((UINT8*)BootOption+Size-pOptions));
+ }
+#if CSM_SUPPORT
+ else
+ {
+ Status=BootLegacy(Dp,Number);
+ }
+#endif
+ return Status;
+}
+
+VOID RunDrivers(){
+ EFI_LOAD_OPTION *DriverOption = NULL; //buffer for DriverXXX variables
+ UINT16 *DriverOrder = NULL; //old(saved) Driver Order
+ UINTN DriverOrderSize = 0; //size of DriverOrder Variable
+ EFI_STATUS Status;
+ UINTN Size,i;
+ BOOLEAN ReconnectAll = FALSE;
+
+ //================== Init Driver Order buffers ========================//
+ Status = GetEfiVariable(L"DriverOrder", &EfiVariableGuid, NULL, &DriverOrderSize, &DriverOrder);
+ if (EFI_ERROR(Status)) return;
+ //===================================================================//
+ // Start drivers refered to by DriverXXXX //
+ //===================================================================//
+ for(i=0; i<DriverOrderSize/sizeof(UINT16); i++){
+ CHAR16 DriverStr[9];
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE Handle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ UINT32 SizeOfOptions;
+ UINT8 *Options;
+
+ // Get Driver Option
+ Swprintf(DriverStr,L"Driver%04X",DriverOrder[i]);
+ Status=GetEfiVariable(DriverStr, &EfiVariableGuid, NULL, &Size, &DriverOption);
+ if ( EFI_ERROR(Status)
+ || (DriverOption->Attributes & LOAD_OPTION_ACTIVE)==0
+ ) continue;
+
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL*)
+ ( //skip the header
+ (UINT8*)(DriverOption+1)
+ //skip the string
+ +(Wcslen((CHAR16*)(DriverOption+1))+1)*sizeof(CHAR16)
+ );
+ Status=pBS->LoadImage(
+ TRUE, TheImageHandle, DevicePath, NULL, 0, &Handle
+ );
+ if (EFI_ERROR(Status)) continue;
+ Status=pBS->HandleProtocol(
+ Handle,&gEfiLoadedImageProtocolGuid,&Image
+ );
+ Options = (UINT8*)DevicePath+DriverOption->FilePathListLength;
+ SizeOfOptions=(UINT32)((UINT8*)DriverOption+Size-Options);
+ if (!EFI_ERROR(Status)&& SizeOfOptions!=0){
+ Image->LoadOptionsSize = SizeOfOptions;
+ Image->LoadOptions = Options;
+ }
+ Status=pBS->StartImage(Handle, NULL, NULL);
+ if ( !EFI_ERROR(Status)
+ && (DriverOption->Attributes & LOAD_OPTION_FORCE_RECONNECT)!=0
+ ) ReconnectAll=TRUE;
+ }
+ pBS->FreePool(DriverOption);
+ pBS->FreePool(DriverOrder);
+ if (ReconnectAll){
+ DisconnectEverything();
+ ConnectEverything();
+ }
+}
+
+EFI_DEVICE_PATH_PROTOCOL* DiscoverPartition(
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+){
+ UINTN Count,i;
+ EFI_HANDLE *Handle;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *PartDevicePath=NULL;
+ HARDDRIVE_DEVICE_PATH* BootParitionDevicePath = (HARDDRIVE_DEVICE_PATH*)DevicePath;
+ //get list of available Block I/O devices
+ Status=pBS->LocateHandleBuffer(ByProtocol,&gEfiBlockIoProtocolGuid,NULL,&Count,&Handle);
+ if (EFI_ERROR(Status)) return NULL;
+
+ for(i=0;i<Count;i++){
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DEVICE_PATH_PROTOCOL *PartitionDevicePath;
+ HARDDRIVE_DEVICE_PATH* PartitionNode;
+ Status = pBS->HandleProtocol(Handle[i],&gEfiBlockIoProtocolGuid,&BlockIo);
+ if (EFI_ERROR(Status)) continue;
+ // if this is not partition, continue
+ if (!BlockIo->Media->LogicalPartition) continue;
+ Status = pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&PartitionDevicePath);
+ if (EFI_ERROR(Status)) continue;
+ // Get last node of the device path. It should be partition node
+ PartitionNode = (HARDDRIVE_DEVICE_PATH*)DPGetLastNode(PartitionDevicePath);
+ //Check if our partition matches Boot partition
+ if ( PartitionNode->Header.Type!=MEDIA_DEVICE_PATH
+ || PartitionNode->Header.SubType!=MEDIA_HARDDRIVE_DP
+ ) continue;
+ if ( PartitionNode->PartitionNumber==BootParitionDevicePath->PartitionNumber
+ && PartitionNode->SignatureType==BootParitionDevicePath->SignatureType
+ && !MemCmp(PartitionNode->Signature,BootParitionDevicePath->Signature,16)
+ ){
+ //Match found
+ PartDevicePath = PartitionDevicePath;
+ break;
+ }
+ }
+ pBS->FreePool(Handle);
+ return PartDevicePath;
+}
+
+EFI_STATUS FwLoadFile (
+ IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+){
+ EFI_GUID *FileGuid;
+ UINTN FvCount,i;
+ EFI_HANDLE *FvHandle;
+ EFI_STATUS Status;
+
+ if (!BufferSize || *BufferSize && !Buffer)
+ return EFI_INVALID_PARAMETER;
+ if (!FilePath || isEndNode(FilePath)){
+ if (BootPolicy){
+ if (DefaultAppFfsGuidPtr==NULL) return EFI_UNSUPPORTED;
+ else FileGuid = DefaultAppFfsGuidPtr;
+ }else{
+ return EFI_INVALID_PARAMETER;
+ }
+ }else{
+ if ( FilePath->Type!=MEDIA_DEVICE_PATH
+ || FilePath->SubType!=MEDIA_FV_FILEPATH_DP
+ ) return EFI_INVALID_PARAMETER;
+ FileGuid = &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)FilePath)->NameGuid;
+ }
+ //If Buffer is NULL, ReadSection will allocate the memory.
+ //That's not what we need.
+ //Initialize Buffer with some value.
+ //We don't care what value is that because *BufferSize is 0 anyway,
+ //so nothing will be copied into the buffer.
+ //We know that *BufferSize is always 0 for NULL buffer because we checked that
+ //at the beginning of the routine.
+ if (!Buffer) Buffer = (VOID*)1;
+ Status=pBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &FvCount, &FvHandle);
+ if (EFI_ERROR(Status)) return Status;
+ Status=EFI_NOT_FOUND;
+ for(i=0; i<FvCount; i++)
+ {
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 AuthStatus;
+ Status = pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ if (EFI_ERROR(Status)) continue;
+ Status = Fv->ReadSection(
+ Fv, FileGuid, EFI_SECTION_PE32,
+ 0, &Buffer, BufferSize, &AuthStatus
+ );
+ if (!EFI_ERROR(Status)){
+ if (Status==EFI_WARN_BUFFER_TOO_SMALL) Status=EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+ }
+ pBS->FreePool(FvHandle);
+ return Status;
+}
+
+VOID InstallFwLoadFile(){
+ EFI_HANDLE Handle=NULL;
+ pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiLoadFileProtocolGuid, &FwLoadFileInterface,
+ &gEfiDevicePathProtocolGuid, &FwLoadFileDp,
+ NULL
+ );
+}
+
+//----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SignalProtocolEvent
+//
+// Description: Internal function that installs/uninstall protocol
+// with a specified GUID and NULL interface.
+// Such protocols can be used as event signaling mechanism.
+//
+// Input: ProtocolGuid Pointer to the protocol GUID
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SignalProtocolEvent(IN EFI_GUID *ProtocolGuid){
+ EFI_HANDLE Handle = NULL;
+ pBS->InstallProtocolInterface (
+ &Handle, ProtocolGuid, EFI_NATIVE_INTERFACE,NULL
+ );
+ pBS->UninstallProtocolInterface (
+ Handle, ProtocolGuid, NULL
+ );
+}
+
+#ifdef EFI_DXE_PERFORMANCE
+VOID SavePerformanceData(IN EFI_EVENT Event, IN VOID *Context){
+ PERF_END (0, BDS_TOK, NULL, 0) ;
+ WriteBootToOsPerformanceData();
+}
+#endif
+
+VOID SaveFpdtDataOnLegacyBoot(IN EFI_EVENT Event, IN VOID *Context){
+ AmiFillFpdt (FillOsLoaderStartImageStart); // Fill OsLoaderStartImageStart field in FPDT
+}
+
+VOID SignalConnectDriversEvent(){
+ PROGRESS_CODE(DXE_BDS_CONNECT_DRIVERS);
+ SignalProtocolEvent(&BdsConnectDriversProtocolGuid);
+}
+
+VOID ConnectRootBridgeHandles(){
+ EFI_HANDLE *Handle;
+ UINTN NumberOfHandles;
+ EFI_STATUS Status;
+ UINTN i;
+
+ //Enumerate PCI Bus and Create handles for all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciRootBridgeIoProtocolGuid, NULL,
+ &NumberOfHandles, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<NumberOfHandles; i++)
+ pBS->ConnectController(Handle[i],NULL,NULL,FALSE);
+ pBS->FreePool(Handle);
+}
+
+VOID ReportConnectConOutProgressCode(){
+ PROGRESS_CODE(DXE_CON_OUT_CONNECT);
+}
+
+VOID ConnectVgaConOut(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+ EFI_DEVICE_PATH_PROTOCOL *OnBoard=NULL, *OffBoard=NULL;
+ UINT64 PciAttributes;
+
+ //Get a list of all PCI devices
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,&gEfiPciIoProtocolGuid, NULL, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINT8 PciClass;
+ Status=pBS->HandleProtocol(Handle[i],&gEfiPciIoProtocolGuid,&PciIo);
+ if (EFI_ERROR(Status)) continue;
+ Status=PciIo->Pci.Read(PciIo, EfiPciIoWidthUint8, 0xB, 1, &PciClass);
+ if (EFI_ERROR(Status)) continue;
+ if (PciClass!=PCI_CL_DISPLAY) continue;
+ Status=pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&Dp);
+ if (EFI_ERROR(Status)) continue;
+ //We found Display adapter
+ // Check if this is on-board device
+ //(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE is set).
+ Status = PciIo->Attributes(
+ PciIo, EfiPciIoAttributeOperationGet, 0, &PciAttributes
+ );
+ if ( !EFI_ERROR(Status)
+ && (PciAttributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE)
+ ) OnBoard = AddDevicePath(OnBoard,Dp);
+ else OffBoard = AddDevicePath(OffBoard,Dp);
+ }
+ pBS->FreePool(Handle);
+ //Offboard has a higher priority
+ OffBoard = AddDevicePath(OffBoard,OnBoard);
+ if (OffBoard)
+ {
+ ConnectDevicePath(OffBoard);
+ pBS->FreePool(OffBoard);
+ }
+}
+
+VOID ConnecConsoleVariable(CHAR16* ConVar){
+ EFI_DEVICE_PATH_PROTOCOL *ConPath=NULL;
+ UINTN Size = 0;
+
+ if (EFI_ERROR(
+ GetEfiVariable(ConVar, &EfiVariableGuid, NULL, &Size, &ConPath)
+ )) return;
+
+ //Connect all active console devices
+ ConnectDevicePath(ConPath);
+ pBS->FreePool(ConPath);
+}
+
+VOID InstallConsoleStartedProtocol(
+ CHAR16* ConDevVar, EFI_GUID* ProtocolGuid
+){
+ UINTN Size = 0;
+ VOID *Interface;
+
+ //Signal to Console Splitter that all console devices have been started
+ //if at least one console device exists (ConDev variable exists)
+ if (ConDevVar!=NULL && pRS->GetVariable(
+ ConDevVar, &EfiVariableGuid, NULL, &Size, NULL
+ ) == EFI_NOT_FOUND
+ ) return;
+ //if the protocol is already installed, return
+ if (!EFI_ERROR(pBS->LocateProtocol(ProtocolGuid, NULL, &Interface)))
+ return;
+ pBS->InstallProtocolInterface(
+ &TheImageHandle, ProtocolGuid, EFI_NATIVE_INTERFACE, NULL
+ );
+}
+
+VOID ConnectConOutVariable(){
+ ConnecConsoleVariable(L"ConOut");
+}
+
+VOID InstallConOutStartedProtocol(){
+ InstallConsoleStartedProtocol(L"ConOutDev", &ConOutStartedProtocolGuid);
+}
+
+VOID ReportConnectConInProgressCode(){
+ PROGRESS_CODE(DXE_CON_IN_CONNECT);
+}
+
+VOID ConnectPs2ConIn(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+
+ //Get a list of all PCI to ISA Bridges
+ Status = GetPciHandlesByClass(
+ PCI_CL_BRIDGE, PCI_CL_BRIDGE_SCL_ISA, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ EFI_DEVICE_PATH_PROTOCOL *Dp, *ChildDp;
+ ACPI_HID_DEVICE_PATH Ps2Kbd = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0x303),0
+ };
+ ACPI_HID_DEVICE_PATH Ps2Mouse = {
+ {ACPI_DEVICE_PATH,ACPI_DP,sizeof(ACPI_HID_DEVICE_PATH)},
+ EISA_PNP_ID(0xF03),0
+ };
+ Status=pBS->HandleProtocol(Handle[i],&gEfiDevicePathProtocolGuid,&Dp);
+ if (EFI_ERROR(Status)) continue;
+ pBS->ConnectController(Handle[i],NULL,NULL,FALSE);
+ ChildDp=DPAddNode(Dp, &Ps2Kbd.Header);
+ ConnectDevicePath(ChildDp);
+ pBS->FreePool(ChildDp);
+ ChildDp=DPAddNode(Dp, &Ps2Mouse.Header);
+ ConnectDevicePath(ChildDp);
+ pBS->FreePool(ChildDp);
+ LpcHandle = Handle[i];
+ LpcDevicePath = Dp;
+ }
+ pBS->FreePool(Handle);
+
+}
+
+VOID ConnectUsbConIn(){
+ EFI_STATUS Status;
+ EFI_HANDLE *Handle;
+ UINTN Number,i;
+ //Get a list of all USB Controllers
+ Status = GetPciHandlesByClass(
+ PCI_CL_SER_BUS, PCI_CL_SER_BUS_SCL_USB, &Number, &Handle
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<Number; i++)
+ {
+ pBS->ConnectController(Handle[i],NULL,NULL,TRUE);
+ }
+ pBS->FreePool(Handle);
+}
+
+VOID ConnectConInVariable(){
+ ConnecConsoleVariable(L"ConIn");
+}
+
+VOID InstallConInStartedProtocol(){
+ InstallConsoleStartedProtocol(L"ConInDev", &ConInStartedProtocolGuid);
+}
+
+VOID ConInAvailabilityBeep(){
+ LibReportStatusCode(EFI_PROGRESS_CODE, AMI_STATUS_CODE_BEEP_CLASS|1, 0, NULL, NULL);
+}
+
+VOID InitConVars()
+{
+ UINTN i;
+ UINTN Size = 0;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ConPath=NULL;
+
+ static CHAR16* ConVar[] = {L"ConOut", L"ConIn"};
+ static CHAR16* ConDev[] = {L"ConOutDev", L"ConInDev"};
+
+ // Install Console Stared Protocols
+ // ConSplitter will process notification by populating
+ // corresponding fields of the system table.
+ // At this point the protocol need to be installed
+ // even if no actual console devices are available
+ // to prevent problems on headless systems
+ // caused by NULL console pointers in the system table.
+ // The functions will not install the protocol if it has already been installed
+ InstallConsoleStartedProtocol(NULL, &ConOutStartedProtocolGuid);
+ InstallConsoleStartedProtocol(NULL, &ConInStartedProtocolGuid);
+
+ //Create non-existent ConVar variables for ConIn and ConOut
+ //ErrOut will be treated differently
+ for( i=0; i<2; i++){
+ if (EFI_ERROR(
+ GetEfiVariable(ConDev[i], &EfiVariableGuid, NULL, &Size, &ConPath)
+ )
+ ) continue;
+ //Set ConVar[i] equal to the ConDev[i]
+ pRS->SetVariable(
+ ConVar[i], &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ //Let's take care about ErrOut
+ Status = GetEfiVariable(
+ L"ErrOutDev", &EfiVariableGuid, NULL, &Size, &ConPath
+ );
+ if ( Status == EFI_NOT_FOUND ){
+ Status = GetEfiVariable(
+ L"ConOutDev", &EfiVariableGuid, NULL, &Size, &ConPath
+ );
+ if (!EFI_ERROR(Status))
+ //Set ConErrDev equal to the ConOutDev
+ pRS->SetVariable(
+ L"ErrOutDev", &EfiVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ if (!EFI_ERROR(Status)){
+ //Set ErrOut
+ pRS->SetVariable(
+ L"ErrOut", &EfiVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size, ConPath
+ );
+ }
+ if (ConPath) pBS->FreePool(ConPath);
+}
+
+#define IsRuntimeMemoryType(MemoryType) \
+ ((MemoryType) == EfiACPIReclaimMemory || \
+ (MemoryType) == EfiACPIMemoryNVS || \
+ (MemoryType) == EfiRuntimeServicesCode || \
+ (MemoryType) == EfiRuntimeServicesData || \
+ (MemoryType) == EfiReservedMemoryType )
+
+VOID SaveMemoryTypeInformation (
+ IN EFI_EVENT Event, IN VOID *Context
+){
+#ifdef EFI_DEBUG
+ CONST CHAR8* EfiMemTypeStr[] = {
+ "Reserved ",
+ "LoaderCode ",
+ "LoaderData ",
+ "BSCode ",
+ "BSData ",
+ "RSCode ",
+ "RSData ",
+ "Free ",
+ "Unusable ",
+ "ACPIReclaim",
+ "ACPINVS ",
+ "MMIO ",
+ "MMIOIOPort ",
+ "PalCode "
+ };
+ struct{
+ UINT32 Previous,Current,Next;
+ } MemoryInfoHistory[EfiMaxMemoryType];
+#endif
+ static EFI_GUID HobListGuid = HOB_LIST_GUID;
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *MemoryInformationHob;
+ EFI_MEMORY_TYPE_INFORMATION *MemoryTypeInformation = NULL;
+ UINTN MemoryTypeInformationSize = 0;
+ BOOLEAN IsFirstBoot = FALSE;
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
+ UINTN i, j;
+ BOOLEAN MemoryTypeInformationModified;
+ BOOLEAN RtMemoryQuotasIncreased = FALSE;
+ UINT32 Current, Next;
+
+ static BOOLEAN MemoryTypeInformationIsSaved = FALSE;
+
+ // Make sure the processing is performed only once.
+ // (we are registering callback on multiple events in RegisterMemoryTypeInformationUpdateCallback)
+ if (MemoryTypeInformationIsSaved){
+ pBS->CloseEvent(Event);
+ return;
+ }
+
+ // Get the Memory Type Information settings from Hob if they exist,
+ // PEI is responsible for getting them from variable and building a Hob to save them.
+ MemoryInformationHob = GetEfiConfigurationTable(pST, &HobListGuid);
+ if (MemoryInformationHob == NULL) return;
+ if (EFI_ERROR(
+ FindNextHobByGuid(&gEfiMemoryTypeInformationGuid, &MemoryInformationHob)
+ )) return;
+
+ Status = pRS->GetVariable(
+ L"PreviousMemoryTypeInformation", &gEfiMemoryTypeInformationGuid, NULL,
+ &MemoryTypeInformationSize, NULL
+ );
+ IsFirstBoot = Status==EFI_NOT_FOUND;
+
+ MemoryTypeInformation = (EFI_MEMORY_TYPE_INFORMATION*)(MemoryInformationHob+1);
+ MemoryTypeInformationSize = MemoryInformationHob->Header.HobLength
+ - sizeof (EFI_HOB_GUID_TYPE);
+ // Save memory information for the current boot.
+ // It will be used if next boot is S4 resume.
+ Status = pRS->SetVariable (
+ L"PreviousMemoryTypeInformation", &gEfiMemoryTypeInformationGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ MemoryTypeInformationSize, MemoryTypeInformation
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ // Retrieve the current memory usage statistics. If they are not found, then
+ // no adjustments can be made to the Memory Type Information variable.
+ CurrentMemoryTypeInformation = GetEfiConfigurationTable(
+ pST, &gEfiMemoryTypeInformationGuid
+ );
+ if (CurrentMemoryTypeInformation == NULL) return;
+ MemoryTypeInformationModified = FALSE;
+ TRACE((TRACE_DXE_CORE, "BDS.%s(%X)\n",
+ "SaveMemoryTypeInformation", SaveMemoryTypeInformation
+ ));
+ // Adjust the Memory Type Information for the next boot
+ for (i = 0; MemoryTypeInformation[i].Type != EfiMaxMemoryType; i++) {
+ Current = 0;
+ for (j = 0; CurrentMemoryTypeInformation[j].Type != EfiMaxMemoryType; j++) {
+ if (MemoryTypeInformation[i].Type == CurrentMemoryTypeInformation[j].Type) {
+ Current = CurrentMemoryTypeInformation[j].NumberOfPages;
+ break;
+ }
+ }
+
+ // Set next value to 125% of the current
+ Next = Current + (Current >> 2);
+#ifdef EFI_DEBUG
+ MemoryInfoHistory[i].Previous = MemoryTypeInformation[i].NumberOfPages;
+ MemoryInfoHistory[i].Current = Current;
+ MemoryInfoHistory[i].Next = (Next > MemoryTypeInformation[i].NumberOfPages) ? Next : MemoryTypeInformation[i].NumberOfPages;
+#endif
+ // We are never decreasing the memory type usage values.
+ // It would've been more fair to check for inequality (!=) here to
+ // keep memory type information consistent with the actual memory usage.
+ // We are not doing it to workaround UEFI Windows 7 and Windows 8 bug.
+ // Windows loader can't properly handle (it crashes)
+ // memory map changes that happen after OS load has been launched
+ // and before the ExitBootServices call.
+ // It's very difficult to predict how much memory will be used during
+ // the execution of the Windows loader because in certain cases Windows loader
+ // is pretty active. For example, it sometimes calls
+ // ConnectController for all the devices.
+ // By never decreasing the memory type usage values, we are avoiding the problem
+ // by always assuming the worst case scenario (the heaviest memory usage).
+ // The drawback is, we are stealing more memory than is actually used from the user.
+ if (Next > MemoryTypeInformation[i].NumberOfPages){
+ if ( IsRuntimeMemoryType(MemoryTypeInformation[i].Type) )
+ RtMemoryQuotasIncreased = TRUE;
+ MemoryTypeInformation[i].NumberOfPages = Next;
+ MemoryTypeInformationModified = TRUE;
+ }
+ }
+
+ // If any changes were made to the Memory Type Information settings,
+ // set the new variable value;
+ if ( MemoryTypeInformationModified ){
+ TRACE((TRACE_DXE_CORE, " Memory Previous Current Next \n"));
+ TRACE((TRACE_DXE_CORE, " Type Pages Pages Pages \n"));
+ TRACE((TRACE_DXE_CORE, "=========== ======== ======== ========\n"));
+ for (i = 0; MemoryTypeInformation[i].Type != EfiMaxMemoryType; i++) {
+ TRACE((
+ TRACE_DXE_CORE, "%s %8X %8X %8X\n",
+ EfiMemTypeStr[MemoryTypeInformation[i].Type],
+ MemoryInfoHistory[i].Previous,
+ MemoryInfoHistory[i].Current,
+ MemoryInfoHistory[i].Next
+ ));
+ }
+ Status = pRS->SetVariable(
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, &gEfiMemoryTypeInformationGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ MemoryTypeInformationSize, MemoryTypeInformation
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (IsFirstBoot && RtMemoryQuotasIncreased){
+ TRACE((
+ TRACE_DXE_CORE,
+ "Default RT memory quotas have been increased. Resetting the system...\n"
+ ));
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ pBS->CloseEvent(Event);
+ MemoryTypeInformationIsSaved = TRUE;
+}
+
+VOID RegisterMemoryTypeInformationUpdateCallback(){
+ EFI_EVENT Event;
+ VOID *Registration;
+
+ EFI_BOOT_MODE BootMode = GetBootMode();
+ if ( BootMode == BOOT_ON_S4_RESUME
+ || BootMode == BOOT_ON_FLASH_UPDATE
+ || BootMode == BOOT_IN_RECOVERY_MODE
+ ) return;
+
+ // We really want to get control.
+ // That's why we are registering callbacks for multiple boot events hoping that
+ // at least one of them will be triggered.
+ // If multiple events are signaled, only the first one is handled
+ RegisterProtocolCallback(
+ &BeforeBootProtocolGuid,
+ SaveMemoryTypeInformation,
+ NULL, &Event, &Registration
+ );
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SaveMemoryTypeInformation,
+ NULL, &Event, &Registration
+ );
+ CreateLegacyBootEvent(TPL_CALLBACK, &SaveMemoryTypeInformation, NULL, &Event);
+ pBS->CreateEvent(
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,TPL_CALLBACK,
+ &SaveMemoryTypeInformation, NULL, &Event
+ );
+}
+
+VOID CallTheDispatcher(){
+ DXE_SERVICES *pDxe;
+
+ if (EFI_ERROR(LibGetDxeSvcTbl(&pDxe)))
+ return;
+ if (pDxe) pDxe->Dispatch();
+}
+
+VOID SignalAllDriversConnectedEvent(){
+ SignalProtocolEvent(&BdsAllDriversConnectedProtocolGuid);
+}
+
+VOID HandoffToTse(){
+ AMI_POST_MANAGER_PROTOCOL *AmiPostMgr=NULL;
+
+ if (!EFI_ERROR(pBS->LocateProtocol(
+ &AmiPostMgrProtocolGuid, NULL, &AmiPostMgr
+ ))) AmiPostMgr->Handshake();
+
+}
+
+VOID BdsEntry (IN EFI_BDS_ARCH_PROTOCOL *This)
+{
+
+ UINTN i;
+
+ PERF_END(0, DXE_TOK, NULL, 0);
+ PERF_START(0, BDS_TOK, NULL, 0);
+ InitParts2(TheImageHandle, pST);
+ //Lang & LangCodes are initialized by Setup driver
+ InitSystemVariable(L"Timeout", sizeof(UINT16), &DefaultTimeout);
+
+{
+ EFI_EVENT Event;
+ VOID *Registration;
+#ifdef EFI_DXE_PERFORMANCE
+ RegisterProtocolCallback(
+ &BeforeBootProtocolGuid,
+ SavePerformanceData,
+ NULL, &Event, &Registration
+ );
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SavePerformanceData,
+ NULL, &Event, &Registration
+ );
+
+#endif
+ RegisterProtocolCallback(
+ &BeforeLegacyBootProtocolGuid,
+ SaveFpdtDataOnLegacyBoot,
+ NULL, &Event, &Registration
+ );
+
+}
+ pBS->LocateHandleBuffer(AllHandles, NULL, NULL, &NumberOfHandles, &RootHandles);
+
+ for(i=0; BdsControlFlowFunctions[i]!=NULL; i++){
+ TRACE((TRACE_DXE_CORE, "BDS.%s(%X)\n",
+ BdsControlFlowFunctionNames[i], BdsControlFlowFunctions[i]
+ ));
+ BdsControlFlowFunctions[i]();
+ }
+}
+
+// Deprecated Variable.
+// Use TheImageHandle instead.
+EFI_HANDLE ThisImageHandle = NULL;
+
+EFI_STATUS BdsInit (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_HANDLE Handle = NULL;
+ InitAmiLib(ImageHandle, SystemTable);
+ ThisImageHandle = ImageHandle;
+ return pBS->InstallProtocolInterface(&Handle, &gEfiBdsArchProtocolGuid, EFI_NATIVE_INTERFACE, &BDS);
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Bds.uni b/Core/CORE_DXE/Bds.uni
new file mode 100644
index 0000000..dd24315
--- /dev/null
+++ b/Core/CORE_DXE/Bds.uni
Binary files differ
diff --git a/Core/CORE_DXE/BdsBoard.c b/Core/CORE_DXE/BdsBoard.c
new file mode 100644
index 0000000..ea5ee36
--- /dev/null
+++ b/Core/CORE_DXE/BdsBoard.c
@@ -0,0 +1,1074 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BdsBoard.c 2 10/30/13 6:54a Ireneyang $
+//
+// $Revision: 2 $
+//
+// $Date: 10/30/13 6:54a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BdsBoard.c $
+//
+// 2 10/30/13 6:54a Ireneyang
+// - Fix Setup menu erroneously shows multiple instances of
+// the same bootable device for EIP139412
+//
+// 65 5/20/13 4:37p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Implement ORPHAN_BOOT_POLICY_KEEP for legacy groups
+// [Files] BootOptions.h BootOptions.c BdsBoard.c
+//
+// 64 5/24/12 3:24p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Graphics console tokens moved from BdsBoard.c into
+// Tokens.c
+// [Files] BdsBoard.c Tokens.c
+//
+// 1 8/25/12 4:39a Wesleychen
+// Update to rev.63 for EIP85762.
+//
+// 63 4/09/12 5:41p Artems
+// Implementation of NON_FW_BOOT_OPTION_HIDE functionality
+//
+// 62 11/01/11 1:41p Felixp
+// Definition of the BeforeLegacyBootProtocolGuid variable is added.
+//
+// 61 10/28/11 2:52p Artems
+// Moved function ConnectConsoles to FastBoot module
+//
+// 60 3/28/11 3:49p Felixp
+// Bug fix: Cloning of BOOT_OPTION_NAME_PREFIX_FUNCTION,
+// BOOT_OPTION_NAME_SUFFIX_FUNCTION, or
+// BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION caused an unknown
+// identifier error because
+// "extern" declaration for the cloned function was missing.
+//
+// 59 3/09/11 5:47p Artems
+// For ConnectPS2ConIn function added #ifdef from PS2Ctl_SUPPORT
+//
+// 58 2/25/11 12:30p Artems
+// EIP 53767 - Velocity boot time above 5 seconds. Added provision to skip
+// USB keyboard initialization
+//
+// 57 2/15/11 6:50p Artems
+//
+// 56 1/24/11 3:51p Pats
+// [TAG] - EIP 18488
+// [Category] - Enhancement
+// [Severity] - Normal
+// [Symptom] - PS2CTL: Need hooks for port swap, Keybaord mouse detect.
+// [RootCause] - Support may be needed for kbc controller or SIO with
+// different support from AMI KB-5.
+// [Solution] - Modified to allow external f AutodetectKbdMousePortsPtr()
+// function.
+// [Files] - BdsBaord.c, CORE_DXE.C, and in PS2CTL module - kbc.c,
+// ps2ctl.h, ps2ctl.sdl, and ps2main.c
+// NOTE: Implementation of this change requires changes to the PS2CTL
+// module.
+//
+// 55 11/18/10 3:33p Felixp
+// Clean up
+//
+// 54 11/17/10 4:45p Felixp
+// Minor bug fix in SetBootOptionPriorities
+//
+// 53 11/15/10 5:23p Felixp
+// Default values of the orphan policy macros are updated to
+// match with the setting of the corresponding SDL tokens.
+// ApplyOrphanBootOptionsPolicy renamed to ApplyOrphanBootOptionPolicy
+// Some debug messages are removed
+//
+// 52 10/07/10 1:35p Felixp
+// Make sure code compiles without CSM
+//
+// 51 10/07/10 1:21p Felixp
+// Support for BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION SDL token is
+// added.
+//
+// 50 10/01/10 8:11a Felixp
+// Boot option normalization is moved from PreProcessBootOptions
+// to a separate function NormalizeBootOptions.
+//
+// 49 9/29/10 9:19a Felixp
+// Enhancement(EIP 39464) : Implementation of the BdsEntry function is
+// changed.
+// The BdsEntry is now a dispatching function that calls a collection of
+// functions
+// formed by the BDS_CONTROL_FLOW eLink.
+//
+// 48 9/21/10 3:31p Felixp
+// Boot Option Infrastructure Improvements:
+// - NORMALIZE_BOOT_OPTIONS SDL token is replaced with
+// NORMALIZE_BOOT_OPTION_NAME and NORMALIZE_BOOT_OPTION_DEVICE_PATH
+// - MATCH_BOOT_OPTION_BY_LOCATION and MATCH_BOOT_OPTION_BY_DEVICE
+// SDL tokens and the supporting code are added.
+//
+// 47 9/02/10 11:47a Felixp
+//
+// 46 8/27/10 9:33a Felixp
+// Bug fix in the implementation of the eLink-based hooks.
+// Function headers added.
+//
+// 45 8/20/10 4:10p Felixp
+// Bug fin in LZMA support ( InstallLzmaDecompressProtocol was called too
+// late).
+//
+// 44 8/20/10 3:25p Felixp
+//
+// 43 8/20/10 3:12p Felixp
+// LZMA compression support
+//
+// 42 6/30/10 11:11a Felixp
+// Clean up
+//
+// 41 6/29/10 11:03p Felixp
+// New Boot Options Maintenance Infrastructure.
+// See AMI_Aptio_4.x_Boot_Options_Maintenance_Infrastructure_Porting_Guide
+// _NDA.doc for details.
+//
+// 40 5/07/10 6:03p Felixp
+// Improvement in CreateLegacyBootOption (EIP 38132): Protection against
+// BootOrder buffer overrun is added
+//
+// 39 4/22/10 10:44p Felixp
+// INSTALL_DUMMY_SECURITY_PROTOCOL SDL token is created.
+//
+// 38 2/24/10 8:23a Felixp
+//
+// 37 2/24/10 8:22a Felixp
+// IsFastBoot function removed (it is part of the FastBoot eModule).
+//
+// 36 2/03/10 3:40p Oleksiyy
+// Minor bug fix
+//
+// 35 2/02/10 5:46p Felixp
+// Fast Boot related code is removed from BDS. It is now part of the stand
+// alone FastBoot eModule.
+//
+// 34 10/28/09 12:23p Felixp
+// Minor improvement of the CreateDefaultBootOptions function: compiler
+// dependent code is removed(EIP 28577).
+//
+// 33 10/09/09 6:18p Felixp
+// UGA pixel type replaced with GOP type (UEFI 2.1 compatibility)
+//
+// 32 3/06/09 2:12p Felixp
+// Bug fix in IsFastBoot function (SetupData pointer was used after memory
+// had been freed).
+//
+// 31 1/16/09 3:00p Felixp
+// Iso9660FileSystemSupportEnabled global constant is added.
+// The constant is used to enable/disable ISO96660 partition support in
+// the partition driver.
+//
+// 30 11/03/08 5:21p Felixp
+// Do no re-create boot option for the built-in Shell, if Shell is not
+// included into the ROM
+//
+// 29 10/22/08 10:58a Felixp
+// Code to recreate deleted boot option for the built-in Shell is
+// added(EIP 15524).
+// Processing of the DriverOrder list is added.
+//
+// 28 10/21/08 5:56p Felixp
+// Multi-language support added to UEFI boot options implementation
+//
+// 27 10/17/08 3:47p Yakovlevs
+// Support for UEFI boot options added
+//
+// 26 9/30/08 11:08p Felixp
+// BeforeBootProtocolGuid is added
+//
+// 25 6/06/08 10:52a Felixp
+// Support for boot with minimal configuration added
+//
+// 24 11/08/07 4:52p Felixp
+// Code updated to compile and work without CSM.
+//
+// 23 10/26/07 2:38p Felixp
+// New FW based load file protocl is added.
+// This protocol is used to load FW based EFI applications such as built
+// in Shell.
+//
+// 22 10/19/07 9:20a Felixp
+// - SDL tokens are added in CORE_DXE.sdl to customize list of text
+// modes.
+// - SDL tokens are added in CORE_DXE.sdl to customize color values(EIP:
+// 9854).
+// BdsBoard updated with the graphic console tables
+//
+// 21 4/10/07 9:36a Felixp
+//
+// 19 2/12/07 1:46p Felixp
+// 1. Correct handling of disabled legacy BBS options
+// 2. Name of the legacy device removed from legacy boot option because it
+// is not needed (AMITSE does not use it)
+// 3. Clean up in ConnectDevicePath
+//
+// 18 1/31/07 11:57a Yakovlevs
+// Fixed EIP 8888. BIOS build w/o SIO_SUPPORT
+//
+// 17 12/29/06 2:39p Felixp
+//
+// 16 10/12/06 9:39a Felixp
+// Default boot order changed (from HD, CD to CD,HD)
+//
+// 15 6/08/06 7:12p Sivagarn
+// - Included function headers
+// - Updated file header
+// - Fixed EIP 7580 issue. Search for (EIP7580) for changes
+//
+// 14 3/13/06 1:44a Felixp
+//
+// 13 1/12/06 7:00p Felixp
+// Do nor create Shell boot option if Shell module is not in the project
+// or disabled.
+//
+// 12 12/12/05 9:46a Felixp
+// Default boot order changed.
+//
+// 11 11/08/05 4:07a Felixp
+// Setup notification GUIDs added
+//
+// 10 11/07/05 10:26a Felixp
+// 1. Support for Boot with Minimum Configuration
+// 2. Support for customization of default boot options and their order
+// 3. Support for Shell residing at any FV
+//
+// 7 5/24/05 2:52p Felixp
+// Boot menu moved to SetupEngine
+//
+// 2 4/08/05 3:02p Felixp
+// Improved responce for the QuietBoot
+//
+// 1 4/08/05 7:39a Felixp
+//
+//**********************************************************************
+
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+// Name: BdsBoard.C
+//
+// Description: This file contains BDS/CORE_DXE related OEM code. There are
+// variables defined in this file that might change for each
+// OEM project
+////---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+//---------------------------------------------------------------------------
+// Include Files
+//---------------------------------------------------------------------------
+#include "BootOptions.h"
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/Decompress.h>
+#include <CORE_DXEStrTokens.h>
+#include <Setup.h>
+#include <GenericSio.h>
+#include <BootOptioneLinks.h>
+#ifdef CSM_SUPPORT
+#include <Protocol/LegacyBiosExt.h>
+#endif
+
+//---------------------------------------------------------------------------
+// MACRO Constants
+//---------------------------------------------------------------------------
+#define _AND_ & // (EIP7580)+
+
+#ifndef FW_ORPHAN_BOOT_OPTIONS_POLICY
+#define FW_ORPHAN_BOOT_OPTIONS_POLICY ORPHAN_BOOT_OPTIONS_POLICY_DELETE
+#endif
+#ifndef NON_FW_ORPHAN_BOOT_OPTIONS_POLICY
+#define NON_FW_ORPHAN_BOOT_OPTIONS_POLICY ORPHAN_BOOT_OPTIONS_POLICY_KEEP
+#endif
+#ifndef ORPHAN_GROUP_HEADERS_POLICY
+#define ORPHAN_GROUP_HEADERS_POLICY ORPHAN_BOOT_OPTIONS_POLICY_DELETE
+#endif
+
+//---------------------------------------------------------------------------
+// Type definitions
+//---------------------------------------------------------------------------
+typedef enum{
+// BoTagLegacyXxx
+// BoTagUefiXxx
+// BoTagXxx
+ BoTagLegacyFloppy,
+ BoTagLegacyHardDisk,
+ BoTagLegacyCdrom,
+ BoTagLegacyPcmcia,
+ BoTagLegacyUsb,
+ BoTagLegacyEmbedNetwork,
+ BoTagLegacyBevDevice,
+ BoTagUefi,
+ BoTagEmbeddedShell
+} BOOT_OPTION_TAG;
+
+//---------------------------------------------------------------------------
+// Constant and Variables declarations
+//---------------------------------------------------------------------------
+const UINT16 DefaultTimeout = DEFAULT_BOOT_TIMEOUT;
+
+STRING_REF BbsDevTypeNameToken[] = {
+ STRING_TOKEN(STR_FD),
+ STRING_TOKEN(STR_HD),
+ STRING_TOKEN(STR_CD),
+ STRING_TOKEN(STR_PCMCIA),
+ STRING_TOKEN(STR_USB),
+ STRING_TOKEN(STR_NET),
+ STRING_TOKEN(STR_BEV),
+ STRING_TOKEN(STR_UNKNOWN)
+};
+
+struct{
+ UINT8 Type;
+ UINT8 SubType;
+ STRING_REF StrToken;
+} DpStrings[] = {
+ {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, STRING_TOKEN(STR_ATAPI)},
+ {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, STRING_TOKEN(STR_SCSI)},
+ {MESSAGING_DEVICE_PATH, MSG_USB_DP, STRING_TOKEN(STR_USB)},
+ {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, STRING_TOKEN(STR_NET)},
+ {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, STRING_TOKEN(STR_HD)},
+ {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, STRING_TOKEN(STR_CD)}
+};
+
+//these GUIDs are used by BDS.c
+EFI_GUID SetupEnterProtocolGuid=AMITSE_SETUP_ENTER_GUID;
+EFI_GUID SecondBootOptionProtocolGuid=AMITSE_AFTER_FIRST_BOOT_OPTION_GUID;
+EFI_GUID BeforeBootProtocolGuid = AMITSE_EVENT_BEFORE_BOOT_GUID;
+#ifndef EFI_AMI_LEGACYBOOT_PROTOCOL_GUID
+#define EFI_AMI_LEGACYBOOT_PROTOCOL_GUID \
+ {0x120d28aa, 0x6630, 0x46f0, 0x81, 0x57, 0xc0, 0xad, 0xc2, 0x38, 0x3b, 0xf5}
+#endif
+EFI_GUID BeforeLegacyBootProtocolGuid = EFI_AMI_LEGACYBOOT_PROTOCOL_GUID;
+EFI_GUID ShellFfsFileNameGuid = SHELL_GUID;
+#if Shell_SUPPORT
+EFI_GUID *DefaultAppFfsGuidPtr = &ShellFfsFileNameGuid;
+#else
+EFI_GUID *DefaultAppFfsGuidPtr = NULL;
+#endif
+
+EFI_GUID SetupVariableGuid = SETUP_GUID;
+
+struct {
+ VENDOR_DEVICE_PATH media;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ffs;
+ EFI_DEVICE_PATH_PROTOCOL end;
+} ShellDp = {
+ {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
+ sizeof(VENDOR_DEVICE_PATH)
+ },
+ AMI_MEDIA_DEVICE_PATH_GUID
+ },
+ {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_FV_FILEPATH_DP,
+ sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
+ },
+ SHELL_GUID
+ },
+ {
+ END_DEVICE_PATH, END_ENTIRE_SUBTYPE,
+ sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+const STRING_REF UnknownDeviceToken = STRING_TOKEN(STR_UNKNOWN);
+
+BOOT_OPTION_TAG LegacyBootOptionTags[] = {
+ BoTagLegacyFloppy,
+ BoTagLegacyHardDisk,
+ BoTagLegacyCdrom,
+ BoTagLegacyPcmcia,
+ BoTagLegacyUsb,
+ BoTagLegacyEmbedNetwork,
+ BoTagLegacyBevDevice,
+ UNASSIGNED_HIGHEST_TAG
+};
+
+BOOT_OPTION_TAG BootOptionTagPriorities[] = {
+ BOOT_OPTION_TAG_PRIORITIES,
+ UNASSIGNED_HIGHEST_TAG
+};
+
+BOOLEAN NormalizeBootOptionName = NORMALIZE_BOOT_OPTION_NAME;
+BOOLEAN NormalizeBootOptionDevicePath = NORMALIZE_BOOT_OPTION_DEVICE_PATH;
+
+//---------------------------------------------------------------------------
+// External variables
+//---------------------------------------------------------------------------
+extern EFI_GUID EfiVariableGuid;
+
+#if SIO_SUPPORT // (EIP8888)+
+extern SPIO_LIST_ITEM SIO_DEVICE_LIST EndOfList; // (EIP7580)+
+#endif // (EIP8888)-
+//---------------------------------------------------------------------------
+// Variables
+//---------------------------------------------------------------------------
+
+#if SIO_SUPPORT // (EIP8888)+
+SPIO_LIST_ITEM *gSpioList[] = {SIO_DEVICE_PTR_LIST NULL}; // (EIP7580)+
+#endif // (EIP8888)-
+
+//---------------------------------------------------------------------------
+// Function Prototypes
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Function Implementations
+//---------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DevicePathNodeToStrRef
+//
+// Description: This function converts node from the device path to a string.
+// Once the whole device path is converted the string is used as
+// as a boot opton name.
+// This function is only used is component name protocol does not report device name.
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *Dp - pointer to the device path node
+//
+// Output: STRING_REF - string token (-1, if the string token is not available)
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+STRING_REF DevicePathNodeToStrRef(EFI_DEVICE_PATH_PROTOCOL *Dp){
+ UINTN i;
+ //Built in Shell is a special case
+ if ( NODE_LENGTH(Dp)==NODE_LENGTH(&ShellDp.media.Header)
+ && MemCmp(Dp,&ShellDp.media.Header,NODE_LENGTH(Dp))==0
+ ) return STRING_TOKEN(STR_SHELL);
+ //BBS device path is another special case
+#ifdef CSM_SUPPORT
+ if ( Dp->Type==BBS_DEVICE_PATH ){
+ return BbsDevTypeNameToken[BBS_DEVICE_TYPE_TO_INDEX(((BBS_BBS_DEVICE_PATH*)Dp)->DeviceType)];
+ }
+#endif
+ for (i=0; i < sizeof(DpStrings)/sizeof(DpStrings[0]); i++){
+ if ((Dp->Type==DpStrings[i].Type) && (Dp->SubType==DpStrings[i].SubType)){
+ return DpStrings[i].StrToken;
+ }
+ }//for i
+
+ return INVALID_STR_TOKEN;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetBbsEntryDeviceTypeDefault
+//
+// Description: Using the passed BBS_TABLE entry pointer, determine the device
+// type of the associated device
+//
+// Input: BBS_TABLE *BbsEntry - pointer to a BBS_TABLE entry
+//
+// Output: UINT16 - device type of the BBS entry, see LegacyBios.h for actual values
+// BBS_FLOPPY
+// BBS_HARDDISK
+// BBS_CDROM
+// BBS_PCMCIA
+// BBS_USB
+// BBS_EMBED_NETWORK
+// BBS_BEV_DEVICE
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 GetBbsEntryDeviceTypeDefault(BBS_TABLE *BbsEntry){
+#ifdef CSM_SUPPORT
+ UINT16 DeviceType = BbsEntry->DeviceType;
+#if BBS_USB_DEVICE_TYPE_SUPPORT
+ if ( BbsEntry->Class == PCI_CL_SER_BUS
+ && BbsEntry->SubClass == PCI_CL_SER_BUS_SCL_USB
+ ) return BBS_USB;
+#endif
+#if BBS_NETWORK_DEVICE_TYPE_SUPPORT
+ if ( BbsEntry->Class == PCI_CL_NETWORK
+ && BbsEntry->DeviceType == BBS_BEV_DEVICE
+ ) return BBS_EMBED_NETWORK;
+#endif
+ return DeviceType;
+#else
+ return 0;
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetLegacyDevOrderType
+//
+// Description: Using the passed BOOT_OPTION structure, which should correspond to
+// a legacy device entry, determine the device type
+//
+// Input: BOOT_OPTION *Option - pointer to the BOOT_OPTION structure for the
+// device in question
+//
+// Output: UINT16 - device type of the BOOT_OPTION item, see LegacyBios.h for actual values
+// BBS_FLOPPY
+// BBS_HARDDISK
+// BBS_CDROM
+// BBS_PCMCIA
+// BBS_USB
+// BBS_EMBED_NETWORK
+// BBS_BEV_DEVICE
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 GetLegacyDevOrderType(BOOT_OPTION *Option){
+ return ((BBS_BBS_DEVICE_PATH*)Option->FilePathList)->DeviceType;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindTagPriority
+//
+// Description: For the passed Tag entry, return the correct boot priority based on
+// the BootOptionTagPriorities global variable that is filled out
+// based on the SDL Token BOOT_OPTION_TAG_PRIORITIES.
+//
+// Input: UINT16 Tag - one of the following items of the BOOT_OPTION_TAG enum:
+// BoTagLegacyFloppy
+// BoTagLegacyHardDisk
+// BoTagLegacyCdrom
+// BoTagLegacyPcmcia
+// BoTagLegacyUsb
+// BoTagLegacyEmbedNetwork
+// BoTagLegacyBevDevice
+// BoTagUefi
+// BoTagEmbeddedShell
+//
+// Output: The index of this item in the BootOptionTagPriorities structure, which
+// also corresponds to the boot priority that should be assigned to this
+// class of device
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 FindTagPriority(UINT16 Tag){
+ UINT32 i;
+ for(i=0; BootOptionTagPriorities[i]!=UNASSIGNED_HIGHEST_TAG; i++)
+ if (Tag==BootOptionTagPriorities[i]) return i;
+ return UNASSIGNED_HIGHEST_TAG;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsShellBootOption
+//
+// Description: Determine if the passed BOOT_OPTION is the built in EFI Shell
+//
+// Input: BOOT_OPTION *Option - the boot option in question
+//
+// Output: BOOLEAN - TRUE - this boot option represent the built in EFI Shell
+// FALSE - this is not the built in EFI Shell
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsShellBootOption(BOOT_OPTION *Option){
+ EFI_DEVICE_PATH_PROTOCOL *Dp = Option->FilePathList;
+
+ if (Dp==NULL) return FALSE;
+ if ( NODE_LENGTH(Dp)==NODE_LENGTH(&ShellDp.media.Header)
+ && MemCmp(Dp,&ShellDp.media.Header,NODE_LENGTH(Dp))==0
+ ) return TRUE;
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetBootOptionTags
+//
+// Description: Go through the entire boot option list and Apply priorities for
+// each entry in the list.
+//
+// Input: DLIST *BootOptionList - the entire Boot Option List
+//
+// Output: none
+//
+// Note: To change boot order priorities, do not modify this function,
+// modify the SDL Token BootOptionTagPriorities.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetBootOptionTags(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+ UINT32 UefiBootOptionsInc = 0x100;
+
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ UINT32 TagPriority;
+ UINT32 BaseTag = UNASSIGNED_HIGHEST_TAG;
+#ifdef CSM_SUPPORT
+ if (IsLegacyBootOption(Option)){
+ UINT16 DeviceType;
+ DeviceType = ((BBS_BBS_DEVICE_PATH*)Option->FilePathList)->DeviceType;
+ BaseTag = LegacyBootOptionTags[BBS_DEVICE_TYPE_TO_INDEX(DeviceType)];
+ }else
+#endif
+ if (IsShellBootOption(Option)) BaseTag = BoTagEmbeddedShell;
+ else BaseTag = BoTagUefi;
+ if (BaseTag == UNASSIGNED_HIGHEST_TAG) continue;
+ TagPriority = FindTagPriority(BaseTag);
+ //UEFI boot options must have unique tags, otherwise then will be groupped when
+ //GROUP_BOOT_OPTIONS_BY_TAG tokens is enabled
+ if (BaseTag == BoTagUefi) BaseTag += UefiBootOptionsInc++;
+ Option->Tag = BootOptionTag(BaseTag, TagPriority);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateGroupHeader
+//
+// Description: Create a Group Header Entry for the passed BOOT_OPTION and add the
+// group header to the master boot options list
+//
+// Input: DLIST *BootOptionList - the master boot options list to add the newly
+// created group item
+// BOOT_OPTION *FirstGroupOption - the boot option which needs linked to a
+// group item
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CreateGroupHeader(DLIST *BootOptionList, BOOT_OPTION *FirstGroupOption){
+#ifdef CSM_SUPPORT
+ static struct {
+ BBS_BBS_DEVICE_PATH bbs;
+ EFI_DEVICE_PATH_PROTOCOL end;
+ } BbsDpTemplate = {
+ {
+ {BBS_DEVICE_PATH,BBS_BBS_DP,sizeof(BBS_BBS_DEVICE_PATH)},
+ BBS_HARDDISK,0,0
+ },
+ {END_DEVICE_PATH,END_ENTIRE_SUBTYPE,sizeof(EFI_DEVICE_PATH_PROTOCOL)}
+ };
+
+ BOOT_OPTION *Option;
+
+ if (!IsLegacyBootOption(FirstGroupOption)) return;
+ Option = CreateBootOption(BootOptionList);
+ Option->BootOptionNumber = FirstGroupOption->BootOptionNumber;
+ Option->Priority = FirstGroupOption->Priority;
+ Option->Tag = FirstGroupOption->Tag;
+ Option->FwBootOption = TRUE;
+ Option->GroupHeader = TRUE;
+ BbsDpTemplate.bbs.DeviceType=GetBbsEntryDeviceType(FirstGroupOption->BbsEntry);
+ Option->FilePathList = DPCopy(&BbsDpTemplate.bbs.Header);
+ Option->FilePathListLength = DPLength(Option->FilePathList);
+ ConstructBootOptionName(Option);
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetBootOptionPriorities
+//
+// Description: Go through the boot option list and set the priorities of each
+// group of devices
+//
+// Input: DLIST *BootOptionList - the master list of boot options
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetBootOptionPriorities(){
+ DLINK *Link;
+ UINT16 PreviousBootOptionNumber = INVALID_BOOT_OPTION_NUMBER;
+ UINT32 PreviousTag = UNASSIGNED_HIGHEST_TAG;
+ UINT32 PreviousPriority=0;
+ BOOT_OPTION *Option;
+ UINT16 NextOptionNumber;
+
+ //Detect first unused boot option number
+ NextOptionNumber = 0;
+ if (!DListEmpty(BootOptionList)){
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if ( Option->BootOptionNumber != INVALID_BOOT_OPTION_NUMBER
+ && Option->BootOptionNumber > NextOptionNumber
+ ) NextOptionNumber = Option->BootOptionNumber;
+ }
+ NextOptionNumber++;
+ }
+
+ SortList(BootOptionList, CompareTagThenPriority);
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+#if GROUP_BOOT_OPTIONS_BY_TAG
+ if (Option->BootOptionNumber==INVALID_BOOT_OPTION_NUMBER){
+ if ( PreviousTag != Option->Tag
+ || Option->Tag==UNASSIGNED_LOWEST_TAG
+ || Option->Tag==UNASSIGNED_HIGHEST_TAG
+ ) PreviousBootOptionNumber=NextOptionNumber++;
+ Option->BootOptionNumber=PreviousBootOptionNumber;
+ Option->Priority=++PreviousPriority;
+ }else{
+ PreviousBootOptionNumber = Option->BootOptionNumber;
+ PreviousPriority = Option->Priority;
+ }
+ PreviousTag = Option->Tag;
+#else
+ if (Option->BootOptionNumber==INVALID_BOOT_OPTION_NUMBER){
+ Option->BootOptionNumber=(NextOptionNumber)++;
+ Option->Priority=++PreviousPriority;
+ }else{
+ PreviousPriority = Option->Priority;
+ }
+#endif
+ }
+ DUMP_BOOT_OPTION_LIST(BootOptionList,"After Setting Priorities");
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateGroupHeaders
+//
+// Description: Go throuhg the the boot option list and
+//
+// Input:
+//
+// Output:
+//
+// Note: This function assums that the BootOptionList is already sorted by tag and
+// then by priority. failure to adhere to those assumptions will cause
+// undesired behavoir
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CreateGroupHeaders(DLIST *BootOptionList){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+ UINT32 PreviousTag = UNASSIGNED_LOWEST_TAG;
+
+ //PRECONDITION: Boot Option List is sorted by tag then by priority
+
+ DUMP_BOOT_OPTION_LIST(BootOptionList,"Before Adding Group Headers");
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if (PreviousTag == Option->Tag) continue;
+ PreviousTag = Option->Tag;
+ if ( Option->Tag==UNASSIGNED_LOWEST_TAG
+ || Option->Tag==UNASSIGNED_HIGHEST_TAG
+ ) continue;
+ if (!Option->GroupHeader) CreateGroupHeader(BootOptionList,Option);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ApplyOrphanBootOptionPolicy
+//
+// Description: Apply the correct policy to the passed orphaned boot iptions
+//
+// Input: DLIST *BootOptionList - the master boot option list
+// BOOT_OPTION *Option - The orphaned boot option
+// UINTN Policy - the policy to follow, valid values are
+// ORPHAN_BOOT_OPTIONS_POLICY_DELETE
+// ORPHAN_BOOT_OPTIONS_POLICY_DISABLE
+// ORPHAN_BOOT_OPTIONS_POLICY_KEEP
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ApplyOrphanBootOptionPolicy(
+ DLIST *BootOptionList, BOOT_OPTION *Option, const int Policy
+){
+ if (Policy==ORPHAN_BOOT_OPTIONS_POLICY_DELETE){
+ if (Option->BootOptionNumber!=INVALID_BOOT_OPTION_NUMBER){
+ CHAR16 BootStr[9];
+ Swprintf(BootStr,L"Boot%04X",Option->BootOptionNumber);
+ pRS->SetVariable(
+ BootStr, &EfiVariableGuid, 0, 0, NULL
+ );
+ }
+ DeleteBootOption(BootOptionList, Option);
+ }else if (Policy==ORPHAN_BOOT_OPTIONS_POLICY_DISABLE){
+ Option->Attributes &= ~LOAD_OPTION_ACTIVE;
+ }else if (Policy==ORPHAN_BOOT_OPTIONS_POLICY_HIDE){
+ if(!IsLegacyBootOption(Option) || Option->GroupHeader)
+ Option->Attributes |= LOAD_OPTION_HIDDEN;
+ MaskFilePathList(Option);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PreProcessBootOptions
+//
+// Description: Attempts to find stale boot options in the master boot option
+// list, and apply the specified policy to them.
+//
+// Policy is based on SDL tokens: FW_ORPHAN_BOOT_OPTIONS_POLICY and
+// NON_FW_ORPHAN_BOOT_OPTIONS_POLICY
+//
+// Input: DLIST *BootOptionList - master boot option list
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PreProcessBootOptions(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+
+ // Process boot options not associated with the particular boot device.
+ // We can't process group headers just yet because groups that
+ // are non-empty now, can become empty at the end of this loop
+ // once their orphan members are deleted.
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ //skip group headers for now; we'll process them later
+ //in the PostProcessBootOptions
+ if (Option->GroupHeader || IsBootOptionWithDevice(Option))
+ continue;
+ if (Option->FwBootOption)
+ ApplyOrphanBootOptionPolicy(
+ BootOptionList, Option, FW_ORPHAN_BOOT_OPTIONS_POLICY
+ );
+ else
+ ApplyOrphanBootOptionPolicy(
+ BootOptionList, Option, NON_FW_ORPHAN_BOOT_OPTIONS_POLICY
+ );
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PostProcessBootOptions
+//
+// Description: Go through the master boot option list and apply orphan boot option
+// policy to the boot option groups
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PostProcessBootOptions(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+
+ SortList(BootOptionList, CompareTagThenPriority);
+ //Now we are ready for the processing of orphan group headers.
+ //process empty groups ( groups with just the header)
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if (!Option->GroupHeader) continue;
+ if (IsGroupOrphan(Option))
+ ApplyOrphanBootOptionPolicy(BootOptionList, Option, ORPHAN_GROUP_HEADERS_POLICY);
+ }
+
+#if GROUP_BOOT_OPTIONS_BY_TAG
+ CreateGroupHeaders(BootOptionList);
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNamePrefixDefault
+//
+// Description: Based on the passed boot option, determine if a prefix
+// needs prepended to the front of the boot option name. If return
+// value is non-zero, then the returned number of CHAR16s from the
+// Name buffer should prepended to the front of the boot option name
+//
+// Input: BOOT_OPTION *Option - boot option in question
+// CHAR16 *Name - pointer to the buffer in which to return the prefix
+// UINTN NameSize - size of the buffer being passed
+//
+// Output: UINTN - size of the string being returned
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNamePrefixDefault(BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize){
+ if (IsLegacyBootOption(Option)) return 0;
+ //TODO: use string token
+ return Swprintf(Name, L"UEFI: ");
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameSuffixDefault
+//
+// Description: Based on the passed boot option, determine if anything needs appended
+// to the boot option name string. If return value is not zero, then the
+// returned number of characers should be appended to the end of the name
+// string buffer.
+//
+// Input: BOOT_OPTION *Option - the boot option in question
+// CHAR16 *Name - pointer to the buffer to returne the append string
+// UINTN NameSize - the size of the buffer being passed
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNameSuffixDefault(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ return 0;
+}
+
+extern DEVICE_PATH_TO_DEVICE_MATCH_TEST BOOT_OPTION_DP_MATCHING_FUNCTIONS EndOfDpMatchingFunctions;
+DEVICE_PATH_TO_DEVICE_MATCH_TEST *DpMatchingFunction[] = {
+ BOOT_OPTION_DP_MATCHING_FUNCTIONS NULL
+};
+
+extern BOOT_OPTION_TO_DEVICE_MATCH_TEST BOOT_OPTION_MATCHING_FUNCTIONS EndOfMatchingFunctions;
+BOOT_OPTION_TO_DEVICE_MATCH_TEST *MatchingFunction[] = {
+ BOOT_OPTION_MATCHING_FUNCTIONS NULL
+};
+
+extern FILTER_BOOT_DEVICE_TEST BOOT_OPTION_BOOT_DEVICE_FILTERING_FUNCTIONS EndOfFilteringFunctions;
+FILTER_BOOT_DEVICE_TEST *FilteringFunction[] = {
+ BOOT_OPTION_BOOT_DEVICE_FILTERING_FUNCTIONS NULL
+};
+
+extern CONSTRUCT_BOOT_OPTION_NAME BOOT_OPTION_BUILD_NAME_FUNCTIONS EndOfBuildNameFunctions;
+CONSTRUCT_BOOT_OPTION_NAME *BuildNameFunctions[] = {
+ BOOT_OPTION_BUILD_NAME_FUNCTIONS NULL
+};
+
+extern BUILD_BOOT_OPTION_FILE_PATH_LIST BOOT_OPTION_BUILD_FILE_PATH_FUNCTIONS EndOfBuildFilePathFunctions;
+BUILD_BOOT_OPTION_FILE_PATH_LIST *BuildFilePathFunctions[] = {
+ BOOT_OPTION_BUILD_FILE_PATH_FUNCTIONS NULL
+};
+
+extern CONSTRUCT_BOOT_OPTION_NAME BOOT_OPTION_NAME_PREFIX_FUNCTION;
+CONSTRUCT_BOOT_OPTION_NAME *ConstructBootOptionNamePrefix = BOOT_OPTION_NAME_PREFIX_FUNCTION;
+
+extern CONSTRUCT_BOOT_OPTION_NAME BOOT_OPTION_NAME_SUFFIX_FUNCTION;
+CONSTRUCT_BOOT_OPTION_NAME *ConstructBootOptionNameSuffix = BOOT_OPTION_NAME_SUFFIX_FUNCTION;
+
+#ifndef BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION
+#define BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION GetBbsEntryDeviceTypeDefault
+#endif
+extern GET_BBS_ENTRY_DEVICE_TYPE BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION;
+GET_BBS_ENTRY_DEVICE_TYPE *GetBbsEntryDeviceType = BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION;
+
+#if FAST_BOOT_SUPPORT
+VOID FastBoot();
+BOOLEAN IsFastBoot();
+
+VOID FastBootHook(){
+ if(IsFastBoot()) FastBoot();
+}
+#endif
+
+#if CAPSULE_SUPPORT
+EFI_STATUS CapsuleDispatch(IN DXE_SERVICES *DxeServices);
+VOID CapsuleHook(){
+ DXE_SERVICES *pDxe;
+
+ if (EFI_ERROR(LibGetDxeSvcTbl(&pDxe)))
+ return;
+ // Process capsule
+ CapsuleDispatch(pDxe);
+}
+#endif
+//==========================================================
+//Graphic Console Tables
+//==========================================================
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL ColorArray[] = {
+ { GC_COLOR_BLACK , 0}, // case EFI_BLACK: // case EFI_BACKGROUND_BLACK >> 4
+ { GC_COLOR_BLUE , 0}, // case EFI_BLUE : // case EFI_BACKGROUND_BLUE >> 4
+ { GC_COLOR_GREEN , 0}, // case EFI_GREEN : // case EFI_BACKGROUND_GREEN >> 4
+ { GC_COLOR_CYAN , 0}, // case EFI_CYAN : // case EFI_BACKGROUND_CYAN >> 4
+ { GC_COLOR_RED , 0}, // case EFI_RED : // case EFI_BACKGROUND_RED >> 4
+ { GC_COLOR_MAGENTA , 0}, // case EFI_MAGENTA : // case EFI_BACKGROUND_MAGENTA >> 4
+ { GC_COLOR_BROWN , 0}, // case EFI_BROWN : // case EFI_BACKGROUND_BROWN >> 4
+ { GC_COLOR_LIGHTGRAY , 0}, // case EFI_LIGHTGRAY : // case EFI_BACKGROUND_LIGHTGRAY >> 4
+ { GC_COLOR_DARKGRAY , 0}, // case EFI_DARKGRAY :
+ { GC_COLOR_LIGHTBLUE , 0}, // case EFI_LIGHTBLUE :
+ { GC_COLOR_LIGHTGREEN , 0}, // case EFI_LIGHTGREEN :
+ { GC_COLOR_LIGHTCYAN , 0}, // case EFI_LIGHTCYAN :
+ { GC_COLOR_LIGHTRED , 0}, // case EFI_LIGHTRED :
+ { GC_COLOR_LIGHTMAGENTA, 0}, // case EFI_LIGHTMAGENTA :
+ { GC_COLOR_YELLOW , 0}, // case EFI_YELLOW :
+ { GC_COLOR_WHITE , 0} // case EFI_WHITE :
+};
+
+const BOOLEAN Iso9660FileSystemSupportEnabled =
+#ifdef FsIso9660_SUPPORT
+ (FsIso9660_SUPPORT==1)
+#else
+ FALSE
+#endif
+ ;
+
+BOOLEAN const InstallDummySecurityProtocol = INSTALL_DUMMY_SECURITY_PROTOCOL;
+
+//==========================================================
+// LZMA Compression Support
+//==========================================================
+#if LZMA_SUPPORT
+
+//LZMA Decompress protocol
+#define EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL_GUID \
+ { 0x9a44198e, 0xa4a2, 0x44e6, 0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f }
+
+EFI_STATUS LzmaDecomprGetInfo (
+ IN VOID *This,
+ IN VOID *Source, IN UINT32 SourceSize,
+ OUT UINT32 *DestinationSize, OUT UINT32 *ScratchSize
+){
+ return LzmaGetInfo(Source,SourceSize,DestinationSize,ScratchSize);
+}
+
+EFI_STATUS LzmaDecomprDecompress (
+ IN VOID *This,
+ IN VOID* Source, IN UINT32 SourceSize,
+ IN OUT VOID* Destination, IN UINT32 DestinationSize,
+ IN OUT VOID* Scratch, IN UINT32 ScratchSize
+){
+ return LzmaDecompress(Source,SourceSize,Destination,DestinationSize,Scratch,ScratchSize);
+}
+
+VOID InstallLzmaDecompressProtocol(
+ IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable
+){
+static const EFI_DECOMPRESS_PROTOCOL LzmaDecompressInterface = {
+ &LzmaDecomprGetInfo, &LzmaDecomprDecompress
+};
+static const EFI_GUID CustomizedDecompressProtocolGuid = EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL_GUID;
+ EFI_HANDLE Handle = NULL;
+ SystemTable->BootServices->InstallProtocolInterface(
+ &Handle,(EFI_GUID*)&CustomizedDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE, (VOID*)&LzmaDecompressInterface
+ );
+}
+#endif
+
+extern BDS_CONTROL_FLOW_FUNCTION BDS_CONTROL_FLOW EndOfBdsControlFlowFunctions;
+BDS_CONTROL_FLOW_FUNCTION *BdsControlFlowFunctions[] = {
+ BDS_CONTROL_FLOW NULL
+};
+CHAR8 *BdsControlFlowFunctionNames[] = {
+ BDS_CONTROL_FLOW_NAMES NULL
+};
+
+VOID* AutodetectKbdMousePortsPtr=
+#if KBC_AUTODETECT_PORTS_FUNCTION
+ KBC_AUTODETECT_PORTS_FUNCTION
+#else
+ NULL
+#endif
+ ;
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/BootOptions.c b/Core/CORE_DXE/BootOptions.c
new file mode 100644
index 0000000..8cbe3b7
--- /dev/null
+++ b/Core/CORE_DXE/BootOptions.c
@@ -0,0 +1,2842 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BootOptions.c 7 7/08/15 4:30a Chienhsieh $
+//
+// $Revision: 7 $
+//
+// $Date: 7/08/15 4:30a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/BootOptions.c $
+//
+// 7 7/08/15 4:30a Chienhsieh
+// [EIP210170] Improved BootOption DevicePath match algorithm.
+//
+// 6 7/15/14 9:55p Chienhsieh
+// Update to rev.39 for EIP172950, Core updates for UEFI Variable
+// Technical Advisory implement.
+//
+// 39 6/03/14 5:11p Artems
+// [TAG] EIP166565
+// [Category] Improvement
+// [Description] Runtime attribute for LegacyDevOrder variable is
+// modified depending on
+// token value, to support SCE tool
+// [Files] BootOptions.c
+//
+// 38 5/12/14 5:12p Artems
+// [TAG] EIP166565
+// [Category] Improvement
+// [Description] Variables LegacyDevOrder and OldLegacyDevOrder removed
+// runtime access attribute
+// [Files] BootOptions.c
+//
+// 5 10/30/13 6:53a Ireneyang
+// - Fix Setup menu erroneously shows multiple instances of
+// the same bootable device for EIP139412
+//
+// 36 6/21/13 2:54p Felixp
+// Bug fix(EIP 124559):
+// Symptom: When MATCH_BOOT_OPTION_BY_LOCATION was zero, off-board
+// legacy mass storage device
+// was mistakenly matched with on-board legacy boot options.
+// Root cause: DeviceTypeDevicePathTest was matching unrelated device
+// paths.
+// Solution: DeviceTypeDevicePathTest function is updated to return
+// FALSE (no-match) when
+// device interface type is unknown.
+// MatchBootOptionsToDevices is updated disable multiple boot option
+// matching for legacy devices.
+// Legacy device can't be matched with more than one boot option.
+// Files: BootOptions.c
+//
+// 35 5/20/13 4:33p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Implement ORPHAN_BOOT_POLICY_KEEP for legacy groups
+// [Files] BootOptions.h BootOptions.c BdsBoard.c
+//
+// 4 9/17/13 10:11p Thomaschen
+// Add EIP 134220 solution to fix boot option doesn't change
+// in special test step.
+//
+// 34 4/26/13 2:32p Felixp
+// [TAG] EIP109955
+// [Category] Improvement
+// [Description] Support USB device identification by serial number.
+//
+// 33 2/18/13 10:54a Felixp
+// Minor improvements:
+// - ConstructBootOptionName: unused variable is removed.
+// - BuildNameFilePath: check for out-of-memory condiftion.
+//
+// 32 2/18/13 10:52a Felixp
+// Improvement(EIP 115148): ReadBootOptions is updated to delete
+// ill-formed boot option variables.
+//
+// 31 2/07/13 2:18p Artems
+// [TAG] EIP111307
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] After insert two floppies into system and change Boot Mode
+// from ''UEFI'' to ''Legacy'' in BIOS setup utility, check it will show
+// two Floppy Drive BBS Priorites in BIOS Setup Utility
+// [RootCause] UEFI boot option was mistakingly matched to legacy boot
+// device
+// [Solution] Added specific matching function to eliminate mistaken
+// matches
+// [Files] BootOptions.c Core_Dxe.sdl
+//
+// 30 11/28/12 4:53p Felixp
+// Bug fix: The Bds was not building when CSM was not in the project.
+// Root cause: the MaskFilePathList function, which is used in BdsBoard.c,
+// was declared in BootOptions.c under #ifdef CSM_SUPPORT.
+// Solution: The definition of MaskFilePathList is moved outside of #ifdef
+// CSM_SUPPORT.
+//
+// 29 11/09/12 4:37p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] ill-formed bootoption can get control
+// [RootCause] Function ValidateBootOption was returning BOOLEAN value,
+// while ReadBootOption was checked EFI_STATUS value
+// [Solution] Replaced function ValidateBootOption with
+// IsBootOptionValid function
+// Updated ReadBootOption function to perform correct check
+// [Files] BootOptions.c
+//
+// 28 7/19/12 6:28p Felixp
+// Enhacement:
+// Validate boot option NVRAM variables before processing (make sure all
+// the fields contain valid data).
+// The validation is performed by the new ValidateBootOption function.
+//
+// 27 7/19/12 4:29p Felixp
+// Enhacement:
+// The implementation of the MatchBootOptionsToDevices function is
+// changed.
+// The old implementation was always matching boot device to a single boot
+// option.
+// The new implementation allows matching of multiple boot options to the
+// same boot device.
+//
+// 26 7/02/12 4:40p Felixp
+// [TAG] EIP83692
+// [Category] Improvement
+// [Description] The implementation from previous check in is updated to
+// use BootOptionDpMatchingFunctions eLinks instead of
+// BootOptionMatchingFunctions.
+// It is more appropriate as this is a device path test.
+// MatchUsbClassOptionToUsbDevice is renamed to UsbClassDevicePathTest.
+// [Files] Core_Dxe.sdl, BootOptions.c
+//
+// 25 6/21/12 4:58p Artems
+// [TAG] EIP83692
+// [Category] Improvement
+// [Description] Added function to match existing UEFI boot option with
+// USB class to available USB boot device
+// [Files] Core_Dxe.sdl BootOptions.c
+//
+// 24 6/01/12 3:59p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Dump boot options doesn't print "hidden" attribute
+// [RootCause] Incorrect bit check
+// [Solution] Corrected bit check
+// [Files] BootOptions.c
+//
+// 23 4/12/12 6:12p Felixp
+// [TAG] EIP84716
+// [Category] Improvement
+// [Description] PXE boot item doesn't show particular IPV4 / IPV6 in
+// boot menu
+//
+// 22 4/09/12 5:56p Artems
+// Implementation of NON_FW_BOOT_OPTION_HIDE functionality
+//
+// 21 12/05/11 3:58p Felixp
+// [TAG] EIP72485
+// [Category] Improvement
+// [Description] Handling of the UEFI HDD boot devices has changed.
+// Old implementation: UEFI HDD boot devices were filtered out using
+// IsUefiHddBootDevice filter function prior to the boot option matching.
+// New implementation: UEFI HDD boot devices participate in the boot
+// option matching. Unmatched UEFI HDD devices are deleted by the
+// DeleteUnmatchedUefiHddBootDevices function.
+// The problems with the implementation is that UEFI HDD boot options have
+// always been orphan boot options,
+// which caused customer's confusion and side effects in the custom boot
+// option maintenance code.
+//
+// [Files] BootOptions.c
+// CORE_DXE.sdl
+//
+// 20 10/31/11 10:10a Felixp
+// Follow up to previous check in(EIP 69507): Bug fix
+// GetPhysicalNetworkCardHandle:
+// wrong pointer was passed to pBS->FreePool
+//
+// 19 10/24/11 5:45p Felixp
+// [TAG] EIP69507
+// [Category] Improvement
+// Improvement is the handling of the boot options associated with
+// the network devices in ConstructBootOptionNameByHandle function .
+// The name is now constructed using physical network card handle
+// (as opposed to a handle associated with the IP connection).
+//
+// 18 10/19/11 12:54p Felixp
+// [TAG] EIP71102
+// [Category] Improvement
+// SaveBootOptions is updated to validate the boot option before saving
+// it.
+// The boot option can be invalid due to:
+// - a hot plug boot device disconnected in the middle of the BDS
+// processing
+// - bug in the boot option processing eLink function from other eModule
+//
+// 17 9/20/11 12:39p Felixp
+// [TAG] EIP70093
+// [Category] Improvement
+// [Description] BuildLegacyDevOrderBuffer is updated.
+// The code that creates a dummy LegacyDevOrder variable
+// containing just a header when no legacy devices are found is removed.
+// The code was required to support old versions of TSE.
+// It is no longer required.
+//
+// 16 9/20/11 12:28p Felixp
+// DumpBootOptionList function that prints debug messages is updated to
+// print hidden attribute.
+//
+// 15 6/16/11 8:55a Felixp
+// Bug fix in FindLegacyDeviceGroupByBbsIndex to prevent premature
+// matching of a BBS index
+// to the Type of the next group in the LegacyDevOrder structure.
+//
+// 14 11/18/10 3:31p Felixp
+// Clean up
+//
+// 13 11/18/10 8:11a Felixp
+// Masking of legacy devices is added.
+//
+// 12 11/15/10 5:15p Felixp
+// LocateDevicePathTest: function is updated to perform a full device path
+// match
+// (earlier implementation could match boot option with the handle of the
+// parent device)
+// DeviceTypeDevicePathTest: code that handles removable device without a
+// media is removed
+// (it may have unintended consequences)
+// NormalizeBootOptions: the order of normalization is changed to
+// normalize device path
+// prior to the name (to make sure name reflects updated device path)
+//
+// 11 10/07/10 1:35p Felixp
+// Make sure code compiles without CSM.
+//
+// 10 10/07/10 12:58p Felixp
+// BuildLegacyDevOrderBuffer function is added
+//
+// 9 10/06/10 5:33p Felixp
+// Bug fix in DeviceTypeDevicePathTest function.
+//
+// 8 10/01/10 8:07a Felixp
+// NormalizeBootOptions function is added.
+//
+// 7 9/29/10 9:23a Felixp
+// 1. Enhancement(EIP 39464) : Implementation of the BdsEntry function is
+// changed.
+// The BdsEntry is now a dispatching function that calls a collection of
+// functions
+// formed by the BDS_CONTROL_FLOW eLink.
+// 2. Minor Imrpvement in ConstructBootOptionName function.
+//
+// 6 9/22/10 12:41p Felixp
+// Bug fix in AdjustLegacyBootOptionPriorities: the disabled boot option
+// was not enabled based on LagacyDevOrder status
+//
+// 5 9/21/10 3:33p Felixp
+// Boot Option Infrastructure Improvements:
+// - NORMALIZE_BOOT_OPTIONS SDL token is replaced with
+// NORMALIZE_BOOT_OPTION_NAME and NORMALIZE_BOOT_OPTION_DEVICE_PATH
+// - MATCH_BOOT_OPTION_BY_LOCATION and MATCH_BOOT_OPTION_BY_DEVICE
+// SDL tokens and the supporting code are added.
+//
+// 4 8/27/10 9:32a Felixp
+// Function headers added
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+// Name: BootOptions.c
+//
+// Description: Contains the code for dealing with boot options and their maintance
+//
+////---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+#include "BootOptions.h"
+#include <Protocol/PDiskInfo.h>
+#include <Protocol/UsbIo.h>
+
+EFI_HII_HANDLE HiiHandle=0;
+EFI_GUID AmiBbsDevicePathGuid = AMI_BBS_DEVICE_PATH_GUID;
+EFI_GUID AmiMaskedDevicePathGuid = AMI_MASKED_DEVICE_PATH_GUID;
+EFI_GUID AmiDeviceNameDevicePathGuid = AMI_DEVICE_NAME_DEVICE_PATH_GUID;
+#ifdef CSM_SUPPORT
+EFI_GUID LegacyDevOrderGuid = LEGACY_DEV_ORDER_GUID;
+#endif
+
+DLIST BootOptionListStructure;
+DLIST BootDeviceListStructure;
+DLIST *BootOptionList = &BootOptionListStructure;
+DLIST *BootDeviceList = &BootDeviceListStructure;
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SortList
+//
+// Description: Sort the list of DLIST items using the passed COMPARE_FUNCTION to
+// determine the correct ordering of items
+//
+// Input: DLIST *List - list of items to sort
+// COMPARE_FUNCTION Compare - function to use to to sort the list
+//
+// Output: DLIST *List
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SortList(DLIST *List, COMPARE_FUNCTION Compare){
+ DLIST MergeList;
+ DLINK *p, *q, *e;
+ UINTN pSize, qSize, inSize;
+ UINT32 NoMerges;
+ UINTN i;
+
+ if(List->Size <= 1) //nothing to sort
+ return;
+
+ inSize = 1;
+ MergeList = *List;
+
+ while(1)
+ {
+ p = MergeList.pHead;
+ DListInit(&MergeList); //clear list
+ NoMerges = 0;
+
+ while(p != NULL)
+ {
+ NoMerges++;
+ q = p;
+ for(i = 0, pSize = 0; i < inSize; i++)
+ {
+ pSize++;
+ q = q->pNext;
+ if(q == NULL)
+ break;
+ }
+
+ qSize = inSize;
+ while(pSize > 0 || (qSize > 0 && q != NULL))
+ {
+ if(pSize == 0)
+ {
+ e = q;
+ q = q->pNext;
+ DListAdd(&MergeList, e);
+ qSize--;
+ }
+ else if(qSize == 0 || q == NULL)
+ {
+ e = p;
+ p = p->pNext;
+ DListAdd(&MergeList, e);
+ pSize--;
+ }
+ else if(Compare(p, q) > 0)
+ {
+ e = q;
+ q = q->pNext;
+ DListAdd(&MergeList, e);
+ qSize--;
+ }
+ else
+ {
+ e = p;
+ p = p->pNext;
+ DListAdd(&MergeList, e);
+ pSize--;
+ }
+ }
+ p = q;
+ }
+ if(NoMerges <= 1)
+ break;
+ inSize *= 2;
+ }
+ *List = MergeList;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CompareTagThenPriority
+//
+// Description: Compare the two boot options passed and determine the priority of
+// the first parameter in relation to the second parameter
+// Try to compare based on the following parameters in order,
+// Tag, then Group Header, then Priority
+//
+// Input: DLINK *Link1 - boot option 1
+// DLINK *Link2 - boot option 2
+//
+// Output: INT32 - the comparison result
+// Less than zero - Boot option 1 is lower priority than boot option 2
+// zero - boot option 1 is same priority as boot option 2
+// greater than zero - boot option 1 is a higher priority than boot option 2
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INT32 CompareTagThenPriority(DLINK *Link1, DLINK *Link2){
+ BOOT_OPTION *Option1 = (BOOT_OPTION*)Link1;
+ BOOT_OPTION *Option2 = (BOOT_OPTION*)Link2;
+ if (Option1->Tag < Option2->Tag) return -1;
+ else if (Option1->Tag > Option2->Tag) return 1;
+ if (Option1->GroupHeader != Option2->GroupHeader)
+ return (Option1->GroupHeader) ? -1 : 1;
+ if (Option1->Priority < Option2->Priority) return -1;
+ else if (Option1->Priority > Option2->Priority) return 1;
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ComparePriorityThenBootOptionNumber
+//
+// Description: Compare the two passed boot options first by their priority
+// if their priorities are equal, compare them based on their
+// boot option number
+//
+// Input: DLINK *Link1 - boot option 1
+// DLINK *Link2 - boot option 2
+//
+// Output: INT32 - the comparison result
+// Less than zero - Boot option 1 is lower priority than boot option 2
+// zero - boot option 1 is same priority as boot option 2
+// greater than zero - boot option 1 is a higher priority than boot option 2
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INT32 ComparePriorityThenBootOptionNumber(DLINK *Link1, DLINK *Link2){
+ BOOT_OPTION *Option1 = (BOOT_OPTION*)Link1;
+ BOOT_OPTION *Option2 = (BOOT_OPTION*)Link2;
+ if (Option1->Priority < Option2->Priority) return -1;
+ else if (Option1->Priority > Option2->Priority) return 1;
+ if (Option1->BootOptionNumber < Option2->BootOptionNumber) return -1;
+ else if (Option1->BootOptionNumber > Option2->BootOptionNumber) return 1;
+ if (Option1->GroupHeader != Option2->GroupHeader)
+ return (Option1->GroupHeader) ? -1 : 1;
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateBootOption
+//
+// Description: Create a BOOT_OPTION for the first entry in the passed BootOptionList
+//
+// Input: DLIST *BootOptionList - the list entry that needs a BOOT_OPTION
+// structure created
+//
+// Output: BOOT_OPTION * - pointer to the created BOOT_OPTION
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOT_OPTION* CreateBootOption(DLIST *BootOptionList){
+ static BOOT_OPTION BootOptionTemplate = {
+ {NULL,NULL}, LOAD_OPTION_ACTIVE, NULL, NULL, 0, NULL, 0,
+ INVALID_BOOT_OPTION_NUMBER, LOWEST_BOOT_OPTION_PRIORITY,
+ UNASSIGNED_HIGHEST_TAG,
+ INVALID_HANDLE, INVALID_BBS_INDEX, NULL, FALSE, FALSE
+ };
+
+ BOOT_OPTION *Option = Malloc(sizeof(BOOT_OPTION));
+ ASSERT(Option!=NULL);
+ *Option = BootOptionTemplate;
+ DListAdd(BootOptionList, &Option->Link);
+ return Option;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteBootOption
+//
+// Description: Delete the passed BOOT_OPTION from the BootOptionList
+//
+// Input: DLIST *BootOptionList - the master boot option list
+// BOOT_OPTION *Option - the option that should be deleted from the
+// master boot option list
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DeleteBootOption(DLIST *BootOptionList, BOOT_OPTION *Option){
+ DListDelete(BootOptionList,&Option->Link);
+ if (Option->Description!=NULL) pBS->FreePool(Option->Description);
+ if (Option->FilePathList!=NULL) pBS->FreePool(Option->FilePathList);
+ if (Option->OptionalDataSize!=0) pBS->FreePool(Option->OptionalData);
+ pBS->FreePool(Option);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateBootDevice
+//
+// Description: Create a boot device entry and add it to the BootDeviceList
+// fill the entry with the information from the passed parameters
+//
+// Input: DLIST *BootDeviceList - The master boot device list to add the
+// new boot device entry
+// EFI_HANDLE DeviceHandle - the handle of the device
+// UINT16 BbsIndex - the index in the bbs table of the device
+// BBS_TABLE *BbsEntry - the entire bbs table
+//
+// Output: BOOT_DEVICE * - the new boot device
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOT_DEVICE* CreateBootDevice(
+ DLIST *BootDeviceList, EFI_HANDLE DeviceHandle,
+ UINT16 BbsIndex, BBS_TABLE *BbsEntry
+){
+ BOOT_DEVICE *Device = Malloc(sizeof(BOOT_DEVICE));
+ ASSERT(Device!=NULL);
+ Device->BbsEntry = BbsEntry;
+ Device->BbsIndex = BbsIndex;
+ Device->DeviceHandle = DeviceHandle;
+ DListAdd(BootDeviceList, &Device->Link);
+ return Device;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteBootDevice
+//
+// Description: Delete the boot device out of the master boot device list
+//
+// Input: DLIST *BootDeviceList - the master boot device list
+// BOOT_DEVICE *Device - the boot device to delete from the master
+// boot device list
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DeleteBootDevice(DLIST *BootDeviceList, BOOT_DEVICE* Device){
+ DListDelete(BootDeviceList, &Device->Link);
+ pBS->FreePool(Device);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateBootOptionWithBootDeviceInfo
+//
+// Description: Update the boot option with the information from the passed
+// boot device information
+//
+// Input: BOOT_OPTION *Option - the boot option that needs updated
+// BOOT_DEVICE *Device - the boot device that contains the information
+// that the boot option needs updated with
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateBootOptionWithBootDeviceInfo(
+ BOOT_OPTION *Option, BOOT_DEVICE* Device
+){
+ Option->BbsEntry = Device->BbsEntry;
+ Option->BbsIndex = Device->BbsIndex;
+ Option->DeviceHandle = Device->DeviceHandle;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateBootOptionsFromNvramOption
+//
+// Description: Create a boot option using the nvram information
+//
+// Input: DLIST *BootOptionList - the master boot option list
+// UINT16 BootOptionNumber - the XXXX of the BootXXXX boot option
+// EFI_LOAD_OPTION NvramOption - the associated EFI_LOAD_OPTION
+// UINTN NvramOptionSize - the sizeof the nvram option
+// UINT32 Priority - the priority of the boot option
+//
+// Output: BOOT_OPTION * - the created boot option
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOT_OPTION* CreateBootOptionsFromNvramOption(
+ DLIST *BootOptionList, UINT16 BootOptionNumber,
+ EFI_LOAD_OPTION *NvramOption, UINTN NvramOptionSize,
+ UINT32 *Priority
+){
+ BOOT_OPTION *Option;
+ UINTN DescriptionSize;
+ UINT32 *OptionalData;
+ UINT8 *FilePathList;
+ UINTN OptionalDataSize;
+
+ Option = CreateBootOption(BootOptionList);
+ Option->Attributes=NvramOption->Attributes;
+ DescriptionSize = (Wcslen((CHAR16*)(NvramOption+1))+1)*sizeof(CHAR16);
+ Option->Description = Malloc(DescriptionSize);
+ MemCpy(Option->Description, NvramOption+1, DescriptionSize);
+
+ FilePathList = (UINT8*)(NvramOption+1)+DescriptionSize;
+ Option->FilePathListLength = NvramOption->FilePathListLength;
+ Option->FilePathList = Malloc(Option->FilePathListLength);
+ MemCpy(
+ Option->FilePathList, FilePathList, Option->FilePathListLength
+ );
+
+ OptionalData = (UINT32*)(FilePathList + NvramOption->FilePathListLength);
+ OptionalDataSize = (UINT8*)NvramOption
+ + NvramOptionSize
+ - (UINT8*)OptionalData;
+ Option->BootOptionNumber = BootOptionNumber;
+ Option->Priority = *Priority;
+ *Priority = GetNextBootOptionPriority(*Priority);
+ if ( OptionalDataSize >= sizeof(UINT32) ){
+ if (*OptionalData==AMI_SIMPLE_BOOT_OPTION_SIGNATURE){
+ OptionalDataSize -= sizeof(UINT32);
+ OptionalData++;
+ Option->FwBootOption = TRUE;
+ }else if (*OptionalData==AMI_GROUP_BOOT_OPTION_SIGNATURE){
+ Option->FwBootOption = TRUE;
+ Option->GroupHeader = TRUE;
+ OptionalDataSize -= sizeof(UINT32);
+ OptionalData++;
+ while ( OptionalDataSize > AMI_NESTED_BOOT_OPTION_HEADER_SIZE){
+ NESTED_BOOT_OPTION *NestedBootOption = (NESTED_BOOT_OPTION*)OptionalData;
+ if ( NestedBootOption->Signature != AMI_NESTED_BOOT_OPTION_SIGNATURE
+ || NestedBootOption->Size > OptionalDataSize
+ ) break;
+ CreateBootOptionsFromNvramOption(
+ BootOptionList, BootOptionNumber, &NestedBootOption->Option,
+ NestedBootOption->Size-AMI_NESTED_BOOT_OPTION_HEADER_SIZE,
+ Priority
+ );
+ OptionalDataSize -= NestedBootOption->Size;
+ OptionalData = (UINT32*)((UINT8*)OptionalData+NestedBootOption->Size);
+ }
+ }
+ }
+
+ if (OptionalDataSize==0){
+ Option->OptionalData = NULL;
+ Option->OptionalDataSize = 0;
+ }else{
+ Option->OptionalData = Malloc(OptionalDataSize);
+ MemCpy(
+ Option->OptionalData, OptionalData, OptionalDataSize
+ );
+ Option->OptionalDataSize = OptionalDataSize;
+ }
+ return Option;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsBootOptionValid
+//
+// Description: The function checks if boot option is well-formed
+//
+// Input: EFI_LOAD_OPTION NvramOption, UINTN NvramOptionSize
+//
+// Output: TRUE - boot option is valid, FALSE otherwise
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsBootOptionValid(EFI_LOAD_OPTION *NvramOption, UINTN NvramOptionSize){
+ CHAR16 *Char;
+ CHAR16 *EndOfDescription;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINTN DevicePathSize;
+
+ // The boot option must have at least the header,
+ // an empty (just the NULL-terminator) description,
+ // and an empty device path (End-of-Device-Path node).
+ if (NvramOption->FilePathListLength<sizeof(EFI_DEVICE_PATH_PROTOCOL)) return FALSE;
+ if (NvramOptionSize < sizeof(*NvramOption)+sizeof(CHAR16)) return FALSE;
+ NvramOptionSize -= sizeof(*NvramOption);
+
+ if ( NvramOption->FilePathListLength >= NvramOptionSize ) return FALSE;
+ NvramOptionSize -= NvramOption->FilePathListLength;
+
+ // The description must include at least the NULL-terminator
+ if (NvramOptionSize < sizeof(CHAR16)) return FALSE;
+
+ // The description must be NULL-terminated
+ Char = (CHAR16*)(NvramOption+1);
+ EndOfDescription = (CHAR16*)((CHAR8*)Char+NvramOptionSize);
+ while( *Char && Char < EndOfDescription) Char++;
+ if (Char==EndOfDescription) return FALSE;
+
+ // Validate the device path;
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)(Char+1); // skip the terminating zero.
+ if (EFI_ERROR(IsValidDevicePath(Dp))) return FALSE;
+ // NvramOption->FilePathListLength can't be zero.
+ // We checked that at the start of the funciton.
+ DevicePathSize = NvramOption->FilePathListLength;
+ while (TRUE) {
+ UINTN Length = NODE_LENGTH(Dp);
+ if (Length>DevicePathSize) return FALSE;
+ // We are not making sure that Length is not equal to zero.
+ // This has already been verified by the IsValidDevicePath above.
+ DevicePathSize -= Length;
+ if (DevicePathSize < sizeof(EFI_DEVICE_PATH_PROTOCOL)){
+ if (DevicePathSize != 0 ) return FALSE;
+ //The last node must be an End-of-Device-Path node.
+ return
+ isEndNode(Dp)
+ && Dp->SubType == END_ENTIRE_SUBTYPE
+ && Length == sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ ;
+ }
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)Dp+Length);
+ }
+ //Should never reach this point.
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadBootOption
+//
+// Description: Read the boot options from NVRAM and create associated
+// boot options in the master boot option list for each valid
+// option
+//
+// Input: DLIST *BootOptionList - the list to update with the nvram options
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ReadBootOptions(){
+ UINT16 *BootOrder = NULL;
+ UINTN BootOrderSize = 0;
+ EFI_STATUS Status;
+ UINTN i;
+ EFI_LOAD_OPTION *NvramOption = NULL;
+ UINT32 Priority=IndexToBootPriority(0);
+ UINTN NvramOptionSize;
+ UINT16 MaxBootOptionNumber=0;
+
+ Status=GetEfiVariable(
+ L"BootOrder", &EfiVariableGuid, NULL, &BootOrderSize, &BootOrder
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<BootOrderSize/sizeof(UINT16); i++){
+ CHAR16 BootStr[9];
+
+ // Get Boot Option
+ Swprintf(BootStr,L"Boot%04X",BootOrder[i]);
+ Status=GetEfiVariable(
+ BootStr, &EfiVariableGuid, NULL, &NvramOptionSize, &NvramOption
+ );
+ if (EFI_ERROR(Status)) continue;
+ //Let's verify if boot option is well-formed
+ if (!IsBootOptionValid(NvramOption, NvramOptionSize)){
+ TRACE((TRACE_DXE_CORE,"The boot option Boot%04X is ill-formed. Deleting...\n",
+ BootOrder[i]
+ ));
+ pRS->SetVariable(BootStr, &EfiVariableGuid, 0, 0, NULL);
+ continue;
+ }
+ CreateBootOptionsFromNvramOption(
+ BootOptionList, BootOrder[i], NvramOption, NvramOptionSize, &Priority
+ );
+ if (BootOrder[i] > MaxBootOptionNumber)
+ MaxBootOptionNumber = BootOrder[i];
+ }
+ pBS->FreePool(NvramOption);
+ pBS->FreePool(BootOrder);
+}
+
+VOID MaskFilePathList(BOOT_OPTION *Option){
+ static struct {
+ VENDOR_DEVICE_PATH vendor;
+ EFI_DEVICE_PATH_PROTOCOL end;
+ } MaskedDp = {
+ {
+ {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, {sizeof(VENDOR_DEVICE_PATH), 0}},
+ AMI_MASKED_DEVICE_PATH_GUID
+ },
+ {END_DEVICE_PATH,END_ENTIRE_SUBTYPE,sizeof(EFI_DEVICE_PATH_PROTOCOL)}
+ };
+ static MaskedDpLength = sizeof(MaskedDp);
+ UINT8 *NewDp;
+
+ NewDp = Malloc(Option->FilePathListLength + MaskedDpLength);
+ if (NewDp==NULL) return;
+ MemCpy(NewDp, &MaskedDp, MaskedDpLength);
+ MemCpy(
+ NewDp+MaskedDpLength, Option->FilePathList,
+ Option->FilePathListLength
+ );
+ pBS->FreePool(Option->FilePathList);
+ Option->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)NewDp;
+ Option->FilePathListLength += MaskedDpLength;
+}
+
+#ifdef CSM_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetBbsIndexByPositionInTheGroup
+//
+// Description: Using the passed position, return the BBS index from the legacy dev
+// order group
+//
+// Input: LEGACY_DEVICE_ORDER *Group - The legacy device order
+// UINT16 Position - the index into the legacy dev order to return
+//
+// Output: UINT32 - the bbs index from the the legacy dev order
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 GetBbsIndexByPositionInTheGroup(
+ LEGACY_DEVICE_ORDER *Group, UINT16 Position
+){
+ UINT16* EndOfGroup = (UINT16*)(
+ (UINT8*)Group + Group->Length + sizeof(UINT32)
+ );
+ UINT16 *IndexPtr = &Group->Device[0];
+ UINT32 Counter = 0;
+
+ while(IndexPtr<EndOfGroup){
+ if (Counter == Position)
+ return *IndexPtr;
+ IndexPtr++;
+ Counter++;
+ }
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindPositionInTheGroupByBbsIndex
+//
+// Description: Get the corresponding device index in the LEGACY_DEV_ORDER based on
+// the bbs index number. Legacy dev order organizes the boot priorities
+// of a class of devices (Cdrom, hdd, bev, etc) and the individual indexes
+// of the device are the relative priorities in which they should be used
+// to attempt a legacy boot.
+//
+// Input: LEGACY_DEVICE_ORDER *Group - pointer to the legacy dev order group
+// UINT16 BbsIndex - index of the device trying to be matched
+//
+// Output: UINT32 - the index of the device inside of the LEGACY_DEV_ORDER
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 FindPositionInTheGroupByBbsIndex(
+ LEGACY_DEVICE_ORDER *Group, UINT16 BbsIndex
+){
+ UINT16* EndOfGroup = (UINT16*)(
+ (UINT8*)Group + Group->Length + sizeof(UINT32)
+ );
+ UINT16 *IndexPtr = &Group->Device[0];
+ UINT32 Counter = 0;
+
+ while(IndexPtr<EndOfGroup){
+ if (*(UINT8*)IndexPtr == *(UINT8*)&BbsIndex)
+ return Counter;
+ IndexPtr++;
+ Counter++;
+ }
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindLegacyDeviceGroupByBbsIndex
+//
+// Description: Go through the legacy device order structure and find the legacy dev order
+// index that matches the bss index.
+//
+// Input: LEGACY_DEVICE_ORDER *DevOrder - pointer to the legacy device order
+// UINTN DevOrderSize - size of the legacy dev order structure
+// UINT16 BbsIndex - index of the bbs device to match
+//
+// Output: LEGACY_DEVICE_ORDER *
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+LEGACY_DEVICE_ORDER* FindLegacyDeviceGroupByBbsIndex(
+ LEGACY_DEVICE_ORDER *DevOrder, UINTN DevOrderSize, UINT16 BbsIndex
+){
+ UINT16 *EndOfDevOrder = (UINT16*)((UINT8*)DevOrder+DevOrderSize);
+ LEGACY_DEVICE_ORDER* EndOfGroup = DevOrder;
+ LEGACY_DEVICE_ORDER* GroupStart = DevOrder;
+ UINT16 *IndexPtr = (UINT16*)EndOfGroup;
+
+ while(IndexPtr<EndOfDevOrder){
+ if (IndexPtr==(UINT16*)EndOfGroup){
+ IndexPtr = &EndOfGroup->Device[0];
+ GroupStart = EndOfGroup;
+ EndOfGroup = (LEGACY_DEVICE_ORDER*)(
+ (UINT8*)EndOfGroup + EndOfGroup->Length + sizeof(UINT32)
+ );
+ }
+ if (*(UINT8*)IndexPtr == *(UINT8*)&BbsIndex) return GroupStart;
+ IndexPtr++;
+ }
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AdjustLegacyBootOptionPriorities
+//
+// Description: Go through the legacy dev order structure and adjust it ot match the
+// current boot priorities
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AdjustLegacyBootOptionPriorities(){
+ EFI_STATUS Status;
+ UINTN DevOrderSize, OldDevOrderSize;
+ LEGACY_DEVICE_ORDER *DevOrder=NULL, *OldDevOrder=NULL;
+ DLINK *Link;
+ UINT16 BootOptionNumber;
+ UINT16 *IndexPtr;
+ UINT16 *EndOfDeviceList;
+ BOOT_OPTION *Option;
+ UINT16 GroupSize=0;
+ INT32 IndexInTheGroup=0;
+ LEGACY_DEVICE_ORDER *CurrentGroup;
+
+ Status = GetEfiVariable(
+ L"LegacyDevOrder", &LegacyDevOrderGuid, NULL,
+ &DevOrderSize, &DevOrder
+ );
+ if(EFI_ERROR(Status) || DevOrderSize < sizeof(LEGACY_DEVICE_ORDER)) return ;
+ Status = GetEfiVariable(
+ L"OldLegacyDevOrder", &LegacyDevOrderGuid, NULL,
+ &OldDevOrderSize, &OldDevOrder
+ );
+ if( EFI_ERROR(Status)
+ || OldDevOrderSize!=DevOrderSize
+ || MemCmp(DevOrder,OldDevOrder, DevOrderSize)==0
+ ){
+ pBS->FreePool(DevOrder);
+ if (!EFI_ERROR(Status)) pBS->FreePool(OldDevOrder);
+ return ;
+ }
+
+ BootOptionNumber = INVALID_BOOT_OPTION_NUMBER;
+ IndexPtr = (UINT16*)DevOrder;
+ EndOfDeviceList = (UINT16*)((UINT8*)IndexPtr+DevOrderSize);
+
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ INT32 NewIndexInTheGroup;
+ LEGACY_DEVICE_ORDER *OldGroup;
+ UINT16 BbsIndex;
+
+ if ( !IsLegacyBootOption(Option) || Option->GroupHeader) continue;
+ // this should never happen during the normal course of operation
+ if (IndexPtr>=EndOfDeviceList) break;
+ // during the normal course of operation both conditions should
+ // happen simultaneously
+ if (BootOptionNumber != Option->BootOptionNumber || GroupSize==0){
+ BootOptionNumber = Option->BootOptionNumber;
+ IndexPtr += GroupSize;
+ CurrentGroup = (LEGACY_DEVICE_ORDER*)IndexPtr;
+ GroupSize = (CurrentGroup->Length)/sizeof(UINT16)-1;
+ IndexPtr = &CurrentGroup->Device[0];
+ IndexInTheGroup = 0;
+ }
+ OldGroup = FindLegacyDeviceGroupByBbsIndex(OldDevOrder,DevOrderSize,*IndexPtr);
+ BbsIndex = GetBbsIndexByPositionInTheGroup(OldGroup,IndexInTheGroup);
+ NewIndexInTheGroup = FindPositionInTheGroupByBbsIndex(CurrentGroup,BbsIndex);
+
+ Option->Priority +=
+ (NewIndexInTheGroup-IndexInTheGroup)*DEFAULT_PRIORITY_INCREMENT;
+ if ((CurrentGroup->Device[NewIndexInTheGroup] & 0xff00)!=0)
+ Option->Attributes &= ~LOAD_OPTION_ACTIVE;
+ else
+ Option->Attributes |= LOAD_OPTION_ACTIVE;
+ IndexPtr++;
+ GroupSize--;
+ IndexInTheGroup++;
+ }
+ pBS->FreePool(DevOrder);
+ pBS->FreePool(OldDevOrder);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UnmaskOrphanDevices
+//
+// Description: This function unmasks orphan devices.
+// The orphan legacy devices are masked by the MaskOrphanDevices function.
+// TSE does not like legacy boot options for devices that are not in the system.
+// To trick TSE we we are camouflaging such boot options by adding GUIDed device path.
+// The device path is added by MaskOrphanDevices function rigth before saving
+// and removed by UnmaskOrphanDevices right after reading
+//
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UnmaskOrphanDevices(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+ VENDOR_DEVICE_PATH *MaskedDp;
+ UINTN MaskedDpLength;
+
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ MaskedDp = (VENDOR_DEVICE_PATH*)Option->FilePathList;
+ if ( MaskedDp->Header.Type != HARDWARE_DEVICE_PATH
+ || MaskedDp->Header.SubType != HW_VENDOR_DP
+ || guidcmp(&AmiMaskedDevicePathGuid, &MaskedDp->Guid) != 0
+ ) continue;
+ MaskedDpLength = DPLength(&MaskedDp->Header);
+ if (Option->FilePathListLength <= MaskedDpLength) continue;
+ Option->FilePathListLength -=MaskedDpLength;
+ MemCpy(
+ Option->FilePathList, (UINT8*)Option->FilePathList+MaskedDpLength,
+ Option->FilePathListLength
+ );
+ if(!IsLegacyBootOption(Option) || Option->GroupHeader)
+ Option->Attributes &= ~LOAD_OPTION_HIDDEN;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildLegacyDevOrderBuffer
+//
+// Description: Go through the master boot option list and create
+// memory representation of the legacy dev order variable
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID BuildLegacyDevOrderBuffer(
+ LEGACY_DEVICE_ORDER **DevOrderBuffer, UINTN *BufferSize
+){
+ UINTN DevOrderSize;
+ LEGACY_DEVICE_ORDER *DevOrder, *GroupPtr;
+ UINT16 *DevPtr;
+ DLINK *Link;
+ UINT16 BootOptionNumber = INVALID_BOOT_OPTION_NUMBER;
+ BOOT_OPTION *Option;
+
+ if (DevOrderBuffer == NULL || BufferSize == NULL) return;
+ if (BootOptionList->Size == 0)
+ DevOrder = Malloc(sizeof(LEGACY_DEVICE_ORDER));
+ else
+ DevOrder = Malloc(BootOptionList->Size*sizeof(LEGACY_DEVICE_ORDER));
+ GroupPtr = DevOrder;
+ DevPtr = (UINT16*)DevOrder;
+
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if ( !IsLegacyBootOption(Option) || Option->GroupHeader) continue;
+ if (Option->BootOptionNumber!=BootOptionNumber){
+ GroupPtr->Length = (UINT16)((UINT8*)DevPtr - (UINT8*)&GroupPtr->Length);
+ GroupPtr = (LEGACY_DEVICE_ORDER*)DevPtr;
+ BootOptionNumber = Option->BootOptionNumber;
+ GroupPtr->Type = GetLegacyDevOrderType(Option);
+ DevPtr = GroupPtr->Device;
+ }
+ if ((Option->Attributes&LOAD_OPTION_ACTIVE)==0)
+ *DevPtr = Option->BbsIndex | 0xff00;
+ else
+ *DevPtr = Option->BbsIndex;
+ DevPtr++;
+ }
+ GroupPtr->Length = (UINT16)((UINT8*)DevPtr - (UINT8*)&GroupPtr->Length);
+ DevOrderSize = (UINT8*)DevPtr - (UINT8*)DevOrder;
+
+ *DevOrderBuffer = DevOrder;
+ *BufferSize = DevOrderSize;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MaskOrphanDevices
+//
+// Description: This function masks orphan devices before saving them.
+// TSE does not like legacy boot options for devices that are not in the system.
+// To trick TSE we we are camouflaging such boot options by adding GUIDed device path.
+// The device path is added by MaskOrphanDevices function rigth before saving
+// and removed by UnmaskOrphanDevices right after reading
+//
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID MaskOrphanDevices(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+ BOOT_OPTION *GroupHeader = NULL;
+
+ SortList(BootOptionList, ComparePriorityThenBootOptionNumber);
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if (!IsLegacyBootOption(Option))
+ continue;
+ if (Option->GroupHeader){
+ if (GroupHeader!=NULL) MaskFilePathList(GroupHeader);
+ GroupHeader=Option;
+ continue;
+ }
+ if (IsBootOptionWithDevice(Option)){
+ if (Option->BootOptionNumber==GroupHeader->BootOptionNumber)
+ GroupHeader=NULL;
+ continue;
+ }
+ MaskFilePathList(Option);
+ }
+ if (GroupHeader!=NULL) MaskFilePathList(GroupHeader);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveLegacyDevOrder
+//
+// Description: Go through the master boot option list and use it to update the
+// legacy dev order variable
+//
+// Input: DLIST *BootOptionList - the master boot option list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SaveLegacyDevOrder(){
+ UINTN DevOrderSize;
+ LEGACY_DEVICE_ORDER *DevOrder;
+
+ SortList(BootOptionList, ComparePriorityThenBootOptionNumber);
+ BuildLegacyDevOrderBuffer(&DevOrder, &DevOrderSize);
+ pRS->SetVariable(
+ L"LegacyDevOrder",
+ &LegacyDevOrderGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+#if RT_ACCESS_SUPPORT_IN_HPKTOOL
+ EFI_VARIABLE_RUNTIME_ACCESS |
+#endif
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ DevOrderSize,
+ DevOrder
+ );
+ pRS->SetVariable(
+ L"OldLegacyDevOrder",
+ &LegacyDevOrderGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ DevOrderSize,
+ DevOrder
+ );
+ pBS->FreePool(DevOrder);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CollectBbsDevice
+//
+// Description: Go through the bbs table and create a entry in the master boot order
+// list for each bbs table entry
+//
+// Input: DLIST *BootDeviceList - the master boot list
+//
+// Output: none
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CollectBbsDevices(DLIST *BootDeviceList){
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *HddInfo;
+ BBS_TABLE *BbsTable;
+ UINT16 i;
+
+ Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios);
+ if(EFI_ERROR(Status)) return ;
+ LegacyBios->ShadowAllLegacyOproms(LegacyBios);
+ LegacyBios->GetBbsInfo(LegacyBios, &HddCount, &HddInfo, &BbsCount, &BbsTable);
+
+ for(i = 0; i < BbsCount; i++){
+ if(BbsTable[i].BootPriority == 0xffff) continue;
+ CreateBootDevice(
+ BootDeviceList,
+ (EFI_HANDLE)*(UINTN*)&BbsTable[i].IBV1,
+ i,&BbsTable[i]
+ );
+ }
+}
+
+#endif //#ifdef CSM_SUPPORT
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CollectProtocolDevices
+//
+// Description: Collect a list of all handles with a particular protocol installed
+// on them and create a boot device for each handle.
+//
+// Input: DLIST *BootDeviceList - the master boot list that needs boot devices
+// added to it.
+// EFI_GUID *ProtocolGuid - the protocol to use when getting a list of
+// device handles
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CollectProtocolDevices(DLIST *BootDeviceList, EFI_GUID *ProtocolGuid){
+ EFI_HANDLE *Devices;
+ UINTN NumberOfDevices;
+ EFI_STATUS Status;
+ UINTN i;
+
+ Status = pBS->LocateHandleBuffer(
+ ByProtocol,ProtocolGuid, NULL,
+ &NumberOfDevices, &Devices
+ );
+ if (EFI_ERROR(Status)) return;
+ for(i=0; i<NumberOfDevices; i++){
+ CreateBootDevice(BootDeviceList,Devices[i],INVALID_BBS_INDEX,NULL);
+ }
+ pBS->FreePool(Devices);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CollectBootDevices
+//
+// Description: Helper function to generate a master boot list based on the
+// load file protocol, the simple file system protocol and, if
+// CSM support is enabled, the legacy bbs table
+//
+// Input: DLIST *BootDeviceList
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CollectBootDevices(){
+ CollectProtocolDevices(BootDeviceList,&gEfiLoadFileProtocolGuid);
+ CollectProtocolDevices(BootDeviceList,&gEfiSimpleFileSystemProtocolGuid);
+#ifdef CSM_SUPPORT
+ CollectBbsDevices(BootDeviceList);
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsUefiHddBootDevice
+//
+// Description: Determine if this boot device is a UEFI HDD
+//
+// Input: BOOT_DEVICE *Device - the device in question
+//
+// Output: BOOLEAN - TRUE - Device is a UEFI HDD Boot Device and it should
+// be removed from the boot order list
+// FALSE - Device is not a UEFI hdd and it should be left
+// in the boot order
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsUefiHddBootDevice(BOOT_DEVICE *Device){
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_STATUS Status;
+
+ if ( Device->DeviceHandle == INVALID_HANDLE
+ || Device->BbsEntry != NULL
+ ) return FALSE;
+
+
+ Status=pBS->HandleProtocol(
+ Device->DeviceHandle, &gEfiBlockIoProtocolGuid, &BlkIo
+ );
+ if (EFI_ERROR(Status)) return FALSE;
+ return !BlkIo->Media->RemovableMedia;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FilterBootDeviceList
+//
+// Description: Master filter handler. Function will call all ELINK functions
+// linked into the BootOptionBootDeviceFilteringFunctions list.
+// If any ELINK function returns FALSE, the device will be removed
+// from the function list
+//
+// Input: DLIST *BootDeviceList - the full boot order list
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID FilterBootDeviceList(){
+// Filter Devices
+ BOOT_DEVICE *Device;
+ DLINK *Link;
+
+ FOR_EACH_BOOT_DEVICE(BootDeviceList, Link, Device){
+ UINT32 i;
+ for(i=0; FilteringFunction[i]!=NULL; i++)
+ if (FilteringFunction[i](Device)){
+ DeleteBootDevice(BootDeviceList, Device);
+ break;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: LocateDevicePathTest
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *OptionalDevicePath -
+// BOOT_DEVICE *Device - the device
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN LocateDevicePathTest(EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device){
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ if (Device->DeviceHandle==INVALID_HANDLE) return FALSE;
+ Status=pBS->LocateDevicePath(
+ &gEfiDevicePathProtocolGuid, &OptionDevicePath, &Handle
+ );
+ if (EFI_ERROR(Status)) return FALSE;
+ if (Handle != Device->DeviceHandle) return FALSE;
+ if (isEndNode(OptionDevicePath)) return TRUE;
+ if (OptionDevicePath->Type != MEDIA_DEVICE_PATH) return FALSE;
+ return OptionDevicePath->SubType==MEDIA_FILEPATH_DP
+ || OptionDevicePath->SubType==MEDIA_FV_FILEPATH_DP;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PartitionDevicePathtest
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath -
+// BOOT_DEVICE *Device -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN PartitionDevicePathTest(
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device
+){
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DEVICE_PATH_PROTOCOL *PartitionDevicePath;
+ HARDDRIVE_DEVICE_PATH* BootParitionDevicePath;
+ HARDDRIVE_DEVICE_PATH* PartitionNode;
+
+ if (Device->DeviceHandle==INVALID_HANDLE) return FALSE;
+ if ( OptionDevicePath->Type!=MEDIA_DEVICE_PATH
+ || OptionDevicePath->SubType!=MEDIA_HARDDRIVE_DP
+ ) return FALSE;
+ BootParitionDevicePath = (HARDDRIVE_DEVICE_PATH*)OptionDevicePath;
+ Status = pBS->HandleProtocol(
+ Device->DeviceHandle,&gEfiBlockIoProtocolGuid,&BlockIo
+ );
+ if (EFI_ERROR(Status)) return FALSE;
+ // if this is not partition, continue
+ if (!BlockIo->Media->LogicalPartition) return FALSE;
+ Status = pBS->HandleProtocol(
+ Device->DeviceHandle,&gEfiDevicePathProtocolGuid,&PartitionDevicePath
+ );
+ if (EFI_ERROR(Status)) return FALSE;
+ // Get last node of the device path. It should be partition node
+ PartitionNode = (HARDDRIVE_DEVICE_PATH*)DPGetLastNode(PartitionDevicePath);
+ //Check if our partition matches Boot partition
+ if ( PartitionNode->Header.Type!=MEDIA_DEVICE_PATH
+ || PartitionNode->Header.SubType!=MEDIA_HARDDRIVE_DP
+ ) return FALSE;
+ if ( PartitionNode->PartitionNumber==BootParitionDevicePath->PartitionNumber
+ && PartitionNode->SignatureType==BootParitionDevicePath->SignatureType
+ && !MemCmp(PartitionNode->Signature,BootParitionDevicePath->Signature,16)
+ ){
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UINT8 GetDevicePathSubtype(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT8 Type){
+ UINT8 SubType;
+
+ if (Dp == NULL) return 0;
+ SubType = 0;
+
+ for( ; !(isEndNode(Dp)); Dp=NEXT_NODE(Dp))
+ if (Dp->Type == Type) SubType = Dp->SubType;
+ return SubType;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeviceTypeDevicePathTest
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *Dp - The device path to search
+// Type Device - The type of node to search for
+//
+// Output: EFI_DEVICE_PATH_PROTOCOL*
+// NULL - No node was found
+// Non-null - A node was found, and the pointer was returned
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_DEVICE_PATH_PROTOCOL* GetDevicePathNodeOfType(EFI_DEVICE_PATH_PROTOCOL *Dp, UINT8 Type){
+ EFI_DEVICE_PATH_PROTOCOL *Node = NULL;
+
+ if (Dp == NULL) return NULL;
+
+ for( ; !(isEndNode(Dp)); Dp=NEXT_NODE(Dp))
+ if (Dp->Type == Type) Node = Dp;
+ return Node;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeviceTypeDevicePathTest
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *OptionalDevicePath -
+// BOOT_DEVICE *Device - the device
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN DeviceTypeDevicePathTest(EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device){
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINT8 DeviceInterface, OptionInterface;
+ EFI_DEVICE_PATH_PROTOCOL *DeviceMedia, *OptionMedia;
+
+ if (Device->DeviceHandle==INVALID_HANDLE) return FALSE;
+
+ Status=pBS->HandleProtocol(
+ Device->DeviceHandle, &gEfiDevicePathProtocolGuid, &Dp
+ );
+ if (EFI_ERROR(Status)) return FALSE;
+
+ DeviceInterface = GetDevicePathSubtype(
+ Dp, MESSAGING_DEVICE_PATH
+ );
+ //If DeviceInterface is 0, the interface type is unknown.
+ //Can't do the matching.
+ if (DeviceInterface == 0) return FALSE;
+ if (DeviceInterface == MSG_SATA_DP)
+ DeviceInterface = MSG_ATAPI_DP;
+ OptionInterface = GetDevicePathSubtype(
+ OptionDevicePath, MESSAGING_DEVICE_PATH
+ );
+ if (OptionInterface == MSG_SATA_DP)
+ OptionInterface = MSG_ATAPI_DP;
+ if (DeviceInterface != OptionInterface) return FALSE;
+
+ DeviceMedia = GetDevicePathNodeOfType(Dp,MEDIA_DEVICE_PATH);
+ OptionMedia = GetDevicePathNodeOfType(OptionDevicePath,MEDIA_DEVICE_PATH);
+ if ( DeviceMedia != NULL && OptionMedia != NULL
+ && NODE_LENGTH(DeviceMedia) == NODE_LENGTH(OptionMedia)
+ && MemCmp(DeviceMedia,OptionMedia,NODE_LENGTH(DeviceMedia)) == 0
+ ){
+ NormalizeBootOptionDevicePath = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#define MSG_USB_DP_PRESENT 0x1
+#define MSG_USB_CLASS_DP_PRESENT 0x2
+#define MSG_USB_WWID_CLASS_DP_PRESENT 0x4
+
+BOOLEAN IsUsbDp(
+ IN EFI_DEVICE_PATH_PROTOCOL *Dp,
+ OUT UINT32 *AvailableNodes OPTIONAL
+)
+{
+ UINT32 Flags = 0;
+
+ for( ; !(isEndNode(Dp)); Dp = NEXT_NODE(Dp)) {
+ if(Dp->Type == MESSAGING_DEVICE_PATH) {
+ if(Dp->SubType == MSG_USB_DP) {
+ Flags |= MSG_USB_DP_PRESENT;
+ continue;
+ }
+ if(Dp->SubType == MSG_USB_CLASS_DP) {
+ Flags |= MSG_USB_CLASS_DP_PRESENT;
+ continue;
+ }
+ if(Dp->SubType == MSG_USB_WWID_CLASS_DP) {
+ Flags |= MSG_USB_WWID_CLASS_DP_PRESENT;
+ }
+ }
+ }
+ if(AvailableNodes != NULL)
+ *AvailableNodes = Flags;
+
+ return (Flags != 0) ? TRUE : FALSE;
+}
+
+BOOLEAN UsbClassDevicePathTest(
+ IN EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath,
+ IN BOOT_DEVICE *Device
+)
+{
+ EFI_STATUS Status;
+ USB_CLASS_DEVICE_PATH *UsbDp;
+ EFI_DEVICE_PATH_PROTOCOL *DevDp;
+ UINT32 AvailableNodes;
+
+ if(OptionDevicePath->Type != MESSAGING_DEVICE_PATH ||
+ OptionDevicePath->SubType != MSG_USB_CLASS_DP)
+ return FALSE; //boot option is not USB class boot option
+
+ Status = pBS->HandleProtocol(Device->DeviceHandle, &gEfiDevicePathProtocolGuid, &DevDp);
+ if(EFI_ERROR(Status))
+ return FALSE; //device doesn't support EFI_DEVICE_PATH protocol
+
+ if(!IsUsbDp(DevDp, &AvailableNodes))
+ return FALSE; //device is not a USB device
+
+ UsbDp = (USB_CLASS_DEVICE_PATH *)OptionDevicePath;
+ return (UsbDp->VendorId == 0xffff &&
+ UsbDp->ProductId == 0xffff &&
+ UsbDp->DeviceClass == 0xff &&
+ UsbDp->DeviceSubClass == 0xff &&
+ UsbDp->DeviceProtocol == 0xff) ? TRUE : FALSE;
+
+//TODO
+//add USB class specific comparison, once USB driver produces required device path node
+}
+
+#ifdef CSM_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BbsDevicePathTest
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath -
+// BOOT_DEVICE *Device -
+//
+// Output:
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BbsDevicePathTest(
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device
+){
+ BBS_BBS_DEVICE_PATH *BbsDp;
+ if (OptionDevicePath->Type!=BBS_DEVICE_PATH) return FALSE;
+ if (Device->BbsEntry==NULL) return FALSE;
+ BbsDp = (BBS_BBS_DEVICE_PATH*)OptionDevicePath;
+ return BbsDp->DeviceType == GetBbsEntryDeviceType(Device->BbsEntry);
+
+}
+
+UINT8 GetBbsDeviceInstance( UINT16 BbsIndex, BBS_TABLE *BbsEntry){
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Class;
+ UINT8 SubClass;
+ UINT16 Index;
+
+ if (BbsIndex==0) return 0;
+ Bus = BbsEntry->Bus;
+ Device = BbsEntry->Device;
+ Function = BbsEntry->Function;
+ Class = BbsEntry->Class;
+ SubClass = BbsEntry->SubClass;
+ BbsEntry -= BbsIndex;
+
+ for( Index = BbsIndex-1
+ ; Index != 0xFFFF
+ ; Index--
+ ){
+ if( Bus != BbsEntry[Index].Bus
+ || Device != BbsEntry[Index].Device
+ || Function != BbsEntry[Index].Function
+ || Class != BbsEntry[Index].Class
+ || SubClass != BbsEntry[Index].SubClass
+ ) return BbsIndex - 1 - Index;
+ }
+ return BbsIndex - 1 - Index;
+}
+
+BOOLEAN AmiBbsDevicePathTest(
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device
+){
+ AMI_BBS_DEVICE_PATH *AmiBbsDp;
+
+ if (Device->BbsEntry==NULL) return FALSE;
+ AmiBbsDp = (AMI_BBS_DEVICE_PATH*)OptionDevicePath;
+ return AmiBbsDp->Header.Header.Type == HARDWARE_DEVICE_PATH
+ && AmiBbsDp->Header.Header.SubType == HW_VENDOR_DP
+ && guidcmp(&AmiBbsDevicePathGuid, &AmiBbsDp->Header.Guid) == 0
+ && AmiBbsDp->Bus == Device->BbsEntry->Bus
+ && AmiBbsDp->Device == Device->BbsEntry->Device
+ && AmiBbsDp->Function == Device->BbsEntry->Function
+ && AmiBbsDp->Class == Device->BbsEntry->Class
+ && AmiBbsDp->SubClass == Device->BbsEntry->SubClass
+ && AmiBbsDp->Instance == GetBbsDeviceInstance(Device->BbsIndex,Device->BbsEntry);
+ ;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchDevicePathToDevice
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *OptionDp -
+// BOOT_DEVICE *Device -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchDevicePathToDevice(EFI_DEVICE_PATH_PROTOCOL *OptionDp, BOOT_DEVICE *Device){
+ UINT32 i;
+ for(i=0; DpMatchingFunction[i]!=NULL; i++)
+ if (DpMatchingFunction[i](OptionDp,Device)) return TRUE;
+ return FALSE;
+}
+
+BOOLEAN MatchUefiFloppyDrive(BOOT_OPTION *Option, BOOT_DEVICE *Device){
+ // This function makes sure that UEFI boot option is not matched
+ // with the legacy boot device.
+ // A legacy boot device is a device with a valid BbsIndex.
+ // A UEFI boot option is a boot option with FilePathList does not start
+ // with the BBS device path.
+ // When this funciton returns FALSE, the matching process fails.
+ // The function is executed via the BootOptionMatchingFunctions eLink.
+ return Device->BbsIndex==INVALID_BBS_INDEX || IsLegacyBootOption(Option);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure:
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchBootOpionToDevice(BOOT_OPTION *Option, BOOT_DEVICE *Device){
+ UINT32 i;
+ //all the functions have to return TRUE
+ for(i=0; MatchingFunction[i]!=NULL; i++)
+ if (!MatchingFunction[i](Option,Device)) return FALSE;
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchBootOptionsToDevices
+//
+// Description:
+//
+// Input: DLIST *BootOptionList -
+// DLIST *BootDeviceList -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID MatchBootOptionsToDevices(){
+ DLINK *OptionLink, *DeviceLink;
+ BOOT_OPTION *Option;
+ BOOT_DEVICE *Device;
+
+ FOR_EACH_BOOT_DEVICE(BootDeviceList,DeviceLink,Device){
+ BOOLEAN DeviceIsMatched = FALSE;
+ FOR_EACH_BOOT_OPTION(BootOptionList,OptionLink,Option){
+ EFI_DEVICE_PATH_PROTOCOL *OptionDp = Option->FilePathList;
+ EFI_DEVICE_PATH_PROTOCOL *DpInstance;
+ //Skip the group headers and the options that have already been matched.
+ if (Option->GroupHeader || IsBootOptionWithDevice(Option)) continue;
+ do {
+ EFI_DEVICE_PATH_PROTOCOL *TmpDp = OptionDp;
+ while( (DpInstance = DPNextInstance(&TmpDp,NULL))!=NULL
+ && MatchDevicePathToDevice(DpInstance,Device)
+ ) pBS->FreePool(DpInstance);
+
+ OptionDp = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)OptionDp+DPLength(OptionDp));
+ } while( Option->FwBootOption && DpInstance==NULL
+ && (UINT8*)OptionDp<(UINT8*)Option->FilePathList+Option->FilePathListLength
+ );
+ if (DpInstance == NULL && MatchBootOpionToDevice(Option,Device)){
+ UpdateBootOptionWithBootDeviceInfo(Option,Device);
+ DeviceIsMatched = TRUE;
+ // Legacy device can't be matched with more than one boot option.
+ if (IsLegacyBootOption(Option)) break;
+ }else{
+ if (DpInstance!=NULL) pBS->FreePool(DpInstance);
+ }
+ }
+ if (DeviceIsMatched) DeleteBootDevice(BootDeviceList, Device);
+ }
+}
+
+VOID DeleteUnmatchedUefiHddBootDevices(){
+ BOOT_DEVICE *Device;
+ DLINK *Link;
+
+ FOR_EACH_BOOT_DEVICE(BootDeviceList, Link, Device){
+ if (IsUefiHddBootDevice(Device)){
+ DeleteBootDevice(BootDeviceList, Device);
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetPhysicalBlockIoHandle
+//
+// Description:
+//
+// Input: EFI_HANDLE *BlockIoHandle -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_HANDLE GetPhysicalBlockIoHandle(EFI_HANDLE BlockIoHandle){
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath, *Dp;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = BlockIoHandle;
+
+ Status=pBS->HandleProtocol(
+ Handle, &gEfiBlockIoProtocolGuid, &BlkIo
+ );
+ if (EFI_ERROR(Status)) return Handle;
+ if (!BlkIo->Media->LogicalPartition) return Handle;
+ Status=pBS->HandleProtocol(
+ Handle, &gEfiDevicePathProtocolGuid, &DevicePath
+ );
+ if (EFI_ERROR(Status)) return Handle;
+ Dp=DevicePath;
+ while(BlkIo->Media->LogicalPartition){
+ EFI_DEVICE_PATH_PROTOCOL *PrevDp=Dp;
+ //We need to cut Devicepath node to get Phisycal Partition
+ Dp=DPCut(PrevDp);
+ if (PrevDp!=DevicePath) pBS->FreePool(PrevDp);
+ if (Dp == NULL) break;
+ PrevDp=Dp;
+ Status=pBS->LocateDevicePath(
+ &gEfiBlockIoProtocolGuid,&PrevDp,&Handle
+ );
+ if(EFI_ERROR(Status)) break;
+ Status=pBS->HandleProtocol(
+ Handle, &gEfiBlockIoProtocolGuid, &BlkIo
+ );
+ if(EFI_ERROR(Status)) break;
+ }
+ if (Dp!=NULL && Dp!=DevicePath) pBS->FreePool(Dp);
+ //if physical Block I/O handle is not found, return original handle
+ return (BlkIo->Media->LogicalPartition) ? BlockIoHandle : Handle;
+}
+
+EFI_HANDLE GetPhysicalNetworkCardHandle(EFI_HANDLE Handle, UINT8 *IpType){
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath, *Dp;
+ EFI_STATUS Status;
+
+ Status=pBS->HandleProtocol(
+ Handle, &gEfiLoadFileProtocolGuid, &LoadFile
+ );
+ if (EFI_ERROR(Status)) return Handle;
+
+ Status=pBS->HandleProtocol(
+ Handle, &gEfiDevicePathProtocolGuid, &DevicePath
+ );
+ if (EFI_ERROR(Status)) return Handle;
+ for(Dp=DevicePath; !(isEndNode(Dp)); Dp=NEXT_NODE(Dp)){
+ if (Dp->Type == MESSAGING_DEVICE_PATH && Dp->SubType == MSG_MAC_ADDR_DP){
+ EFI_HANDLE NewHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath, *TmpDp;
+
+ Dp=NEXT_NODE(Dp);
+ if (isEndNode(Dp)) break;
+ if ( IpType != NULL) *IpType = GetDevicePathSubtype(Dp, MESSAGING_DEVICE_PATH);
+ TmpDevicePath = TmpDp = DPCopy(DevicePath);
+ Dp = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)Dp - (UINT8*)DevicePath + (UINT8*)TmpDp);
+ Dp->Type = END_DEVICE_PATH;
+ Dp->SubType = END_ENTIRE_SUBTYPE;
+ SET_NODE_LENGTH(Dp,sizeof(*Dp));
+ Status = pBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDp, &NewHandle);
+ if (!EFI_ERROR(Status) && TmpDp==Dp) Handle = NewHandle;
+ pBS->FreePool(TmpDevicePath);
+ break;
+ }
+ }
+ return Handle;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RemoveTrailingSpaces
+//
+// Description:
+//
+// Input: CHAR16 *Name -
+// UINTN NumberOfCharacters -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN RemoveTrailingSpaces(CHAR16 *Name, UINTN NumberOfCharacters){
+ //remove trailing spaces
+ while(NumberOfCharacters>0 && Name[NumberOfCharacters-1]==L' ')
+ NumberOfCharacters--;
+ Name[NumberOfCharacters]=0;
+ return NumberOfCharacters;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameByHandle
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNameByHandle(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ EFI_HANDLE Handle;
+ CHAR16 *ControllerName;
+ CHAR16 *Prefix = L"";
+ UINTN NumberOfCharacters;
+ UINT8 IpType;
+
+ if (Option->DeviceHandle == INVALID_HANDLE) return 0;
+
+ //Name from Controller Handle
+ Handle = GetPhysicalBlockIoHandle(Option->DeviceHandle);
+ if (Handle==Option->DeviceHandle){
+ EFI_HANDLE OldHandle = Handle;
+ Handle = GetPhysicalNetworkCardHandle(Option->DeviceHandle,&IpType);
+ if (Handle != OldHandle) {
+ //TODO: use string token
+ if (IpType == MSG_IPv4_DP) Prefix=L"IP4 ";
+ else if (IpType == MSG_IPv6_DP) Prefix=L"IP6 ";
+ }
+ }
+ if (!GetControllerName(Handle, &ControllerName)) return 0;
+ NumberOfCharacters = Swprintf_s(Name, NameSize, L"%s%s",Prefix,ControllerName);
+ return RemoveTrailingSpaces(Name, NumberOfCharacters);
+}
+
+#ifdef CSM_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameByBbsDescription
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNameByBbsDescription(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ CHAR8 *AsciiNameStr;
+ UINTN NumberOfCharacters;
+
+ if (Option->BbsEntry == NULL) return 0;
+
+ //Name from BBS table
+ AsciiNameStr = (CHAR8*)(UINTN)(
+ (Option->BbsEntry->DescStringSegment<<4)
+ + Option->BbsEntry->DescStringOffset
+ );
+ if (AsciiNameStr == NULL) return 0;
+ for( NumberOfCharacters = 0
+ ; NumberOfCharacters < NameSize-1
+ ; NumberOfCharacters++
+ ){
+ if (!AsciiNameStr[NumberOfCharacters]) break;
+ Name[NumberOfCharacters] = AsciiNameStr[NumberOfCharacters];
+ }
+ Name[NumberOfCharacters]=0;
+ return RemoveTrailingSpaces(Name, NumberOfCharacters);
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DevicePathToNameString
+//
+// Description:
+//
+// Input: EFI_DEVICE_PATH_PROTOCOL *DevicePath -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN DevicePathToNameString(
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath, CHAR16 *Name, UINTN NameSize
+){
+ STRING_REF StrToken;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ UINTN BufferSize;
+ UINTN NumberOfCharacters = 0;
+
+ for( Dp = DevicePath; !(isEndNode(Dp)); Dp=NEXT_NODE(Dp)){
+ StrToken = DevicePathNodeToStrRef(Dp);
+ BufferSize = (NameSize-NumberOfCharacters)*sizeof(CHAR16);
+ if ( StrToken!= INVALID_STR_TOKEN
+ && !EFI_ERROR(HiiLibGetString(
+ HiiHandle,StrToken,&BufferSize, &Name[NumberOfCharacters]
+ ))
+ && BufferSize != 0
+ ){
+ NumberOfCharacters += (BufferSize-1)/sizeof(CHAR16);
+ if (NumberOfCharacters < NameSize - 1){
+ Name[NumberOfCharacters++]=L' ';
+ }
+ }
+ }//for ;
+ if (NumberOfCharacters !=0 ) Name[NumberOfCharacters]=0;
+ return NumberOfCharacters;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameByHandleDevicePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNameByHandleDevicePath(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (Option->DeviceHandle == INVALID_HANDLE) return 0;
+ //Name from Device Path
+
+ if (!EFI_ERROR(pBS->HandleProtocol(
+ Option->DeviceHandle, &gEfiDevicePathProtocolGuid, &DevicePath
+ ))) return DevicePathToNameString(DevicePath, Name, NameSize);
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameByFilePathList
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionNameByFilePathList(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ if (Option->FilePathList == NULL) return 0;
+ return DevicePathToNameString(Option->FilePathList, Name, NameSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionBaseName
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionBaseName(BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize){
+ UINTN NumberOfCharacters;
+ UINT32 i;
+
+ for(i=0; BuildNameFunctions[i]!=NULL; i++){
+ NumberOfCharacters = BuildNameFunctions[i](Option, Name, NameSize);
+ if ( NumberOfCharacters!=0 ) return NumberOfCharacters;
+ }
+
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionName
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructBootOptionName(BOOT_OPTION *Option){
+ CHAR16 Name[1024];
+ UINTN Length = sizeof(Name)/sizeof(CHAR16);
+ UINTN NumberOfCharacters, BaseNameLength;
+
+ NumberOfCharacters = ConstructBootOptionNamePrefix(Option,Name,Length);
+ Length -= NumberOfCharacters;
+ BaseNameLength = ConstructBootOptionBaseName(
+ Option, &Name[NumberOfCharacters], Length
+ );
+ NumberOfCharacters += BaseNameLength;
+ if (BaseNameLength==0){
+ //Unknown Device
+ UINTN BufferSize = Length*sizeof(CHAR16);
+ if (EFI_ERROR(
+ HiiLibGetString(
+ HiiHandle, UnknownDeviceToken, &BufferSize, &Name[NumberOfCharacters]
+ )
+ )){
+ NumberOfCharacters += Swprintf_s(
+ &Name[NumberOfCharacters], Length, L"Unknown Device"
+ );
+ }else{
+ NumberOfCharacters += (BufferSize-1)/sizeof(CHAR16);
+ }
+ Length -= NumberOfCharacters;
+ }
+ NumberOfCharacters += ConstructBootOptionNameSuffix(
+ Option, &Name[NumberOfCharacters], Length
+ );
+ //convert number of characters into string buffer size
+ Length = (NumberOfCharacters+1)*sizeof(CHAR16);
+ Option->Description = Malloc(Length);
+ MemCpy(Option->Description,Name,Length);
+ return NumberOfCharacters;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructBootOptionNameBySerialNumber
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructAtaBootOptionNameBySerialNumber(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ static EFI_GUID DiskInfoGuid = EFI_DISK_INFO_PROTOCOL_GUID;
+ EFI_HANDLE Handle;
+ UINTN NumberOfCharacters;
+ EFI_DISK_INFO_PROTOCOL *DiskInfo;
+ EFI_STATUS Status;
+ UINT16 IdentifyData[256];
+ UINT32 Size;
+ CHAR8 SerialNumber[21];
+
+ if (Option->DeviceHandle == INVALID_HANDLE) return 0;
+
+ Handle = GetPhysicalBlockIoHandle(Option->DeviceHandle);
+ Status = pBS->HandleProtocol(
+ Handle, &DiskInfoGuid, &DiskInfo
+ );
+ if (EFI_ERROR(Status)) return 0;
+ Size = sizeof(IdentifyData);
+ Status = DiskInfo->Identify ( DiskInfo, IdentifyData, &Size );
+ if (EFI_ERROR(Status)) return 0;
+ MemCpy(SerialNumber, IdentifyData+10, 20);
+ SerialNumber[20] = 0;
+ NumberOfCharacters = Swprintf_s(Name, NameSize, L"%S", SerialNumber);
+ return NumberOfCharacters;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructUsbBootOptionNameBySerialNumber
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// CHAR16 *Name -
+// UINTN NameSize -
+//
+// Output:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructUsbBootOptionNameBySerialNumber(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+
+ EFI_HANDLE Handle;
+ UINTN NumberOfCharacters;
+ EFI_STATUS Status;
+
+ EFI_USB_IO_PROTOCOL *UsbIo = NULL;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc = {0};
+ CHAR16 *UsbSerialNumber=NULL;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath=NULL;
+
+ if (Option->DeviceHandle == INVALID_HANDLE) return 0;
+
+ Handle = GetPhysicalBlockIoHandle(Option->DeviceHandle);
+
+ Status = pBS->HandleProtocol(Handle, &gEfiUsbIoProtocolGuid, &UsbIo);
+ if(EFI_ERROR(Status)) return 0;
+ Status = UsbIo->UsbGetDeviceDescriptor(UsbIo, &DevDesc);
+ if(EFI_ERROR(Status)) return 0;
+
+ if (DevDesc.StrSerialNumber) {
+ Status = UsbIo->UsbGetStringDescriptor(UsbIo, 0x0409, DevDesc.StrSerialNumber, &UsbSerialNumber);
+ if(EFI_ERROR(Status)) return 0;
+ pBS->CopyMem( Name, UsbSerialNumber, (Wcslen(UsbSerialNumber)+1)*2 );
+ NumberOfCharacters = Wcslen(UsbSerialNumber);
+ return NumberOfCharacters;
+ }
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructInternalBootOptionName
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructInternalBootOptionName(
+ BOOT_OPTION *Option, CHAR16 *Name, UINTN NameSize
+){
+ static CONSTRUCT_BOOT_OPTION_NAME *IntBuildNameFunctions[] = {
+ ConstructAtaBootOptionNameBySerialNumber,
+ ConstructUsbBootOptionNameBySerialNumber,
+ ConstructBootOptionNameByHandle,
+#ifdef CSM_SUPPORT
+ ConstructBootOptionNameByBbsDescription,
+#endif
+ NULL
+ };
+ UINTN NumberOfCharacters;
+ UINT32 i;
+
+ for(i=0; IntBuildNameFunctions[i]!=NULL; i++){
+ NumberOfCharacters = IntBuildNameFunctions[i](Option, Name, NameSize);
+ if ( NumberOfCharacters!=0 ) return NumberOfCharacters;
+ }
+
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConstructInternalDeviceName
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN ConstructInternalDeviceName(
+ BOOT_DEVICE *Device, CHAR16 *Name, UINTN NameSize
+){
+ static BOOT_OPTION BootOption = {
+ {NULL,NULL}, LOAD_OPTION_ACTIVE, NULL, NULL, 0, NULL, 0,
+ INVALID_BOOT_OPTION_NUMBER, LOWEST_BOOT_OPTION_PRIORITY,
+ UNASSIGNED_HIGHEST_TAG,
+ INVALID_HANDLE, INVALID_BBS_INDEX, NULL, TRUE, FALSE
+ };
+ UpdateBootOptionWithBootDeviceInfo(&BootOption,Device);
+ return ConstructInternalBootOptionName(&BootOption, Name, NameSize);
+}
+
+BOOLEAN AmiDeviceNameDevicePathTest(
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath, BOOT_DEVICE *Device
+){
+ AMI_DEVICE_NAME_DEVICE_PATH *NameDp;
+ CHAR16 Name[1024];
+ UINTN Size = sizeof(Name)/sizeof(CHAR16);
+ UINTN NumberOfCharacters;
+
+ NameDp = (AMI_DEVICE_NAME_DEVICE_PATH*)OptionDevicePath;
+ if( NameDp->Header.Header.Type != HARDWARE_DEVICE_PATH
+ || NameDp->Header.Header.SubType != HW_VENDOR_DP
+ || guidcmp(
+ &AmiDeviceNameDevicePathGuid,
+ &NameDp->Header.Guid
+ ) != 0
+ ) return FALSE;
+
+ NumberOfCharacters = ConstructInternalDeviceName(
+ Device, Name, Size
+ );
+ if (NumberOfCharacters==0) return FALSE;
+ //convert number of charcters into string buffer size
+ Size = (NumberOfCharacters+1)*sizeof(CHAR16);
+ return
+ Size == NODE_LENGTH(&NameDp->Header.Header)-sizeof(*NameDp)
+ && !MemCmp(Name,NameDp+1,Size);
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: AddDevicePathToFilePathList
+//
+// Description:
+// Adds another device path to an array of boot option device paths
+//
+// Input:
+// IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePathListPtr
+// On input, pointer to the current boot option FilePathList
+// On output, pointer to the new FilePathList. Memory used by original FilePathList is deallocated.
+//
+// IN OUT UINTN *FilePathListLength,
+// On input, pointer to the length of the current FilePathList
+// On output, pointer to the length of the new FilePathList
+//
+// IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+// Device path to add to the FilePathList
+//
+// Output:
+// VOID
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+VOID AddDevicePathToFilePathList(
+ EFI_DEVICE_PATH_PROTOCOL **FilePathListPtr, UINTN *FilePathListLength,
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ UINTN DevicePathLength;
+ EFI_DEVICE_PATH_PROTOCOL *NewFilePathList;
+
+ if ( FilePathListPtr == NULL
+ || FilePathListLength == NULL
+ || DevicePath == NULL
+ ) return;
+
+ DevicePathLength = DPLength(DevicePath);
+ if (*FilePathListPtr == NULL) *FilePathListLength = 0;
+
+ NewFilePathList = Malloc(*FilePathListLength + DevicePathLength);
+ if ( *FilePathListPtr != NULL ){
+ MemCpy(NewFilePathList, *FilePathListPtr, *FilePathListLength);
+ pBS->FreePool(*FilePathListPtr);
+ }
+ MemCpy(
+ (UINT8*)NewFilePathList+*FilePathListLength,
+ DevicePath, DevicePathLength
+ );
+ *FilePathListLength += DevicePathLength;
+ *FilePathListPtr = NewFilePathList;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildEfiFilePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BuildEfiFilePath(BOOT_OPTION *Option){
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+ EFI_STATUS Status;
+
+ if ( Option->FilePathList!=NULL
+ || Option->BbsEntry != NULL
+ || Option->DeviceHandle == INVALID_HANDLE
+ ) return FALSE;
+ Status = pBS->HandleProtocol(Option->DeviceHandle, &gEfiDevicePathProtocolGuid, &Dp);
+ if (EFI_ERROR(Status)) return FALSE;
+ Option->FilePathList = DPCopy(Dp);
+ Option->FilePathListLength = DPLength(Dp);
+ return TRUE;
+}
+
+#ifdef CSM_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildLegacyFilePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BuildLegacyFilePath(BOOT_OPTION *Option){
+ static struct {
+ BBS_BBS_DEVICE_PATH bbs;
+ EFI_DEVICE_PATH_PROTOCOL end;
+ } BbsDpTemplate = {
+ {
+ {BBS_DEVICE_PATH,BBS_BBS_DP,sizeof(BBS_BBS_DEVICE_PATH)},
+ BBS_HARDDISK,0,0
+ },
+ {END_DEVICE_PATH,END_ENTIRE_SUBTYPE,sizeof(EFI_DEVICE_PATH_PROTOCOL)}
+ };
+
+ if (Option->FilePathList!=NULL || Option->BbsEntry == NULL) return FALSE;
+ BbsDpTemplate.bbs.DeviceType=GetBbsEntryDeviceType(Option->BbsEntry);
+ Option->FilePathList = DPCopy(&BbsDpTemplate.bbs.Header);
+ Option->FilePathListLength = DPLength(Option->FilePathList);
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildLegacyLocationFilePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+// Note: function only available, and used, if CSM_SUPPORT token is defined and enabled
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BuildLegacyLocationFilePath(BOOT_OPTION *Option){
+ static struct {
+ AMI_BBS_DEVICE_PATH amibbs;
+ EFI_DEVICE_PATH_PROTOCOL end;
+ } AmiBbsDpTemplate = {
+ {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(AMI_BBS_DEVICE_PATH) },
+ AMI_BBS_DEVICE_PATH_GUID
+ },
+ 0, 0, 0, 0, 0, 0
+ },
+ {END_DEVICE_PATH,END_ENTIRE_SUBTYPE,sizeof(EFI_DEVICE_PATH_PROTOCOL)}
+ };
+
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+
+ if (Option->BbsEntry == NULL) return FALSE;
+ if ( Option->DeviceHandle == INVALID_HANDLE
+ || EFI_ERROR(pBS->HandleProtocol(Option->DeviceHandle, &gEfiDevicePathProtocolGuid, &Dp))
+ ){
+ Dp = &AmiBbsDpTemplate.amibbs.Header.Header;
+ AmiBbsDpTemplate.amibbs.Bus = (UINT8)Option->BbsEntry->Bus;
+ AmiBbsDpTemplate.amibbs.Device = (UINT8)Option->BbsEntry->Device;
+ AmiBbsDpTemplate.amibbs.Function = (UINT8)Option->BbsEntry->Function;
+ AmiBbsDpTemplate.amibbs.Class = (UINT8)Option->BbsEntry->Class;
+ AmiBbsDpTemplate.amibbs.SubClass = (UINT8)Option->BbsEntry->SubClass;
+ AmiBbsDpTemplate.amibbs.Instance = GetBbsDeviceInstance(Option->BbsIndex,Option->BbsEntry);
+ }
+ AddDevicePathToFilePathList(
+ &Option->FilePathList, &Option->FilePathListLength, Dp
+ );
+ return TRUE;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildNameFilePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BuildNameFilePath(BOOT_OPTION *Option){
+ static AMI_DEVICE_NAME_DEVICE_PATH AmiNameDpTemplate = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(AMI_DEVICE_NAME_DEVICE_PATH) },
+ AMI_DEVICE_NAME_DEVICE_PATH_GUID
+ }
+ };
+ static EFI_DEVICE_PATH_PROTOCOL EndOfDevicePathNode = {
+ END_DEVICE_PATH, END_ENTIRE_SUBTYPE,
+ {sizeof(EFI_DEVICE_PATH_PROTOCOL),0}
+ };
+
+ CHAR16 Name[1024];
+ UINTN Size = sizeof(Name)/sizeof(CHAR16);
+ UINTN NumberOfCharacters;
+ AMI_DEVICE_NAME_DEVICE_PATH *NameDp;
+ EFI_DEVICE_PATH_PROTOCOL *Dp;
+
+ NumberOfCharacters = ConstructInternalBootOptionName(
+ Option, Name, Size
+ );
+ if (NumberOfCharacters==0) return FALSE;
+ //convert number of charcters into string buffer size
+ Size = (NumberOfCharacters+1)*sizeof(CHAR16);
+
+ Dp = Malloc(sizeof(AmiNameDpTemplate)+Size+sizeof(EndOfDevicePathNode));
+ ASSERT(Dp!=NULL)
+ if (Dp==NULL) return FALSE;
+ NameDp = (AMI_DEVICE_NAME_DEVICE_PATH*)Dp;
+
+ *NameDp = AmiNameDpTemplate;
+ SET_NODE_LENGTH(Dp,(UINT16)(sizeof(AmiNameDpTemplate)+Size));
+ MemCpy(NameDp+1, Name, Size);
+ MemCpy(NEXT_NODE(Dp), &EndOfDevicePathNode, sizeof(EndOfDevicePathNode));
+ AddDevicePathToFilePathList(
+ &Option->FilePathList, &Option->FilePathListLength, Dp
+ );
+ pBS->FreePool(Dp);
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BuildBootOptionFilePath
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN BuildBootOptionFilePath(BOOT_OPTION *Option){
+ UINT32 i;
+ BOOLEAN FilePathCreated = FALSE;
+
+ for(i=0; BuildFilePathFunctions[i]!=NULL; i++){
+ FilePathCreated |= BuildFilePathFunctions[i](Option);
+ }
+ return FilePathCreated;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateBootOptionsForNewBootDevices
+//
+// Description:
+//
+// Input: DLIST *BootOptionList -
+// DLIST *BootDeviceList -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CreateBootOptionsForNewBootDevices(){
+ DLINK *Link;
+ BOOT_DEVICE *Device;
+
+ FOR_EACH_BOOT_DEVICE(BootDeviceList,Link,Device){
+ BOOT_OPTION *Option = CreateBootOption(BootOptionList);
+ UpdateBootOptionWithBootDeviceInfo(Option,Device);
+ DeleteBootDevice(BootDeviceList, Device);
+ Option->FwBootOption = TRUE;
+ ConstructBootOptionName(Option);
+ if (!BuildBootOptionFilePath(Option)){
+ Option->FilePathList=NULL;
+ Option->FilePathListLength=0;
+ }
+ }
+ DUMP_BOOT_OPTION_LIST(BootOptionList,"Before Processing");
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: NormalizeBootOptions
+//
+// Description: If normalization is enabled, regenerates all the description strings
+// and/or file path lists
+//
+// Input: none
+//
+// Output: none
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID NormalizeBootOptions(){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+
+ // Normalize boot options
+ //(regenerate the description string and the file path list)
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ if ( !Option->FwBootOption || !IsBootOptionWithDevice(Option)
+ || Option->BootOptionNumber == INVALID_BOOT_OPTION_NUMBER
+ ) continue;
+ if (NormalizeBootOptionDevicePath){
+ EFI_DEVICE_PATH_PROTOCOL *OldFilePathList = Option->FilePathList;
+ UINTN OldFilePathListLength = Option->FilePathListLength;
+ Option->FilePathList = NULL;
+ Option->FilePathListLength = 0;
+ BuildBootOptionFilePath(Option);
+ if (Option->FilePathList == NULL){
+ Option->FilePathList = OldFilePathList;
+ Option->FilePathListLength = OldFilePathListLength;
+ }else if (OldFilePathList != NULL){
+ pBS->FreePool(OldFilePathList);
+ }
+ }
+ if (NormalizeBootOptionName){
+ CHAR16 *OldDescription = Option->Description;
+ Option->Description = NULL;
+ ConstructBootOptionName(Option);
+ if (Option->Description == NULL)
+ Option->Description = OldDescription;
+ else if (OldDescription != NULL)
+ pBS->FreePool(OldDescription);
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DumpBootOptionList
+//
+// Description:
+//
+// Input: DLIST *BootOptionList -
+// CHAR8 *ListCaption -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DumpBootOptionList(DLIST *BootOptionList, CHAR8 *ListCaption){
+ DLINK *Link;
+ BOOT_OPTION *Option;
+ if (ListCaption!=NULL)
+ TRACE((TRACE_DXE_CORE,"%s:\n",ListCaption));
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ CHAR8 *Details1, *Details2, *Details3;
+ if (Option->GroupHeader) Details1="(group header)";
+ else if (!IsBootOptionWithDevice(Option)) Details1 ="(orphan)";
+ else Details1="";
+ if ((Option->Attributes&LOAD_OPTION_ACTIVE)!=LOAD_OPTION_ACTIVE) Details2="(disabled)";
+ else Details2="";
+ if ((Option->Attributes&LOAD_OPTION_HIDDEN)==LOAD_OPTION_HIDDEN) Details3="(hidden)";
+ else Details3="";
+ TRACE((TRACE_DXE_CORE,
+ "%X(%X/%X).%S%s%s%s\n",
+ Option->BootOptionNumber,Option->Priority,Option->Tag,Option->Description,
+ Details1,Details2,Details3
+ ));
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetBootOptionPackedSize
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN GetBootOptionPackedSize(BOOT_OPTION *Option){
+ return
+ sizeof(EFI_LOAD_OPTION)
+ + (Wcslen(Option->Description)+1)*sizeof(CHAR16)
+ + Option->FilePathListLength
+ + Option->OptionalDataSize;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PackBootOption
+//
+// Description:
+//
+// Input: BOOT_OPTION *Option -
+// EFI_LOAD_OPTION *NvramOption -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID* PackBootOption(BOOT_OPTION *Option, EFI_LOAD_OPTION *NvramOption){
+ UINTN DescriptionSize;
+ UINT8 *Ptr;
+
+ DescriptionSize = (Wcslen(Option->Description)+1)*sizeof(CHAR16);
+ NvramOption->Attributes = Option->Attributes;
+ NvramOption->FilePathListLength = (UINT16)Option->FilePathListLength;
+ MemCpy(NvramOption+1,Option->Description,DescriptionSize);
+ Ptr = (UINT8*)(NvramOption+1)+DescriptionSize;
+ MemCpy(Ptr, Option->FilePathList, Option->FilePathListLength);
+ Ptr += Option->FilePathListLength;
+ return Ptr;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SaveBootOptions
+//
+// Description:
+//
+// Input: DLIST *BootOptionList -
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SaveBootOptions(){
+ UINTN BootOrderSize;
+ UINT16 *BootOrder;
+ DLINK *Link;
+ UINTN BootOrderIndex = 0;
+ BOOT_OPTION *Option;
+
+ //PRECONDITION: All Boot Option Numbers are set
+ SortList(BootOptionList, ComparePriorityThenBootOptionNumber);
+ DUMP_BOOT_OPTION_LIST(BootOptionList, "Before Saving");
+ BootOrderSize = BootOptionList->Size*sizeof(UINT16);
+ if (BootOrderSize==0) return;
+ BootOrder = Malloc(BootOrderSize);
+
+ FOR_EACH_BOOT_OPTION(BootOptionList,Link,Option){
+ EFI_LOAD_OPTION *NvramOption;
+ BOOT_OPTION *NestedOption;
+ DLINK *TmpLink;
+ UINTN NvramOptionSize;
+ UINT8 *Ptr;
+ CHAR16 BootStr[9];
+ EFI_STATUS Status;
+ BOOLEAN HasNestedOptions = FALSE;
+
+ //Meke sure the boot option is well-formed
+ if( Option->FilePathListLength == 0
+ || Option->FilePathList == NULL
+ || Option->BootOptionNumber == INVALID_BOOT_OPTION_NUMBER
+ ){
+ TRACE((TRACE_DXE_CORE,
+ "SaveBootOptions: skipping invalid boot option '%X.%S'\n",
+ Option->BootOptionNumber,Option->Description
+ ));
+ continue;
+ }
+
+ NvramOptionSize = GetBootOptionPackedSize(Option);
+ if (Option->FwBootOption){
+ NvramOptionSize += sizeof(UINT32); //signature
+ //TRACE((-1,"(%X) before size loop: size=%X\n",Option->BootOptionNumber,NvramOptionSize));
+ FOR_EACH_LIST_ELEMENT(Option->Link.pNext, TmpLink, NestedOption, BOOT_OPTION){
+ if (Option->BootOptionNumber != NestedOption->BootOptionNumber)
+ break;
+ NvramOptionSize += AMI_NESTED_BOOT_OPTION_HEADER_SIZE +
+ + GetBootOptionPackedSize(NestedOption)
+ + sizeof(UINT32); //signature;
+ //TRACE((-1,"Nested(%X) size loop: size=%X\n",Option->BootOptionNumber,NvramOptionSize));
+ HasNestedOptions = TRUE;
+ }
+ }
+ NvramOption = Malloc(NvramOptionSize);
+ Ptr = PackBootOption(Option,NvramOption);
+ if (Option->FwBootOption){
+ if (HasNestedOptions)
+ *(UINT32*)Ptr = AMI_GROUP_BOOT_OPTION_SIGNATURE;
+ else
+ *(UINT32*)Ptr = AMI_SIMPLE_BOOT_OPTION_SIGNATURE;
+ Ptr += sizeof(UINT32);
+ //TRACE((-1,"(%X) before save loop: size=%X\n",Option->BootOptionNumber,Ptr-(UINT8*)NvramOption));
+ if (HasNestedOptions){
+ FOR_EACH_LIST_ELEMENT(Option->Link.pNext, TmpLink, NestedOption, BOOT_OPTION){
+ NESTED_BOOT_OPTION *NestedPackedOption;
+
+ if (Option->BootOptionNumber != NestedOption->BootOptionNumber)
+ break;
+ NestedPackedOption = (NESTED_BOOT_OPTION*)Ptr;
+ NestedPackedOption->Signature = AMI_NESTED_BOOT_OPTION_SIGNATURE;
+ Ptr = PackBootOption(NestedOption,&NestedPackedOption->Option);
+ *(UINT32*)Ptr = AMI_SIMPLE_BOOT_OPTION_SIGNATURE;
+ Ptr += sizeof(UINT32);
+ if (NestedOption->OptionalDataSize!=0){
+ MemCpy(
+ Ptr, NestedOption->OptionalData, NestedOption->OptionalDataSize
+ );
+ Ptr += NestedOption->OptionalDataSize;
+ }
+ NestedPackedOption->Size = (UINT32)(Ptr - (UINT8*)NestedPackedOption);
+ //delete nested option
+ DeleteBootOption(BootOptionList,NestedOption);
+ //TRACE((-1,"Nested(%X) save loop: size=%X\n",Option->BootOptionNumber,Ptr-(UINT8*)NvramOption));
+ }
+ }
+ }
+ if (Option->OptionalDataSize!=0){
+ MemCpy(
+ Ptr, Option->OptionalData, Option->OptionalDataSize
+ );
+ }
+ //TRACE((-1,"Saving %d: %X; %X; ods=%d\n",Option->BootOptionNumber,Ptr+Option->OptionalDataSize,(UINT8*)NvramOption+NvramOptionSize,Option->OptionalDataSize));
+ ASSERT(Ptr+Option->OptionalDataSize == (UINT8*)NvramOption+NvramOptionSize)
+ Swprintf(BootStr,L"Boot%04X",Option->BootOptionNumber);
+ Status = pRS->SetVariable(
+ BootStr, &EfiVariableGuid,
+ BOOT_VARIABLE_ATTRIBUTES, NvramOptionSize, NvramOption
+ );
+ BootOrder[BootOrderIndex]=Option->BootOptionNumber;
+ Link = Option->Link.pNext;
+ DeleteBootOption(BootOptionList,Option);
+ pBS->FreePool(NvramOption);
+ if (EFI_ERROR(Status)) continue;
+ BootOrderIndex++;
+ }
+ pRS->SetVariable(
+ L"BootOrder", &EfiVariableGuid,
+ BOOT_VARIABLE_ATTRIBUTES, BootOrderIndex*sizeof(UINT16), BootOrder
+ );
+ pBS->FreePool(BootOrder);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateBootOptionVariables
+//
+// Description: This function initializes the global variables.
+// Must be called before any other boot option processing function can be used.
+//
+// Input: none
+//
+// Output: none
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateBootOptionVariables(){
+ LoadStrings(TheImageHandle, &HiiHandle);
+ DListInit(BootOptionList);
+ DListInit(BootDeviceList);
+}
+
+BOOLEAN IsGroupOrphan(BOOT_OPTION *Option)
+{
+ BOOT_OPTION *Current;
+
+ Current = (BOOT_OPTION *)BootOptionList->pHead;
+ while(Current != NULL) {
+ if(Current == Option)
+ break;
+ Current = (BOOT_OPTION *)Current->Link.pNext;
+ }
+
+ if(Current == NULL) //shouldn't be here - input parameter is not found in boot options
+ return TRUE;
+
+ Current = (BOOT_OPTION *)Current->Link.pNext; //get next boot option
+ if(Current == NULL || Current->Tag != Option->Tag) //group option is alone (next either NULL or different tag)
+ return TRUE;
+
+ while(Current != NULL && Current->Tag == Option->Tag) {
+ if(IsBootOptionWithDevice(Current)) //one of physical boot options in group has device
+ return FALSE;
+ Current = (BOOT_OPTION *)Current->Link.pNext;
+ }
+ return TRUE;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/CORE_DXE.cif b/Core/CORE_DXE/CORE_DXE.cif
new file mode 100644
index 0000000..d67cf9e
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXE.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "CORE_DXE"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\"
+ RefName = "CORE_DXE"
+[files]
+"CORE_DXE.sdl"
+"CORE_DXE.mak"
+"Bds.uni"
+"BdsBoard.c"
+[parts]
+"ArchProtocol"
+<endComponent>
diff --git a/Core/CORE_DXE/CORE_DXE.mak b/Core/CORE_DXE/CORE_DXE.mak
new file mode 100644
index 0000000..a765462
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXE.mak
@@ -0,0 +1,189 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/BIN/Core/CORE_DXE/CORE_DXE.mak 14 9/29/10 9:19a Felixp $
+#
+# $Revision: 14 $
+#
+# $Date: 9/29/10 9:19a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Core/CORE_DXE/CORE_DXE.mak $
+#
+# 14 9/29/10 9:19a Felixp
+# Enhancement(EIP 39464) : Implementation of the BdsEntry function is
+# changed.
+# The BdsEntry is now a dispatching function that calls a collection of
+# functions
+# formed by the BDS_CONTROL_FLOW eLink.
+#
+# 13 8/26/10 12:52p Felixp
+# Spelling error in one of the identifiers in BootOptioneLinks.h
+#
+# 12 6/29/10 11:03p Felixp
+# New Boot Options Maintenance Infrastructure.
+# See AMI_Aptio_4.x_Boot_Options_Maintenance_Infrastructure_Porting_Guide
+# _NDA.doc for details.
+#
+# 11 2/23/10 9:19p Felixp
+# Support of the BDS String Override via BDS_SDBS eLink (EIP 32696).
+#
+# 10 11/19/09 12:55p Felixp
+# Entry point name has changed (from DxeCoreEntry to DxeMain).
+#
+# 9 6/08/06 7:13p Sivagarn
+# - Updated file header
+# - Fixed EIP 7580 issue. Search for (EIP7580) for changes
+#
+# 8 3/13/06 1:44a Felixp
+# BdsInitialize eLink created
+#
+# 7 12/02/05 11:16a Felixp
+# @set INCLUDE=%%INCLUDE%% removed since it's not needed.
+#
+# 6 6/20/05 12:01p Felixp
+#
+# 5 5/24/05 2:48p Felixp
+# support for SUPPORTED_LANGUAGES
+#
+# 4 4/12/05 2:59p Felixp
+#
+# 3 4/08/05 7:39a Felixp
+# Boot Menu implemented
+#
+# 2 2/11/05 5:46p Felixp
+# Binary files organization improved:
+# - extra layer of sub-component removed
+# - macros initialization moved to SDL tokens to eliminate undefined
+# macros situation
+# - debug and release binaries have different names now (workaround for
+# VeB limitation)
+#
+# 1 1/28/05 12:44p Felixp
+#
+# 4 1/25/05 3:27p Felixp
+# compression enabled;
+# dependency from token.h added
+#
+# 3 1/21/05 12:01p Felixp
+# BootScriptSave moved to CORE_DXE
+#
+# 2 1/18/05 3:21p Felixp
+# PrintDebugMessage renamed to Trace
+#
+# 5 11/10/04 5:18p Felixp
+# reference to EfiDriverLib.lib removed
+#
+# 25 4/07/04 12:46a Felixp
+# REAL PLATFORM DEBUGGING (lots of bug fixes)
+#
+# 20 3/28/04 2:11p Felixp
+# 1. PE Loader and some other commonly used code moved to the Library
+# 2. Warnings fixed (from now on warning will be treated as error)
+#
+# 19 3/27/04 9:23a Felixp
+#
+# 18 3/25/04 3:47p Robert
+# added Misc.obj to and removed reset.obj from the MAK file
+#
+# 8 2/06/04 2:46a Felixp
+# - Support for VC6 tools
+# - bug fixes
+# - component AddOn added
+#
+# 7 2/04/04 6:50p Yakovlevs
+#
+# 6 1/20/04 11:32a Felixp
+# Memory Services added (at the moment they are non-buildable)
+#
+# 5 1/18/04 8:33a Felixp
+# From now on, OBJ files are created in a component specific subdirectory
+# of $(BUILD_DIR)
+#
+# 2 1/05/04 6:09p Robert
+#
+# 1 12/05/03 4:15p Felixp
+#
+#**********************************************************************
+
+#<AMI_FHDR_START>
+#-----------------------------------------------------------------------
+# Name: CORE_DXE.MAK
+#
+# Description: This NMAKE script file builds the CORE_DXE driver
+#
+#-----------------------------------------------------------------------
+#<AMI_FHDR_END>
+
+all : CORE_DXE
+
+CORE_DXE : $(BUILD_DIR)\CORE_DXE.mak $(BUILD_DIR)\BootOptioneLinks.h CORE_DXEBin
+
+$(BUILD_DIR)\CORE_DXE.mak : $(CORE_DXE_DIR)\$(@B).cif $(CORE_DXE_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CORE_DXE_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CORE_DXEBin : $(AMIDXELIB) $(CORE_DXE_LIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\CORE_DXE.mak all\
+ GUID=5AE3F37E-4EAE-41ae-8240-35465B5E81EB \
+ ENTRY_POINT=DxeMain \
+ TYPE=DXE_CORE LIBRARIES= \
+ "CFLAGS=$(CFLAGS) /D\"SUPPORTED_LANGUAGES=$(SUPPORTED_LANGUAGES: =)\" /D\"SIO_DEVICE_LIST=$(DxeSioList)\" /D\"SIO_DEVICE_PTR_LIST=_AND_ $(DxeSioList: =_AND_ )\" "\
+ "EXT_HEADERS=$(BUILD_DIR)\token.h $(BUILD_DIR)\BootOptioneLinks.h"\
+ HAS_RESOURCES=1 COMPRESS=1\
+ "INIT_LIST=$(DxeCoreInitialize)"\
+ "INIT_LIST2=$(BdsEntryInitialize)"\
+!IF "$(BDS_SDBS: =)"==""
+ "STRGATHER_FLAGS=-db $(BUILD_DIR)\$(CORE_DXE_DIR)\Bds.sdb"\
+!ELSE
+ "STRGATHER_FLAGS=-db $(BUILD_DIR)\$(CORE_DXE_DIR)\Bds.sdb -db $(BDS_SDBS: = -db )"\
+!ENDIF
+
+# We are trying to convert a list of comma separated functions to a list of comma
+# separated function name strings.
+# The original list of function may contain C comment blocks /* */
+BDS_CONTROL_FLOW0 = $(BDS_CONTROL_FLOW: =) # remove the spaces
+BDS_CONTROL_FLOW1 = $(BDS_CONTROL_FLOW0:*/,=*/) # remove commas after the comments
+BDS_CONTROL_FLOW2 = $(BDS_CONTROL_FLOW1:*//*=) # merge the adjacent comments
+BDS_CONTROL_FLOW3 = $(BDS_CONTROL_FLOW2:*/=*/") # add quote after the comment to begin the next string
+BDS_CONTROL_FLOW4 = "$(BDS_CONTROL_FLOW3:,=",")", # add quotes before and after the commas
+BDS_CONTROL_FLOW_STRINGS = $(BDS_CONTROL_FLOW4:"/*=/*) # remove quote before the comments
+
+$(BUILD_DIR)\BootOptioneLinks.h : $(BUILD_DIR)\Token.h $(CORE_DXE_DIR)\CORE_DXE.mak
+ $(SILENT)type << >$(BUILD_DIR)\BootOptioneLinks.h
+#define BOOT_OPTION_DP_MATCHING_FUNCTIONS $(BootOptionDpMatchingFunctions)
+#define BOOT_OPTION_MATCHING_FUNCTIONS $(BootOptionMatchingFunctions)
+#define BOOT_OPTION_BUILD_NAME_FUNCTIONS $(BootOptionBuildNameFunctions)
+#define BOOT_OPTION_BUILD_FILE_PATH_FUNCTIONS $(BootOptionBuildFilePathFunctions)
+#define BOOT_OPTION_BOOT_DEVICE_FILTERING_FUNCTIONS $(BootOptionBootDeviceFilteringFunctions)
+
+#define BDS_CONTROL_FLOW $(BDS_CONTROL_FLOW)
+#define BDS_CONTROL_FLOW_NAMES $(BDS_CONTROL_FLOW_STRINGS)
+<<
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/CORE_DXE.sdl b/Core/CORE_DXE/CORE_DXE.sdl
new file mode 100644
index 0000000..37a52e0
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXE.sdl
@@ -0,0 +1,1169 @@
+TOKEN
+ Name = "CORE_DXE_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable CORE_DXE support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "ConSplitter_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable ConSplitter support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "Partition_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Partition support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "PS2Ctl_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable PS2 Controller support in the project."
+ TokenType = Boolean
+ TargetH = Yes
+ TargetMAK = Yes
+ Token = "KBC_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "GC_COLOR_BLACK"
+ Value = "0,0,0"
+ Help = "Definition of the black color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_BLUE"
+ Value = "0x98,0,0"
+ Help = "Definition of the blue color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_GREEN"
+ Value = "0,0x98,0"
+ Help = "Definition of the green color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_CYAN"
+ Value = "0x98,0x98,0"
+ Help = "Definition of the cyan color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_RED"
+ Value = "0,0,0x98"
+ Help = "Definition of the red color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_MAGENTA"
+ Value = "0x98,0,0x98"
+ Help = "Definition of the magenta color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_BROWN"
+ Value = "0x0,0x40,0x80"
+ Help = "Definition of the brown color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTGRAY"
+ Value = "0x98,0x98,0x98"
+ Help = "Definition of the light gray color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_DARKGRAY"
+ Value = "0x10,0x10,0x10"
+ Help = "Definition of the dark gray color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTBLUE"
+ Value = "0xFF,0x10,0x10"
+ Help = "Definition of the light blue color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTGREEN"
+ Value = "0x10,0xFF,0x10"
+ Help = "Definition of the light green color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTCYAN"
+ Value = "0xFF,0xFF,0xE0"
+ Help = "Definition of the light cyan color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTRED"
+ Value = "0x10,0x10,0xFF "
+ Help = "Definition of the light red color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_LIGHTMAGENTA"
+ Value = "0xF0,0x10,0xFF"
+ Help = "Definition of the light magenta color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_YELLOW"
+ Value = "0x10,0xFF,0xFF"
+ Help = "Definition of the yellow color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_COLOR_WHITE"
+ Value = "0xFF,0xFF,0xFF"
+ Help = "Definition of the white color used by the graphic console\Format: <Blue>,<Green>,<Red>"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "<0-255>,<0-255>,<0-255>"
+End
+
+TOKEN
+ Name = "GC_MODE0"
+ Value = "{ 0, 80, 25, 800, 600 }"
+ Help = "Parameters of the graphica console text mode 0.\NOTE: Text resolution of the mode 0 must be 80 by 25\Format: {ModeNumber, TextColomns,TextRows, HorizontalPixels,VerticalPixels}"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "GC_MODE1"
+ Value = "{ 1, 80, 50, 1280, 1024 }"
+ Help = "Parameters of the graphica console text mode 1.\NOTE: Text resolution of the mode 0 must be 80 by 50\Format: {ModeNumber, TextColomns,TextRows, HorizontalPixels,VerticalPixels}"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "GC_MODE2"
+ Value = "{ 2, 100, 31, 800, 600 }"
+ Help = "Parameters of the graphica console text mode 2.\Format: {ModeNumber, TextColomns,TextRows, HorizontalPixels,VerticalPixels}"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "GC_MODE3"
+ Value = "{ 3, 0, 0, 0, 0 }"
+ Help = "Parameters of the graphica console text mode 3.\Format: {ModeNumber, TextColomns,TextRows, HorizontalPixels,VerticalPixels}"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "GC_MODE_LIST"
+ Value = "$(GC_MODE0), $(GC_MODE1), $(GC_MODE2), $(GC_MODE3)"
+ Help = "List of text modes supported by graphic console.\NOTE: Mode numbers defined by GC_MODEx tokens must be in ascending order."
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "START_IN_NATIVE_RESOLUTION"
+ Value = "1"
+ Help = "When this token is 'on', Graphics console will start in native resolution if available"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INSTALL_DUMMY_SECURITY_PROTOCOL"
+ Value = "1"
+ Help = "When this token is 'on', the Core publishes dummy instance of the security protocol.\The security protocol is one of the architectural protocols and as such must be available.\The default value is 'on'. \Set to 'off' if project includes driver that publishes the security protocol.\"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "PS2MOUSE_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "PS2Ctl_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "PS2KBD_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "PS2Ctl_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "KBC_AUTODETECT_PORTS"
+ Value = "0"
+ Help = "Auto detection of KB/MS using AMI KB-5. This switch will enable/disable the connector swap of Keyboard and PS2 Mouse i.e. keyboard\can be connected to PS2 Mouse connector and vice-versa."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "KBC_AUTODETECT_PORTS_FUNCTION"
+ Value = "AutodetectKbdMousePorts"
+ TokenType = Expression
+ TargetH = Yes
+ Token = "KBC_AUTODETECT_PORTS" "=" "1"
+End
+
+TOKEN
+ Name = "BLOCK_KBC_PIN_22_23_BIT"
+ Value = "1"
+ Help = "Turn this switch On or Off to block or unblock KBC lines P22 and P23.\If unblocked - KBC will be able to change lines P22 and P23 from high to low and back using D1 command.\If blocked - KBC will not be able to change the state of P22 and P23 lines."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LEDS_AT_STARTUP"
+ Value = "2"
+ Help = "Keyboard LEDs after startup:\Bit0: ScrlLock is on/off;\Bit1: NumLock is on/off;\Bit2: CapsLock is on/off."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MAX_HOTKEYS"
+ Value = "20"
+ Help = "Number of hot keys."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INIT_DEFAULT_HOTKEYS"
+ Value = "1"
+ Help = "Initialize default hot keys (perform system soft reset on Ctrl+Alt+Del combination)."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "KBC_BASIC_ASSURANCE_TEST"
+ Value = "1"
+ Help = "1 - Perform KBC Basic Assurance Test. 0 - Do not peform KBC Basic Assurance Test."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DETECT_PS2_KEYBOARD"
+ Value = "0"
+ Help = "1 - Perform PS2 Keyboard Detection. 0 - Do not perform PS2 Keybaord Detection."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DETECT_PS2_MOUSE"
+ Value = "0"
+ Help = "1 - Perform PS2 Mouse Detection. 0 - Do not perform PS2 Mouse Detection."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "INSTALL_KEYBOARD_MOUSE_ALWAYS"
+ Value = "1"
+ Help = "1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if the device is present at the time of detection."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "RETURN_CURRENT_KEY_STATE"
+ Value = "0"
+ Help = "0 - return key shift and toggle states captured during a keypress, 1 - return current shift and toggle state."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "KB_IRQ_SUPPORT"
+ Value = "0"
+ Help = "When this token is ON mouse will operate using interrupt, when OFF polling will be used"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MS_IRQ_SUPPORT"
+ Value = "0"
+ Help = "When this token is ON mouse will operate using interrupt, when OFF polling will be used"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "KBD_READ_BEFORE_INSTALL"
+ Value = "0"
+ Help = "This token will be used to save the key codes if keys are pressed before installing keyboard driver"
+ TokenType = Expression
+ TargetH = Yes
+ Token = "KB_IRQ_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "IBFREE_TIMEOUT"
+ Value = "300"
+ Help = "Timeout (in miliseconds) used for the function IbFreeTimeout()"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CLEAR_PS2KB_BUFFER_AT_READYTOBOOT"
+ Value = "0"
+ Help = "ON -> PS2 KB Buffer will be cleared at ReadyToBoot.\OFF -> PS2 KB Buffer will not be cleared at ReadyToBoot."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CHECK_BDA_KEYBOARD_BUFFER"
+ Value = "1"
+ Help = "ON -> BDA KBD Buffer will be checked for any key whenever there is no key is found in ReadKeyStroke().\OFF -> BDA KBD Buffer will not be checked."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CLEAR_PENDING_KEYS_IN_PS2"
+ Value = "0"
+ Help = "ON -> Resets the keyboard before PS2 Driver is started and Clears OBF on every Kbd Reset as some Notbook KBC has some pending keys even after disabling and enabling Scanning."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BBS_USB_DEVICE_TYPE_SUPPORT"
+ Value = "0"
+ Help = "Treat USB devices as a separate BBS device type"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BBS_NETWORK_DEVICE_TYPE_SUPPORT"
+ Value = "0"
+ Help = "Treat network devices as a separate BBS device type"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "GROUP_BOOT_OPTIONS_BY_TAG"
+ Value = "1"
+ Help = "When this token is on, the boot options are grouped by tag.\When this token is off, the boot list is flat (a.k.a. flex boot)."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FW_ORPHAN_BOOT_OPTIONS_POLICY"
+ Value = "ORPHAN_BOOT_OPTIONS_POLICY_DELETE"
+ Help = "Defines handling of the firmware boot options not associated with the device.\The supported policies are: \ORPHAN_BOOT_OPTIONS_POLICY_KEEP\ORPHAN_BOOT_OPTIONS_POLICY_DELETE\ORPHAN_BOOT_OPTIONS_POLICY_DISABLE\"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NON_FW_ORPHAN_BOOT_OPTIONS_POLICY"
+ Value = "ORPHAN_BOOT_OPTIONS_POLICY_HIDE"
+ Help = "Defines handling of the non-firmware (third party) boot options not associated with the device.\The supported policies are: \ORPHAN_BOOT_OPTIONS_POLICY_KEEP\ORPHAN_BOOT_OPTIONS_POLICY_DELETE\ORPHAN_BOOT_OPTIONS_POLICY_DISABLE\ORPHAN_BOOT_OPTIONS_POLICY_HIDE\"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "ORPHAN_BOOT_OPTIONS_POLICY_KEEP"
+End
+
+TOKEN
+ Name = "ORPHAN_GROUP_HEADERS_POLICY"
+ Value = "ORPHAN_BOOT_OPTIONS_POLICY_DELETE"
+ Help = "Defines handling of the non-firmware (third party) boot options not associated with the device.\The supported policies are: \ORPHAN_BOOT_OPTIONS_POLICY_KEEP\ORPHAN_BOOT_OPTIONS_POLICY_DELETE\ORPHAN_BOOT_OPTIONS_POLICY_DISABLE\"
+ TokenType = Expression
+ TargetH = Yes
+ Range = "ORPHAN_BOOT_OPTIONS_POLICY_KEEP"
+End
+
+TOKEN
+ Name = "NORMALIZE_BOOT_OPTION_NAME"
+ Value = "1"
+ Help = "When the token is on, the Description of the existing boot options is regenerated during the boot option processing.\It is possible to override built time Description normalization policy using NormalizeBootOptionName variable."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NORMALIZE_BOOT_OPTION_DEVICE_PATH"
+ Value = "1"
+ Help = "When the token is on, the FilePathList of the existing boot options is regenerated during the boot option processing.\It is possible to override built time FilePathList normalization policy using NormalizeBootOptionDevicePath variable."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BOOT_OPTION_TAG_PRIORITIES"
+ Value = "BoTagUefi, BoTagLegacyCdrom, BoTagLegacyHardDisk, BoTagLegacyFloppy, BoTagLegacyEmbedNetwork, BoTagEmbeddedShell"
+ Help = "List of value of type BOOT_OPTION_TAG that define priorities of the boot option tags.\BOOT_OPTION_TAG is defined in BdsBoard.c\"
+ TokenType = Expression
+ TargetH = Yes
+ Token = "DEBUG_MODE" "=" "0"
+End
+
+TOKEN
+ Name = "BOOT_OPTION_TAG_PRIORITIES"
+ Value = "BoTagEmbeddedShell, BoTagUefi, BoTagLegacyCdrom, BoTagLegacyHardDisk, BoTagLegacyFloppy, BoTagLegacyEmbedNetwork"
+ Help = "List of value of type BOOT_OPTION_TAG that define priorities of the boot option tags.\BOOT_OPTION_TAG is defined in BdsBoard.c\"
+ TokenType = Expression
+ TargetH = Yes
+ Token = "DEBUG_MODE" "!=" "0"
+End
+
+TOKEN
+ Name = "BOOT_OPTION_NAME_PREFIX_FUNCTION"
+ Value = "ConstructBootOptionNamePrefixDefault"
+ Help = "Name of the function of type CONSTRUCT_BOOT_OPTION_NAME.\The function is used to create boot option name prefix."
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BOOT_OPTION_NAME_SUFFIX_FUNCTION"
+ Value = "ConstructBootOptionNameSuffixDefault"
+ Help = "Name of the function of type CONSTRUCT_BOOT_OPTION_NAME.\The function is used to create boot option name suffix."
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BOOT_OPTION_GET_BBS_ENTRY_DEVICE_TYPE_FUNCTION"
+ Value = "GetBbsEntryDeviceTypeDefault"
+ Help = "Name of the function of type GET_BBS_ENTRY_DEVICE_TYPE.\The function is used to convert device type stored in the BBS table to a legacy device type that will be stored in the NVRAM.\The default implementation(GetBbsEntryDeviceTypeDefault) provides support for BBS_USB_DEVICE_TYPE_SUPPORT and BBS_NETWORK_DEVICE_TYPE_SUPPORT SDL tokens."
+ TokenType = Expression
+ TargetH = Yes
+ Token = "CSM_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "MATCH_BOOT_OPTION_BY_LOCATION"
+ Value = "1"
+ Help = "When this option is on, the boot option is matched to the boot device using device location information. The device location is a specific connection point that the device is attached to. \For example: SATA Controller 1 Port 0, IDE Primary Master, USB Controller 1 Port 3\"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MATCH_BOOT_OPTION_BY_DEVICE"
+ Value = "1"
+ Help = "When this option is on, the boot option is matched to the boot device using device information such as device name, device serial number or other information that uniquely identifies the device."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "BDS_CONNECT_CONSOLE_DEVICES"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow \functions from the 'Connect Console Devices' group"
+ TokenType = Boolean
+End
+
+TOKEN
+ Name = "BDS_FULL_SYSTEM_INITIALIZATION"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow(BDS_CONTROL_FLOW) \functions from the 'Full System Initialization' group"
+ TokenType = Boolean
+End
+
+TOKEN
+ Name = "BDS_CONNECT_CON_OUT_DEVICES"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow(BDS_CONTROL_FLOW) \functions from the 'Connect ConOut Devices' group"
+ TokenType = Boolean
+ Token = "BDS_CONNECT_CONSOLE_DEVICES" "=" "1"
+End
+
+TOKEN
+ Name = "BDS_CONNECT_CON_IN_DEVICES"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow(BDS_CONTROL_FLOW) \functions from the 'Connect ConIn Devices' group"
+ TokenType = Boolean
+ Token = "BDS_CONNECT_CONSOLE_DEVICES" "=" "1"
+End
+
+TOKEN
+ Name = "BDS_UPDATE_BOOT_OPTION_VARIABLES"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow(BDS_CONTROL_FLOW) \functions from the 'UpdateBootOptionVariables,' group"
+ TokenType = Boolean
+End
+
+TOKEN
+ Name = "BDS_PROCESS_BOOT_OPTION_LIST"
+ Value = "1"
+ Help = "Enables/Disables execution of the BDS Control Flow(BDS_CONTROL_FLOW) \functions from the '/*Process Boot Option List*/' group"
+ TokenType = Boolean
+ Token = "BDS_UPDATE_BOOT_OPTION_VARIABLES" "=" "1"
+End
+
+TOKEN
+ Name = "ATAPI_BUSY_CLEAR_TIMEOUT"
+ Value = "16000"
+ Help = "Timeout value for ATAPI busy clear. Set to 16 sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "S3_BUSY_CLEAR_TIMEOUT"
+ Value = "10000"
+ Help = "Timeout value for S3 busy clear. Set to 10 sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DMA_ATA_COMMAND_COMPLETE_TIMEOUT"
+ Value = "5000"
+ Help = "Timeout value for completion of DMA ATA command. Set to 5 Sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DMA_ATAPI_COMMAND_COMPLETE_TIMEOUT"
+ Value = "16000"
+ Help = "Timeout value for completion of DMA ATAPI command. Set to 16 Sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ATAPI_RESET_COMMAND_TIMEOUT"
+ Value = "5000"
+ Help = "Timeout Value for ATAPI reset command. Set to 5 sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "POWERON_BUSY_CLEAR_TIMEOUT"
+ Value = "10000"
+ Help = "The Poweron busy clear timeout value. Set to 10 sec."
+ TokenType = Integer
+ TargetH = Yes
+End
+
+PATH
+ Name = "CORE_DXE_DIR"
+End
+
+MODULE
+ Help = "Includes CORE_DXE.mak to Project"
+ File = "CORE_DXE.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CORE_DXE.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "DxeCoreInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BdsInit,"
+ Parent = "DxeCoreInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "GenericSioEntryPoint,"
+ Parent = "DxeCoreInitialize"
+ Token = "SIO_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InitDataHub,"
+ Parent = "DxeCoreInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UnicodeCollationEntryPoint,"
+ Parent = "DxeCoreInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BDS_CONTROL_FLOW"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "HiiBdsEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "DiskIoEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "GCEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CSEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ Token = "ConSplitter_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PartitionEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ Token = "Partition_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CORE_DXE_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(CORE_DXE_DIR)\CORE_DXE$(ARCH)$(DBG).lib"
+ Parent = "CORE_DXE_LIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BdsEntryInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "DxeSioList"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "PS2CtlEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ Token = "PS2Ctl_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "FloppyCtrlEntryPoint,"
+ Parent = "BdsEntryInitialize"
+ Token = "x64_BUILD" "=" "1"
+ Token = "FLOPPY_CTRL_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "HiiDbEntryPoint,"
+ Parent = "DxeCoreInitialize"
+ Token = "EFI_SPECIFICATION_VERSION" "<=" "0x20000"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "HiiDriverEntryPoint,"
+ Parent = "DxeCoreInitialize"
+ Token = "EFI_SPECIFICATION_VERSION" ">" "0x20000"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BDS_SDBS"
+ Help = "List of SDB files with the string overrides for the BDS component."
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BootOptionDpMatchingFunctions"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BootOptionMatchingFunctions"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BootOptionBootDeviceFilteringFunctions"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BootOptionBuildNameFunctions"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "BootOptionBuildFilePathFunctions"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "LocateDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PartitionDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UsbClassDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BbsDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "AmiBbsDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConstructBootOptionNameByHandle,"
+ Parent = "BootOptionBuildNameFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConstructBootOptionNameByBbsDescription,"
+ Parent = "BootOptionBuildNameFunctions"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConstructBootOptionNameByHandleDevicePath,"
+ Parent = "BootOptionBuildNameFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConstructBootOptionNameByFilePathList,"
+ Parent = "BootOptionBuildNameFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InstallLzmaDecompressProtocol,"
+ Parent = "DxeCoreInitialize"
+ Token = "LZMA_SUPPORT" "=" "1"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "BuildLegacyLocationFilePath,"
+ Parent = "BootOptionBuildFilePathFunctions"
+ Token = "CSM_SUPPORT" "=" "1"
+ Token = "MATCH_BOOT_OPTION_BY_LOCATION" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BuildNameFilePath,"
+ Parent = "BootOptionBuildFilePathFunctions"
+ Token = "MATCH_BOOT_OPTION_BY_DEVICE" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BuildLegacyFilePath,"
+ Parent = "BootOptionBuildFilePathFunctions"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "BuildEfiFilePath,"
+ Parent = "BootOptionBuildFilePathFunctions"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "AmiDeviceNameDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "DeviceTypeDevicePathTest,"
+ Parent = "BootOptionDpMatchingFunctions"
+ Token = "MATCH_BOOT_OPTION_BY_LOCATION" "=" "0"
+ Token = "MATCH_BOOT_OPTION_BY_DEVICE" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SignalConnectDriversEvent,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectRootBridgeHandles,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RegisterMemoryTypeInformationUpdateCallback,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "FastBootHook,"
+ Parent = "BDS_CONTROL_FLOW"
+ Token = "FAST_BOOT_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/* Connect Console Devices */"
+ Parent = "BDS_CONTROL_FLOW"
+ Token = "BDS_CONNECT_CONSOLE_DEVICES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/* Full System Initialization */"
+ Parent = "BDS_CONTROL_FLOW"
+ Token = "BDS_CONNECT_CONSOLE_DEVICES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/* Connect ConOut Devices */"
+ Parent = "/* Connect Console Devices */"
+ Token = "BDS_CONNECT_CON_OUT_DEVICES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/* Connect ConIn Devices */"
+ Parent = "/* Connect Console Devices */"
+ Token = "BDS_CONNECT_CON_IN_DEVICES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ReportConnectConOutProgressCode,"
+ Parent = "/* Connect ConOut Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectVgaConOut,"
+ Parent = "/* Connect ConOut Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectConOutVariable,"
+ Parent = "/* Connect ConOut Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InstallConOutStartedProtocol,"
+ Parent = "/* Connect ConOut Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ReportConnectConInProgressCode,"
+ Parent = "/* Connect ConIn Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectPs2ConIn,"
+ Parent = "/* Connect ConIn Devices */"
+ Token = "PS2Ctl_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectUsbConIn,"
+ Parent = "/* Connect ConIn Devices */"
+ Token = "AMIUSB_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectConInVariable,"
+ Parent = "/* Connect ConIn Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InstallConInStartedProtocol,"
+ Parent = "/* Connect ConIn Devices */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConInAvailabilityBeep,"
+ Parent = "/* Connect ConIn Devices */"
+ Token = "BEEP_ENABLE" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ConnectEverything,"
+ Parent = "/* Full System Initialization */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RunDrivers,"
+ Parent = "/* Full System Initialization */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InitConVars,"
+ Parent = "/* Full System Initialization */"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "InstallFwLoadFile,"
+ Parent = "/* Full System Initialization */"
+ Token = "Shell_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UpdateBootOptionVariables,"
+ Parent = "/* Full System Initialization */"
+ Token = "BDS_UPDATE_BOOT_OPTION_VARIABLES" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CallTheDispatcher,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CapsuleHook,"
+ Parent = "BDS_CONTROL_FLOW"
+ Token = "CAPSULE_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SignalAllDriversConnectedEvent,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "HandoffToTse,"
+ Parent = "BDS_CONTROL_FLOW"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "ReadBootOptions,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "AdjustLegacyBootOptionPriorities,"
+ Parent = "UpdateBootOptionVariables,"
+ Token = "CSM_SUPPORT" "=" "1"
+ Token = "GROUP_BOOT_OPTIONS_BY_TAG" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "UnmaskOrphanDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CollectBootDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "FilterBootDeviceList,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "MatchBootOptionsToDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "DeleteUnmatchedUefiHddBootDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CreateBootOptionsForNewBootDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/*Process Boot Option List*/"
+ Parent = "UpdateBootOptionVariables,"
+ Token = "BDS_PROCESS_BOOT_OPTION_LIST" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "MaskOrphanDevices,"
+ Parent = "UpdateBootOptionVariables,"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SaveLegacyDevOrder,"
+ Parent = "UpdateBootOptionVariables,"
+ Token = "CSM_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SaveBootOptions,"
+ Parent = "UpdateBootOptionVariables,"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SetBootOptionTags,"
+ Parent = "/*Process Boot Option List*/"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "NormalizeBootOptions,"
+ Parent = "/*Process Boot Option List*/"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PreProcessBootOptions,"
+ Parent = "/*Process Boot Option List*/"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SetBootOptionPriorities,"
+ Parent = "/*Process Boot Option List*/"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "PostProcessBootOptions,"
+ Parent = "/*Process Boot Option List*/"
+ InvokeOrder = AfterParent
+End
+
diff --git a/Core/CORE_DXE/CORE_DXESrc.cif b/Core/CORE_DXE/CORE_DXESrc.cif
new file mode 100644
index 0000000..7a2e3d0
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXESrc.cif
@@ -0,0 +1,75 @@
+<component>
+ name = "CORE_DXE Sources(EDK)"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\"
+ RefName = "CORE_DXESrc_EDK"
+[files]
+"CORE_DXESrc.sdl"
+"CORE_DXESrc.mak"
+"CoreSectionExtraction.c"
+"DebugImageInfo.c"
+"DebugImageInfo.h"
+"DebugMask.c"
+"DebugMask.h"
+"dependency.c"
+"Dispatcher.c"
+"DriverSupport.c"
+"DxeCore.h"
+"DxeMain.c"
+"DxeProtocolNotify.c"
+"event.c"
+"exec.h"
+"execdata.c"
+"Ffs.c"
+"FwVol.c"
+"FwVolAttrib.c"
+"FwVolBlock.c"
+"FwVolBlock.h"
+"FwVolDriver.h"
+"FwVolRead.c"
+"FwVolWrite.c"
+"gcd.c"
+"gcd.h"
+"hand.h"
+"handle.c"
+"Image.c"
+"Image.h"
+"ImageFile.c"
+"imem.h"
+"InstallConfigurationTable.c"
+"Library.c"
+"Library.h"
+"locate.c"
+"memdata.c"
+"Notify.c"
+"Page.c"
+"pool.c"
+"SetWatchdogTimer.c"
+"Stall.c"
+"timer.c"
+"tpl.c"
+"hob.c"
+"AmiDxeInit.c"
+"BDS.c"
+"DataHub.c"
+"UnicodeCollation.c"
+"USFontPack.c"
+"DiskIo.c"
+"GC.c"
+"GenericSio.c"
+"EfiPerf.h"
+"LinkedList.h"
+"DxePerf.c"
+"BootOptions.c"
+"DevicePathToText.c"
+"DevicePathFromText.c"
+"DevicePath.h"
+[parts]
+"ConSplitter"
+"Partition"
+"PS2CTL"
+"FrameworkHii"
+"UefiHii"
+"FirmwareManagement"
+"HashService"
+<endComponent>
diff --git a/Core/CORE_DXE/CORE_DXESrc.mak b/Core/CORE_DXE/CORE_DXESrc.mak
new file mode 100644
index 0000000..e60aca0
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXESrc.mak
@@ -0,0 +1,155 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Core/EDK/DxeMain/CORE_DXESrc.mak 20 10/20/11 7:00p Artems $
+#
+# $Revision: 20 $
+#
+# $Date: 10/20/11 7:00p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/EDK/DxeMain/CORE_DXESrc.mak $
+#
+# 20 10/20/11 7:00p Artems
+# File BootOptions.h moved to Include folder - removed reference to its
+# old place
+#
+# 19 5/05/11 3:45p Artems
+# Added EDKII compatibility library for EDKII code embedded into Core
+#
+# 18 6/29/10 11:06p Felixp
+# New Boot Options Maintenance Infrastructure.
+# See AMI_Aptio_4.x_Boot_Options_Maintenance_Infrastructure_Porting_Guide
+# _NDA.doc for details.
+#
+# 17 11/13/09 3:56p Felixp
+# MM_LEGACY_RESERVE_MEM constant in Page.c is converted to SDL token.
+#
+# 16 10/09/09 6:06p Felixp
+# UEFI 2.1 - related changes (suppot Framework and UEFI HII).
+#
+# 15 3/05/09 1:08p Felixp
+# Minor improvements:
+# - Unconditional optimization (despite debug flag settings) is removed
+# - Headers updated
+#
+# 14 8/31/07 1:55p Felixp
+# Updated to support new location of AMIPostMgr.h. It is moved from
+# Core/em/AMITSE into Include/Protocol
+#
+# 13 4/23/07 1:28p Felixp
+# BootScriptSave removed from CORE_DXE(moved into AcpiS3Save driver)
+#
+# 12 3/13/07 2:04a Felixp
+#
+# 11 2/13/07 12:01p Felixp
+#
+# 10 2/13/07 9:18a Felixp
+# MRE Handshake protocol renamed to AMI POST Manager protocol
+# (MreHandshake.h removed from Core Protocols and added to AMITSE module
+# as AMIPostMgr.h)
+#
+# 9 12/05/06 12:34p Felixp
+#
+# 8 8/24/06 10:11a Felixp
+# Preliminary x64 support (work in progress)
+#
+# 7 5/20/06 12:38a Felixp
+#
+# 6 5/19/06 10:46p Felixp
+# Updated to EDK 03.16.06
+# Cleanup
+#
+# 5 4/14/06 2:21p Felixp
+#
+# 4 4/03/06 3:52p Felixp
+# Major changes in PCI and Super I/O:
+# PCI - Root Bridge Resource Allocation Sepcification support
+# Super I/O - multiple Super I/O support; SIO Setup page added;
+#
+# 3 3/17/06 4:28p Felixp
+#
+# 2 3/13/06 5:25p Felixp
+#
+# 1 3/13/06 2:00a Felixp
+#
+# 4 12/02/05 11:20a Felixp
+#
+# 3 3/24/05 3:35p Felixp
+# FloppyCtrl moved into a separate component
+#
+# 2 2/01/05 1:16a Felixp
+# Floppy and PS2 modules added to the CORE_DXE
+#
+# 1 1/28/05 12:45p Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: CORE_DXESrc.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : CORE_DXE_LIB
+
+$(CORE_DXE_LIB) : CORE_DXE_LIB
+
+CORE_DXE_LIB : $(BUILD_DIR)\CORE_DXESrc.mak CORE_DXE_LIBBin
+
+CORE_DXE_CIFS=\
+$(CORE_DXE_SRC_DIR)\$(@B).cif\
+!IF "$(Partition_SUPPORT)"=="1"
+$(PARTITION_DIR)\Partition.cif\
+!ENDIF
+!IF "$(ConSplitter_SUPPORT)"=="1"
+$(CONSOLE_SPLITTER_DIR)\ConSplitter.cif\
+!ENDIF
+!IF "$(PS2Ctl_SUPPORT)"=="1"
+$(PS2Ctl_DIR)\PS2Ctl.cif\
+!ENDIF
+!IF $(EFI_SPECIFICATION_VERSION)>0x20000
+$(UefiHii_DIR)\UefiHii.cif\
+!ELSE
+$(FrameworkHii_DIR)\FrameworkHii.cif\
+!ENDIF
+
+$(BUILD_DIR)\CORE_DXESrc.mak : $(CORE_DXE_SRC_DIR)\$(@B).mak $(BUILD_RULES) $(CORE_DXE_CIFS)
+ $(CIF2MAK) $(CIF2MAK_DEFAULTS) $(CORE_DXE_CIFS)
+
+CORE_DXE_LIBBin : $(BUILD_DIR)\Foundation.lib $(EDK_II_LIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\CORE_DXESrc.mak all\
+ TYPE=LIBRARY LIBRARY_NAME=$(CORE_DXE_LIB)\
+ "EXT_HEADERS=$(BUILD_DIR)\token.h $(FoundationCpu_DIR)\Processor.h"\
+ "MY_INCLUDES=/I$(CORE_PEI_DIR) /I$(Foundation_DIR) /I$(FoundationCpu_DIR)"\
+ "MY_DEFINES=/DMM_LEGACY_RESERVE_MEM=$(MM_LEGACY_RESERVE_MEM)"\
+ NAME=CORE_DXESrc
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2007, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/CORE_DXE/CORE_DXESrc.sdl b/Core/CORE_DXE/CORE_DXESrc.sdl
new file mode 100644
index 0000000..3fc6362
--- /dev/null
+++ b/Core/CORE_DXE/CORE_DXESrc.sdl
@@ -0,0 +1,57 @@
+TOKEN
+ Name = "CORE_DXESrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable CORE_DXESrc support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "TRACE_START"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "!=" "0"
+End
+
+TOKEN
+ Name = "TRACE_STOP"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "!=" "0"
+End
+
+TOKEN
+ Name = "CURSOR_BLINK_ENABLE"
+ Value = "0"
+ Help = "Enables and Disables the functionality to make the cursor blink"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MM_LEGACY_RESERVE_MEM"
+ Value = "0x1000000"
+ Help = "DXE memory manager will try to keep memory in the range 0 - MM_LEGACY_RESERVE_MEM unallocated. \The memory in the range may still get allocated if the addresses in the range are specifically requested by \the AllocatePages calls, or if there is not enough free memory outside of the region to satisfy the request.\"
+ TokenType = Integer
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "CORE_DXE_SRC_DIR"
+End
+
+MODULE
+ Help = "Includes CORE_DXESrc.mak to Project"
+ File = "CORE_DXESrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CORE_DXE.lib"
+ Parent = "$(CORE_DXE_DIR)\CORE_DXE$(ARCH)$(DBG).lib"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/CORE_DXE/ConSplitter/ConSplit.c b/Core/CORE_DXE/ConSplitter/ConSplit.c
new file mode 100644
index 0000000..6963438
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/ConSplit.c
@@ -0,0 +1,2387 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.c 7 8/28/13 10:44p Thomaschen $
+//
+// $Revision: 7 $
+//
+// $Date: 8/28/13 10:44p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.c $
+//
+// 7 8/28/13 10:44p Thomaschen
+// Fixed for EIP133747.
+//
+// 6 8/01/13 2:32a Thomaschen
+// Add for EIP109384.
+// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c.
+//
+// 5 6/26/13 3:09a Thomaschen
+// Remove EIP109384.
+//
+// 3 6/04/13 1:55a Thomaschen
+// Fixed for EIP118202.
+//
+// 2 11/15/12 9:53p Wesleychen
+// Update to rev.55 for EIP103887.
+//
+// 55 10/29/12 3:44p Artems
+// [TAG] EIP103887
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Upgrade Serial Redirection to 4.6.3_Terminal_51 with Core
+// 4654, system will hang 0x06.
+// [RootCause] Uninitialized variable was used
+// [Solution] Initialize DeviceModeNumber variable before using
+// [Files] ConSplit.c
+//
+// 54 10/25/12 2:31a Deepthins
+// [TAG] EIP99475
+// [Category] Improvement
+// [Description] Multi language module Support in the console splitter
+// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h
+//
+// 53 10/08/12 4:28p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] system boots in wrong text mode
+// [RootCause] Incorrect restore of graphics mode after legacy OPROM
+// execution
+// [Solution] Added code for correct restoration of system state after
+// execution of Consplit.stop function
+// [Files] Consplit.c
+//
+// 52 8/13/12 3:39p Artems
+// [TAG] EIP95607
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Execute nsh script and redirect output to file, then exit
+// from shell, setup screen will crash
+// [RootCause] Console splitter maintains global pool of supportedmodes.
+// It's getting adjusted every time new SimpleTextOut (STO) is installed
+// If new STO doesn't support particular mode it is getting marked as
+// unsupported in global pool
+// However once this STO is uninstalled global pool isn't updated, so mode
+// is still marked as unsupported,
+// though system can support it
+// [Solution] Do not connect simpleTextOut driver if it doesn'tsupport
+// mode splitter is in
+// [Files] Consplit.c
+//
+// 51 8/02/12 12:13p Artems
+// [TAG] EIP95607
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Execute nsh script and redirect output to file, then exit
+// from shell, setup screen will crash
+// [RootCause] Console splitter maintains global pool of supported
+// modes.
+// It's getting adjusted every time new SimpleTextOut (STO) is installed
+// If new STO doesn't support particular mode it is getting marked as
+// unsupported in global pool
+// However once this STO is uninstalled global pool isn't updated, so mode
+// is still marked as unsupported,
+// though system can support it
+// [Solution] Added reinitilization of global pool of supported modes on
+// STO uninstall event
+// [Files] Consplit.h Consplit.c
+//
+// 50 7/06/12 11:28a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Support for monitor native resolution
+// [Files] GC.c, Consplit.c, Out.c, Core_Dxe.sdl
+//
+// 49 12/15/11 12:15p Felixp
+// [TAG] EIP73410
+// [Category] Improvement
+// [Description] InstallSimplePointerDevice function is updated to
+// initialize
+// LeftButton and RightButton fields of the
+// EFI_SIMPLE_POINTER_MODE structure exposed by
+// the splitter based on capabilities of the available mouse devices.
+//
+// 48 8/12/11 12:19p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 47 7/11/11 10:10a Felixp
+// Improvement (EIP 64049):
+// REPORT_NO_CON_OUT_ERROR and REPORT_NO_CON_IN_ERROR SDL tokens are added
+// to enable/disable reporting of the console errors.
+//
+// 46 5/13/11 3:37p Felixp
+// Minor improvement in CSStop: the screen is now saved after closing the
+// protocol
+//
+// 45 5/05/11 3:52p Artems
+// Added multi-language keyboard support
+//
+// 44 2/25/11 12:33p Artems
+// EIP 53767 - disable reporting keyboard absence on fast boot path
+//
+// 43 11/15/10 4:59p Felixp
+//
+// 41 9/24/10 3:38p Felixp
+// Enhancement(EIP 43535):
+// The pST->ConOut pointer used to be initialized once all ConOut
+// device are connected. The Console Splitter driver is updated
+// to initialize ConOut-related fields of the systems table
+// early (in the entry point) to workaround bugs in some of the
+// UEFI OpROM drivers that are using pST->ConOut without NULL checking.
+//
+// 40 9/24/10 7:39a Felixp
+// Additional checks for DXE_NO_CON_OUT and DXE_NO_CON_IN errors are
+// added.
+// The errors are now reported when no console devices with device path
+// available.
+//
+// 39 8/10/10 2:31p Vyacheslava
+// Simple Pointer Protocol bug fixes. (EIP#41832)
+//
+// 38 6/23/10 3:02p Felixp
+// SimplePointer splitter support is added.
+//
+// 37 2/19/10 9:58a Artems
+// Merged previous changes
+//
+// 36 2/12/10 6:13p Artems
+// EIP 34632 Added modification of MasterMode.MaxMode value if one of
+// children does not support Mode 2 or higher
+//
+// 34 8/28/09 9:07a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 33 7/08/09 4:42p Artems
+// Added missing functions headers
+//
+// 32 7/07/09 3:35p Artems
+// Added functions headers according to code standard
+//
+// 31 6/16/09 5:50p Artems
+// EIP 21415 Fixed error with CursorVisible variable
+//
+// 30 1/16/09 5:27p Felixp
+// Bug fix.
+// Headless systems hanging(EIP 18165).
+// Symptoms: Systems with no console output devices were hanging towards
+// the end of the boot process (prior to OS handoff).
+// Details: Some of the global variables used by console splitter
+// implementation
+// of TxtOut were only initialized once first physical console output
+// device is detected,
+// which was never happenning of a headless system.
+// The conosle splitter is updated to properly initialize the globals
+// when no actual console output devices are available.
+// UpdateSystemTableConOut function is updated.
+//
+// 29 1/05/09 3:11p Felixp
+// Minor update of UpdateSystemTableConOut.
+// Callback event is closed at the end of the function
+// (system table needs to be populated only once).
+//
+// 28 10/09/08 2:50p Felixp
+// StdErr and StandardErrorHandle initialization added
+//
+// 27 1/31/08 12:00p Olegi
+// Numlock bootup state made setup driven.
+//
+// 26 10/23/07 4:07p Olegi
+// Added a call to syncronize LEDs of ConIn devices during Start.
+//
+// 25 10/23/07 10:12a Felixp
+// Bug fix: after boot to Shell big part of the small AMI logo stayed on
+// the screen.
+// It was only happenning when two conditions were met: serial redirection
+// was turned off and plug in card with the option ROM was connected to
+// the system.
+//
+// 24 9/17/07 4:04p Olegi
+// Added support for AMI_EFIKEYCODE_PROTOCOL and
+// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+//
+// 23 9/05/07 5:43p Felixp
+// Report errors when no ConIn and ConOut devices are not available.
+//
+// 22 9/05/07 11:13a Felixp
+// SimpleTextInEx support removed. It causes problems. Support will add
+// again after Core labeling.
+//
+// 20 1/05/07 5:32p Artems
+//
+// 19 12/29/06 3:01p Felixp
+// 1. Support for GraphicsOutput protocol added
+// 2. Support for more then one text mode added
+//
+// 18 9/27/06 7:42p Felixp
+// SetMode funciton of the ConsoleControl protocol is updated to restore
+// default UGA mode when switching from grphics to text.
+//
+// 17 9/13/06 6:16p Felixp
+// pST->ConOut initialization logic changed: it is now initialized
+// immediately after the first ConOut device has been connected
+//
+// 16 3/13/06 2:37a Felixp
+//
+// 15 12/12/05 8:36p Felixp
+// RestoreTheScreen update: Restore Cursor Status
+//
+// 14 12/12/05 9:32a Felixp
+// Support for synchronization of console devices
+// (now screen is restored after legacy OpROM execution).
+//
+// 13 11/07/05 10:37a Felixp
+// LockStdIn function of ConsoleControl protocol implemented
+//
+// 12 7/15/05 7:17p Felixp
+// CONSOLE_DEVICES_STARTED_PROTOCOL_GUID added.
+// BDS uses it to notify Splitter that Console Devices have been started.
+// Once Splitter receives notification, it will install ConIn and ConOut
+// in System Table
+//
+// 11 5/27/05 12:16p Felixp
+//
+// 10 5/27/05 12:47a Felixp
+// Support for ConsoleControl protocol added
+//
+// 9 4/08/05 7:40a Felixp
+// fix: from now on when new device added, others not cleared
+//
+// 8 3/04/05 9:17a Mandal
+//
+// 7 2/24/05 5:30p Felixp
+// 1. Coded added to Start/Stop functions to open processed handles in
+// BY_CHILD_CONTROLLER mode
+// 2. GetControllerName implemented
+//
+// 6 2/11/05 6:11p Felixp
+// Logic to update ConDev variables
+//
+// 5 2/02/05 4:20p Felixp
+//
+// 3 2/02/05 2:32p Felixp
+// Splitter opens TxtIn and TxtOut in BY_DRIVER mode (used to be
+// GET_PROTOCOL)
+//
+// 2 2/01/05 1:17a Felixp
+//
+// 1 1/28/05 1:16p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/07/05 11:57a Felixp
+//
+// 3 1/04/05 5:15p Robert
+// Changed component name to be more consistent with the other drivers
+// that have been developed
+//
+// 2 1/03/05 5:47p Robert
+// Working beta version of the consplitter
+//
+// 1 12/30/04 9:47a Robert
+// Initial check in
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ConSplit.c
+//
+// Description: Console Splitter driver that creates a cetralized input and
+// output console so that the correct data is going to and coming
+// from the correct devices
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------------
+
+#include "ConSplit.h"
+#include <Protocol/DevicePath.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/HiiDataBase.h>
+#include <Setup.h>
+#include <Dxe.h>
+#include <Hob.h>
+#include <Token.h>
+
+//----------------------------------------------------------------------------
+
+EFI_HANDLE ConSplitHandle = NULL;
+
+DLIST ConInList;
+DLIST ConOutList;
+DLIST ConPointerList;
+DLIST ConInKeyNotifyList;
+
+EFI_KEY_TOGGLE_STATE mCSToggleState = TOGGLE_STATE_VALID;
+BOOLEAN NumLockSet = FALSE;
+static BOOLEAN InitModesTableCalled = FALSE;
+
+static EFI_GUID gSimpleTextOutGuid = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
+static EFI_GUID gSimpleInGuid = EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
+static EFI_GUID gSimpleInExGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
+static EFI_GUID gAmiEfiKeycodeGuid = AMI_EFIKEYCODE_PROTOCOL_GUID;
+static EFI_GUID gSimplePointerGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID;
+static EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static EFI_GUID gAmiMultiLangSupportGuid = AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID;
+
+extern SIMPLE_TEXT_OUTPUT_MODE MasterMode;
+
+
+EFI_STATUS InstallConOutDevice(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut,
+ IN EFI_HANDLE Handle
+ );
+
+EFI_STATUS InstallConInDevice(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn,
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx,
+ IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn,
+ IN EFI_HANDLE Handle
+ );
+
+EFI_STATUS InstallSimplePointerDevice(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer,
+ IN EFI_HANDLE Handle
+ );
+
+EFI_STATUS ConOutHandleCheck(
+ IN EFI_HANDLE Handle
+ );
+
+EFI_STATUS ConInHandleCheck(
+ IN EFI_HANDLE Handle
+ );
+
+VOID CSSetKbLayoutNotifyFn(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+);
+
+EFI_HII_DATABASE_PROTOCOL *HiiDatabase = NULL;
+EFI_HII_KEYBOARD_LAYOUT *gKeyDescriptorList = NULL;
+UINT16 KeyDescriptorListSize = 0;
+static EFI_GUID SetKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;
+
+EFI_STATUS ConSimplePointerHandleCheck( IN EFI_HANDLE Handle );
+
+EFI_DRIVER_BINDING_PROTOCOL gConSplitterDriverBindingProtocol = {
+ CSSupported,
+ CSStart,
+ CSStop,
+ 0x10,
+ NULL,
+ NULL
+ };
+AMI_MULTI_LANG_SUPPORT_PROTOCOL gMultiLangSupportProtocol = {
+ KeyboardLayoutMap
+};
+
+#ifdef EFI_DEBUG
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+static CHAR16 *gDriverName=L"AMI Console Splitter Driver";
+static CHAR16 *gControllerName=L"AMI Console Splitter";
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: ComponentNameGetControllerName
+//
+// Description:
+// EFI_COMPONENT_NAME_PROTOCOL GetControllerName function
+//
+// Input:
+// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance
+// IN EFI_HANDLE Controller - controller handle
+// IN EFI_HANDLE ChildHandle - child handle
+// IN CHAR8* Language - pointer to language description
+// OUT CHAR16** ControllerName - pointer to store pointer to controller name
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - controller name returned
+// EFI_INVALID_PARAMETER - language undefined
+// EFI_UNSUPPORTED - given language not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+)
+{
+ //Supports only English
+ if(!Language || !ControllerName)
+ return EFI_INVALID_PARAMETER;
+
+ if ( ChildHandle!=ConSplitHandle
+ || !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)
+ ) return EFI_UNSUPPORTED;
+
+ *ControllerName=gControllerName;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: ComponentNameGetDriverName
+//
+// Description:
+// EFI_COMPONENT_NAME_PROTOCOL GetDriverName function
+//
+// Input:
+// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance
+// IN CHAR8* Language - pointer to language description
+// OUT CHAR16** DriverName - pointer to store pointer to driver name
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver name returned
+// EFI_INVALID_PARAMETER - language undefined
+// EFI_UNSUPPORTED - given language not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS ComponentNameGetDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+)
+{
+ //Supports only English
+ if(!Language || !DriverName)
+ return EFI_INVALID_PARAMETER;
+
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH))
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName=gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+//Component Name Protocol
+static EFI_COMPONENT_NAME2_PROTOCOL gComponentName = {
+ ComponentNameGetDriverName,
+ ComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+#endif
+
+EFI_CONSOLE_CONTROL_SCREEN_MODE ScreenMode = EfiConsoleControlScreenText;
+BOOLEAN CursorVisible = TRUE;
+BOOLEAN StdInLocked = FALSE;
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: GetMode
+//
+// Description:
+// This function returns current console mode
+//
+// Input:
+// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol
+// OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode - placeholder for mode to return
+// OUT OPTIONAL BOOLEAN *UgaExists - if not NULL on return will have current UGA present state
+// OUT OPTIONAL BOOLEAN *StdInLocked - if not NULL on return will have value of STD_IN_LOCKED state
+//
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function returns correct values
+//
+// Modified:
+//
+// Referrals:
+// ScreenMode
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS GetMode(
+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
+ OUT BOOLEAN *UgaExists OPTIONAL,
+ OUT BOOLEAN *StdInLocked OPTIONAL
+)
+{
+ if (Mode) *Mode = ScreenMode;
+ if (UgaExists) *UgaExists = TRUE;
+ if (StdInLocked) *StdInLocked = FALSE;
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SetMode
+//
+// Description:
+// This function sets current console mode
+//
+// Input:
+// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol
+// IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode - mode to set
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - mode set successfully
+// EFI_INVALID_PARAMETER - incorrect mode given
+//
+// Modified:
+// ScreenMode
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS SetMode(
+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
+)
+{
+ if (ScreenMode != Mode)
+ {
+ ScreenMode = Mode;
+ if (ScreenMode == EfiConsoleControlScreenText)
+ {
+ //Restore UGA mode when switching from graphics to text
+ DLINK *ListPtr = ConOutList.pHead;
+ CON_SPLIT_OUT *SimpleOut;
+ while ( ListPtr != NULL)
+ {
+ SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT);
+ RestoreUgaMode(SimpleOut->Handle);
+ ListPtr = ListPtr->pNext;
+ }
+
+ if (CursorVisible)
+ mCSOutProtocol.EnableCursor(&mCSOutProtocol,TRUE);
+ }
+ else if (ScreenMode == EfiConsoleControlScreenGraphics)
+ {
+ DLINK *ListPtr = ConOutList.pHead;
+ CON_SPLIT_OUT *SimpleOut;
+ CursorVisible = MasterMode.CursorVisible;
+ if (CursorVisible)
+ mCSOutProtocol.EnableCursor(&mCSOutProtocol,FALSE);
+ //Save UGA mode when switching from text to graphics
+ while ( ListPtr != NULL)
+ {
+ SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT);
+ SaveUgaMode(SimpleOut->Handle);
+ ListPtr = ListPtr->pNext;
+ }
+
+ }
+ else return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: LockStdIn
+//
+// Description:
+// This function toggles STD_IN_LOCKED state
+//
+// Input:
+// IN EFI_CONSOLE_CONTROL_PROTOCOL *This - pointer to console protocol
+// IN CHAR16 *Password - pointer to password string
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+//
+// Modified:
+// StdInLocked
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS LockStdIn(
+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
+ IN CHAR16 *Password
+)
+{
+ //TODO: add support for the password
+ StdInLocked = !StdInLocked;
+ return EFI_SUCCESS;
+};
+
+EFI_GUID gConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
+
+EFI_CONSOLE_CONTROL_PROTOCOL gConsoleControlProtocol = {
+ GetMode,
+ SetMode,
+ LockStdIn
+};
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateSystemTableConOut
+//
+// Description:
+// This function updates system table ConOut pointer
+//
+// Input:
+// IN EFI_EVENT Event - signalled event
+// IN VOID *Context - pointer to event context
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID UpdateSystemTableConOut()
+{
+ UINT32 CRC32 = 0;
+
+ if( ConOutList.Size==0 ){
+ //Initialize all the global variables used by
+ //splitter implementation of TxtOut.
+ //When physical ConOut devices are available, the initialization is performed
+ //within InitModesTable routine.
+ VERIFY_EFI_ERROR(ResizeSplitterBuffer(0));
+ VERIFY_EFI_ERROR(pBS->AllocatePool(EfiBootServicesData, sizeof(SUPPORT_RES), &SupportedModes));
+ SupportedModes[0].Rows = 25;
+ SupportedModes[0].Columns = 80;
+ SupportedModes[0].AllDevices = TRUE;
+ }
+
+ pST->ConOut = &mCSOutProtocol;
+ pST->ConsoleOutHandle = ConSplitHandle;
+ // We want to initialize ConOut-related fields of the systems table early
+ // to workaround bugs in some of the UEFI OpROM drivers
+ // that are using pST->ConOut without NULL checking.
+ // We are not installing the instance of SimpleTextOut on ConSplitHandle though,
+ // because it confuses the logic of TSE notification callbacks.
+ // The protocol is installed once all ConOut devices are connected
+ // in ReportNoConOutError.
+ if (pST->StdErr==NULL){
+ pST->StdErr = pST->ConOut;
+ pST->StandardErrorHandle = pST->ConsoleOutHandle;
+ }
+
+ // Now calculate the CRC32 value
+ pST->Hdr.CRC32 = 0;
+ pST->BootServices->CalculateCrc32(pST, sizeof(EFI_SYSTEM_TABLE), &CRC32);
+ pST->Hdr.CRC32 = CRC32;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ReportNoConOutError
+//
+// Description:
+// This function checks if physical ConOut devices are available.
+// If not, DXE_NO_CON_OUT error is reported.
+//
+// Input:
+// IN EFI_EVENT Event - signalled event
+// IN VOID *Context - pointer to event context
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID ReportNoConOutError(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+#if REPORT_NO_CON_OUT_ERROR
+ DLINK *Link;
+ EFI_STATUS Status;
+
+ //Report error if no ConOut devices available or
+ // all console devices are fake devices (without device path).
+ for(Link = ConOutList.pHead; Link!=NULL; Link=Link->pNext){
+ CON_SPLIT_OUT *SimpleOut = OUTTER(Link, Link, CON_SPLIT_OUT);
+ VOID *Dp;
+
+ Status = pBS->HandleProtocol(
+ SimpleOut->Handle, &gEfiDevicePathProtocolGuid, &Dp
+ );
+ if (!EFI_ERROR(Status)) break; // Got one device path
+ }
+ //Report error if no ConOut devices with device path exists
+ if( ConOutList.Size==0 || EFI_ERROR(Status) )
+ ERROR_CODE(DXE_NO_CON_OUT, EFI_ERROR_MAJOR);
+#endif
+ pBS->InstallMultipleProtocolInterfaces (
+ &ConSplitHandle, &gSimpleTextOutGuid, &mCSOutProtocol,
+ &gConsoleControlProtocolGuid, &gConsoleControlProtocol,
+ NULL
+ );
+ pBS->CloseEvent(Event);
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateSystemTableConIn
+//
+// Description:
+// This function updates system table ConIn pointer
+//
+// Input:
+// IN EFI_EVENT Event - signalled event
+// IN VOID *Context - pointer to event context
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID UpdateSystemTableConIn(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ UINT32 CRC32 = 0;
+
+#if REPORT_NO_CON_IN_ERROR
+ DLINK *Link;
+ EFI_STATUS Status;
+
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ static EFI_GUID guidHob = HOB_LIST_GUID;
+
+ //Report error if no ConIn devices available or
+ // all console devices are fake devices (without device path).
+ for(Link = ConInList.pHead; Link!=NULL; Link=Link->pNext){
+ CON_SPLIT_IN *SimpleIn = OUTTER(Link, Link, CON_SPLIT_IN);
+ VOID *Dp;
+
+ Status = pBS->HandleProtocol(
+ SimpleIn->Handle, &gEfiDevicePathProtocolGuid, &Dp
+ );
+ if (!EFI_ERROR(Status)) break; // Got one device path
+ }
+
+ pHit = GetEfiConfigurationTable(pST, &guidHob);
+ //Report error if no ConIn devices with device path exists
+ if( (ConInList.Size == 0 || EFI_ERROR(Status)) && (pHit->BootMode == BOOT_WITH_FULL_CONFIGURATION))
+ ERROR_CODE(DXE_NO_CON_IN, EFI_ERROR_MAJOR);
+#endif
+ pST->ConIn = &mCSSimpleInProtocol;
+
+ pBS->InstallMultipleProtocolInterfaces (
+ &ConSplitHandle,
+ &gSimpleInGuid, &mCSSimpleInProtocol,
+ &gSimpleInExGuid, &mCSSimpleInExProtocol,
+ &gAmiEfiKeycodeGuid, &mCSKeycodeInProtocol,
+ &gEfiSimplePointerProtocolGuid, &mCSSimplePointerProtocol,
+ NULL
+ );
+
+ pST->ConsoleInHandle = ConSplitHandle;
+
+ // Now calculate the CRC32 value
+ pST->Hdr.CRC32 = 0;
+ pST->BootServices->CalculateCrc32(pST, sizeof(EFI_SYSTEM_TABLE), &CRC32);
+ pST->Hdr.CRC32 = CRC32;
+
+ pBS->CloseEvent(Event);
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSEntryPoint
+//
+// Description:
+// This function is Console splitter driver entry point
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - image handle of Console splitter driver
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver installed successfully
+// EFI_ERROR - error occured during execution
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ static EFI_GUID guidConInStarted = CONSOLE_IN_DEVICES_STARTED_PROTOCOL_GUID;
+ static EFI_GUID guidConOutStarted = CONSOLE_OUT_DEVICES_STARTED_PROTOCOL_GUID;
+ // {8FF925F1-8624-4d38-9ED2-F8F5AA94F84A}
+ static EFI_GUID gDummyProtocolGuid =
+ { 0x8ff925f1, 0x8624, 0x4d38, { 0x9e, 0xd2, 0xf8, 0xf5, 0xaa, 0x94, 0xf8, 0x4a } };
+
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ VOID *pRegistration;
+ SETUP_DATA *SetupData = NULL;
+ UINTN VariableSize = 0;
+ EFI_GUID SetupGuid = SETUP_GUID;
+
+ // initialize AMI library
+ InitAmiLib(ImageHandle, SystemTable);
+
+ // initiaize the ImageHandle and DriverBindingHandle
+ gConSplitterDriverBindingProtocol.DriverBindingHandle = NULL;
+ gConSplitterDriverBindingProtocol.ImageHandle = ImageHandle;
+
+ // Install driver binding protocol here
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &gConSplitterDriverBindingProtocol.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &gConSplitterDriverBindingProtocol,
+#ifdef EFI_DEBUG
+ &gEfiComponentName2ProtocolGuid, &gComponentName,
+#endif
+ &gAmiMultiLangSupportGuid, &gMultiLangSupportProtocol,
+ NULL);
+
+ // Create and event for the Simple In Interface
+ Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY,
+ CSWaitForKey, &mCSSimpleInProtocol,
+ &mCSSimpleInProtocol.WaitForKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Create and event for the SimpleInEx Interface
+ Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY,
+ CSWaitForKey, &mCSSimpleInExProtocol,
+ &mCSSimpleInExProtocol.WaitForKeyEx
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ // Create and event for the KeycodeIn Interface
+ Status = pBS->CreateEvent (EFI_EVENT_NOTIFY_WAIT, TPL_NOTIFY,
+ CSWaitForKey, &mCSKeycodeInProtocol,
+ &mCSKeycodeInProtocol.WaitForKeyEx
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Create an event for the SimplePointer Interface
+ Status = pBS->CreateEvent(
+ EFI_EVENT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ ConSplitterSimplePointerWaitForInput,
+ &mCSSimplePointerProtocol,
+ &mCSSimplePointerProtocol.WaitForInput
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ // Initialize the global lists here
+ DListInit(&ConInList);
+ DListInit(&ConOutList);
+ DListInit(&ConPointerList);
+ DListInit(&ConInKeyNotifyList);
+
+ // Register Protocol Notification to expose
+ // Console Splitter interface only after all consoles initialized
+ RegisterProtocolCallback(
+ &guidConOutStarted, ReportNoConOutError,
+ NULL, &Event,&pRegistration
+ );
+ RegisterProtocolCallback(
+ &guidConInStarted, UpdateSystemTableConIn,
+ NULL, &Event,&pRegistration
+ );
+
+ //We need a valid handle
+ //The only way to create it is to install a protocol
+ //Let's install a dummy protocol
+ pBS->InstallMultipleProtocolInterfaces (
+ &ConSplitHandle,
+ &gDummyProtocolGuid, NULL,
+ NULL
+ );
+
+ //install pST->ConOut
+ UpdateSystemTableConOut();
+
+//multi keyboard layout support
+ Status = pBS->CreateEventEx(
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CSSetKbLayoutNotifyFn,
+ NULL,
+ &SetKeyboardLayoutEventGuid,
+ &Event);
+ CSSetKbLayoutNotifyFn(NULL, NULL);
+
+ // Lighten up the keyboard(s) lights
+ if(NumLockSet == FALSE) {
+ Status = GetEfiVariable(L"Setup", &SetupGuid, NULL, &VariableSize, &SetupData);
+ if (!EFI_ERROR(Status)) {
+ if (SetupData->Numlock) {
+ mCSToggleState |= NUM_LOCK_ACTIVE;
+ }
+ pBS->FreePool(SetupData);
+ }
+ NumLockSet=TRUE;
+ }
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSSupported
+//
+// Description:
+// This function is Console splitter driver Supported function for driver
+// binding protocol
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver supports given controller
+// EFI_UNSUPPORTED - driver doesn't support given controller
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn = NULL;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx = NULL;
+ AMI_EFIKEYCODE_PROTOCOL *KeycodeIn = NULL;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut = NULL;
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer = NULL;
+ EFI_STATUS SimplePointerStatus;
+ EFI_STATUS OutStatus;
+ EFI_STATUS InStatus;
+ EFI_STATUS InExStatus;
+ EFI_STATUS KeycodeInStatus;
+ INT32 Dummy;
+
+ if (ControllerHandle == ConSplitHandle)
+ return EFI_UNSUPPORTED;
+
+ // check to see if this device has a simple text out protocol installed on it
+ OutStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleTextOutGuid,
+ &SimpleOut, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if(!EFI_ERROR(OutStatus)) {
+ OutStatus = IsModeSupported(SimpleOut, MasterMode.Mode, &Dummy);
+ if(EFI_ERROR(OutStatus)) {
+ pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ This->DriverBindingHandle, ControllerHandle);
+ }
+ }
+
+
+ // check to see if this device has a simple input protocol installed on it
+ InStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleInGuid,
+ &SimpleIn, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ InExStatus = pBS->OpenProtocol ( ControllerHandle, &gSimpleInExGuid,
+ &SimpleInEx, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ KeycodeInStatus = pBS->OpenProtocol ( ControllerHandle, &gAmiEfiKeycodeGuid,
+ &KeycodeIn, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ // check if device has simple pointer protocol installed on it
+ SimplePointerStatus = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ &SimplePointer,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR(SimplePointerStatus))
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ if (!EFI_ERROR(OutStatus))
+ pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ if (!EFI_ERROR(InStatus))
+ pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ if (!EFI_ERROR(InExStatus))
+ pBS->CloseProtocol(ControllerHandle, &gAmiEfiKeycodeGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ if (!EFI_ERROR(KeycodeInStatus))
+ pBS->CloseProtocol(ControllerHandle, &gSimpleInExGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ if ( EFI_ERROR(SimplePointerStatus) &&
+ EFI_ERROR(OutStatus) &&
+ EFI_ERROR(InStatus) &&
+ EFI_ERROR(InExStatus) &&
+ EFI_ERROR(KeycodeInStatus) )
+ return EFI_UNSUPPORTED;
+
+ return EFI_SUCCESS;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSStart
+//
+// Description:
+// This function is Console splitter driver Start function for driver
+// binding protocol
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver started successfully
+// EFI_UNSUPPORTED - driver didn't start
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSStart(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn = NULL;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx = NULL;
+ AMI_EFIKEYCODE_PROTOCOL *KeycodeIn = NULL;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut = NULL;
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer = NULL;
+ EFI_STATUS Status;
+ EFI_STATUS OutStatus;
+ EFI_STATUS InStatus;
+ EFI_STATUS InExStatus;
+ EFI_STATUS KeycodeInStatus;
+
+ // grab the pointers for the ConIn, ConOut, and StdErr from the System Table
+ // install the current handles for these devices.
+
+ // if Simple In, add the Con In device to the list and
+ InStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleInGuid,
+ &SimpleIn, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ InExStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleInExGuid,
+ &SimpleInEx, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ KeycodeInStatus = pBS->OpenProtocol(ControllerHandle, &gAmiEfiKeycodeGuid,
+ &KeycodeIn, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+
+ if (!EFI_ERROR(InStatus) || !EFI_ERROR(InExStatus) || !EFI_ERROR(KeycodeInStatus))
+ {
+ InStatus = InstallConInDevice(SimpleIn, SimpleInEx, KeycodeIn, ControllerHandle);
+ if (InStatus == EFI_OUT_OF_RESOURCES)
+ return InStatus;
+
+ if (!EFI_ERROR(InStatus))
+ pBS->OpenProtocol(ControllerHandle, &gSimpleInGuid,
+ &SimpleIn, This->DriverBindingHandle,
+ ConSplitHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+ }
+
+ Status = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ &SimplePointer,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR(Status)) {
+ Status = InstallSimplePointerDevice( SimplePointer, ControllerHandle );
+ if (!EFI_ERROR(Status)) {
+ Status = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ &SimplePointer,
+ This->DriverBindingHandle,
+ ConSplitHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else if (Status == EFI_OUT_OF_RESOURCES)
+ return Status;
+ }
+
+ // if it has a simple text out add the Con Out device to the list and
+ OutStatus = pBS->OpenProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ &SimpleOut, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (!EFI_ERROR(OutStatus) )
+ {
+ OutStatus = InstallConOutDevice(SimpleOut, ControllerHandle);
+ if (OutStatus == EFI_OUT_OF_RESOURCES)
+ return OutStatus;
+
+ if (!EFI_ERROR(OutStatus))
+ {
+ RestoreTheScreen(ControllerHandle,SimpleOut);
+ pBS->OpenProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ &SimpleOut, This->DriverBindingHandle,
+ ConSplitHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+ }
+ }
+
+ // If no devices were installed, then Houston we have a problem
+ if ( EFI_ERROR(OutStatus) && EFI_ERROR(InStatus) && EFI_ERROR(Status) )
+ return EFI_UNSUPPORTED;
+
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSStop
+//
+// Description:
+// This function is Console splitter driver Stop function for driver
+// binding protocol
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to driver binding protocol
+// IN EFI_HANDLE ControllerHandle - controller handle to install driver on
+// IN UINTN NumberOfChildren - number of childs on this handle
+// IN OPTIONAL EFI_HANDLE *ChildHandleBuffer - pointer to child handles array
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver stopped successfully
+// EFI_INVALID_PARAMETER - invalid values passed for NumberOfChildren or
+// ChildHandleBuffer
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+)
+{
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+ DLINK *ListPtr;
+ CON_SPLIT_IN *SimpleIn;
+ CON_SPLIT_OUT *SimpleOut;
+ CON_SPLIT_SIMPLE_POINTER *SimplePointer = NULL;
+ BOOLEAN Stopped = FALSE;
+ DLINK *HandleLink = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL;
+
+ if (NumberOfChildren == 0)
+ return EFI_SUCCESS;
+
+ if ( NumberOfChildren != 1 ||
+ ChildHandleBuffer == NULL ||
+ *ChildHandleBuffer!= ConSplitHandle )
+ return EFI_INVALID_PARAMETER;
+
+ // remove simple text out, simple in, simple pointer
+ ListPtr = ConOutList.pHead;
+ while ( ListPtr != NULL)
+ {
+ SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT);
+ if ( SimpleOut->Handle == ControllerHandle)
+ {
+ pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ pBS->CloseProtocol(ControllerHandle, &gSimpleTextOutGuid,
+ This->DriverBindingHandle, ConSplitHandle);
+ DListDelete(&ConOutList, ListPtr);
+ Stopped = TRUE;
+ SaveTheScreen(ControllerHandle, SimpleOut->SimpleOut);
+ Status = pBS->FreePool(SimpleOut);
+ break;
+ }
+
+ ListPtr = ListPtr->pNext;
+ }
+
+ //If we already populated pST->ConOut preserve
+ //screen buffer and list of supported modes
+ //to keep using it when ConOut devices are connected
+ if(ConOutList.Size == 0 && !pST->ConOut) //all devices stops
+ {
+ if(SupportedModes != NULL)
+ {
+ pBS->FreePool(SupportedModes);
+ SupportedModes = NULL;
+ }
+
+ if(ScreenBuffer != NULL)
+ {
+ pBS->FreePool(ScreenBuffer);
+ ScreenBuffer = NULL;
+ }
+
+ if(AttributeBuffer != NULL)
+ {
+ pBS->FreePool(AttributeBuffer);
+ AttributeBuffer = NULL;
+ }
+
+ MasterMode.Mode=0;
+ } else {
+ if(Stopped && ConOutList.Size > 0) //re-initialize supported modes buffer if at least one child was stopped
+ AdjustSupportedModes();
+ }
+
+ ListPtr = ConInList.pHead;
+ while ( ListPtr != NULL)
+ {
+ SimpleIn = OUTTER(ListPtr, Link, CON_SPLIT_IN);
+ if ( SimpleIn->Handle == ControllerHandle)
+ {
+ DListDelete(&ConInList, ListPtr);
+
+ pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ pBS->CloseProtocol(ControllerHandle, &gSimpleInExGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ pBS->CloseProtocol(ControllerHandle, &gAmiEfiKeycodeGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ pBS->CloseProtocol(ControllerHandle, &gSimpleInGuid,
+ This->DriverBindingHandle, ConSplitHandle);
+ break;
+ }
+
+ ListPtr = ListPtr->pNext;
+ }
+
+ if (ListPtr != NULL && SimpleIn->SimpleInEx != NULL) {
+ for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY);
+
+ for (HandleLink = CsInKeyNotify->NotifyHandleList.pHead; HandleLink != NULL;
+ HandleLink = HandleLink->pNext) {
+ CsInNotifyHandle = OUTTER(HandleLink, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE);
+
+ if (SimpleIn->SimpleInEx != CsInNotifyHandle->SimpleInEx) {
+ continue;
+ }
+
+ Status = SimpleIn->SimpleInEx->UnregisterKeyNotify(
+ SimpleIn->SimpleInEx, CsInNotifyHandle->NotifyHandle);
+
+ DListDelete(&(CsInKeyNotify->NotifyHandleList), HandleLink);
+ Status = pBS->FreePool(CsInNotifyHandle);
+ }
+ }
+ Status = pBS->FreePool(SimpleIn);
+ }
+
+ ListPtr = ConPointerList.pHead;
+ while (ListPtr != NULL) {
+ SimplePointer = OUTTER(ListPtr, Link, CON_SPLIT_SIMPLE_POINTER);
+ if ( SimplePointer->Handle == ControllerHandle ) {
+ DListDelete(&ConPointerList, ListPtr);
+
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ This->DriverBindingHandle,
+ ConSplitHandle
+ );
+ Status = pBS->FreePool(SimplePointer);
+ break;
+ }
+ ListPtr = ListPtr->pNext;
+ }
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateConVar
+//
+// Description:
+// This function stores device path of given controller in EFI variable with
+// name sVarName
+//
+// Input:
+// IN EFI_HANDLE Controller - controller, which device path to store
+// IN CHAR16 *sVarName - name of EFI variable to store device path under
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID UpdateConVar(
+ IN EFI_HANDLE Controller,
+ IN CHAR16 *sVarName
+)
+{
+ static EFI_GUID guidDevicePath = EFI_DEVICE_PATH_PROTOCOL_GUID;
+ static EFI_GUID guidEfiVar = EFI_GLOBAL_VARIABLE;
+ EFI_DEVICE_PATH_PROTOCOL *pDevicePath, *pConDev = NULL;
+ EFI_STATUS Status;
+ UINTN DataSize=0;
+ UINT32 Attributes;
+
+ Status = pBS->HandleProtocol(Controller,&guidDevicePath, &pDevicePath);
+ if (EFI_ERROR(Status))
+ return;
+
+ Status = GetEfiVariable(sVarName, &guidEfiVar, &Attributes, &DataSize, &pConDev);
+ if (EFI_ERROR(Status))
+ {
+ if (Status!=EFI_NOT_FOUND)
+ return;
+
+ DataSize = DPLength(pDevicePath);
+ pRS->SetVariable(sVarName, &guidEfiVar,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize, pDevicePath);
+ return;
+ }
+
+ if (!DPIsOneOf(pConDev, pDevicePath, FALSE))
+ {
+ EFI_DEVICE_PATH_PROTOCOL *pNewConDev = DPAddInstance(pConDev, pDevicePath);
+ DataSize = DPLength(pNewConDev);
+ pRS->SetVariable(sVarName, &guidEfiVar, Attributes, DataSize, pNewConDev);
+ pBS->FreePool(pNewConDev);
+ }
+
+ pBS->FreePool(pConDev);
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InstallSimplePointerDevice
+//
+// Description:
+// This function adds another ConIn device to splitter
+//
+// Input:
+// *SimpleIn - pointer to new protocol
+// *SimpleInEx - pointer to new extended protocol
+// *KeycodeIn - pointer to AMI key code protocol
+// Handle - handle of new device
+//
+// Output:
+// EFI_SUCCESS - device added successfully
+// EFI_UNSUPPORTED - device not supported
+// EFI_OUT_OF_RESOURCES - not enough resources to perform operation
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS InstallSimplePointerDevice(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer,
+ IN EFI_HANDLE Handle )
+{
+ EFI_STATUS Status;
+ CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL;
+
+ if (EFI_ERROR(ConSimplePointerHandleCheck(Handle)))
+ return EFI_UNSUPPORTED;
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CON_SPLIT_SIMPLE_POINTER),
+ &ConSimplePointer
+ );
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ ConSimplePointer->SimplePointer = SimplePointer;
+ ConSimplePointer->Handle = Handle;
+ mCSSimplePointerProtocol.Mode->LeftButton |= SimplePointer->Mode->LeftButton;
+ mCSSimplePointerProtocol.Mode->RightButton |= SimplePointer->Mode->RightButton;
+ DListAdd(&ConPointerList, &ConSimplePointer->Link);
+ return EFI_SUCCESS;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InstallConOutDevice
+//
+// Description:
+// This function adds another ConOut device to splitter
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to new protocol
+// IN EFI_HANDLE Handle - handle of new device
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device added successfully
+// EFI_UNSUPPORTED - device not supported
+// EFI_OUT_OF_RESOURCES - not enough resources to perform operation
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS InstallConOutDevice(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut,
+ IN EFI_HANDLE Handle
+)
+{
+ EFI_STATUS Status;
+ CON_SPLIT_OUT *ConOut;
+ INT32 DeviceModeNumber = 0;
+ BOOLEAN FirstChild = FALSE;
+
+ if (EFI_ERROR(ConOutHandleCheck(Handle)))
+ return EFI_UNSUPPORTED;
+
+ if(MasterMode.Mode != 0) //already in extended mode
+ if (EFI_ERROR(IsModeSupported(SimpleOut, MasterMode.Mode, &DeviceModeNumber)))
+ return EFI_UNSUPPORTED; //device doesn't support current mode - do not include into list
+
+
+ if (ConOutList.Size==0 && !InitModesTableCalled) //this is first call
+ {
+ FirstChild = TRUE;
+ Status = InitModesTable(SimpleOut, Handle);
+ if(EFI_ERROR(Status)) //first device becomes master
+ return Status;
+ }
+ else
+ UpdateModesTable(SimpleOut, Handle); //all next devices
+
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(CON_SPLIT_OUT), &ConOut);
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ ConOut->SimpleOut = SimpleOut;
+
+ ConOut->Handle = Handle;
+
+ DListAdd(&ConOutList, &(ConOut->Link));
+
+ if(!FirstChild) {
+ // set child display to a current master mode
+ SimpleOut->SetMode(SimpleOut, DeviceModeNumber);
+ SimpleOut->EnableCursor(SimpleOut, MasterMode.CursorVisible);
+ }
+ UpdateConVar(Handle, L"ConOutDev");
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InstallConInDevice
+//
+// Description:
+// This function adds another ConIn device to splitter
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn - pointer to new protocol
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx - pointer to new extended
+// protocol
+// IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn - pointer to AMI key code protocol
+// IN EFI_HANDLE Handle - handle of new device
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device added successfully
+// EFI_UNSUPPORTED - device not supported
+// EFI_OUT_OF_RESOURCES - not enough resources to perform operation
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS InstallConInDevice(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn,
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx,
+ IN AMI_EFIKEYCODE_PROTOCOL *KeycodeIn,
+ IN EFI_HANDLE Handle
+)
+{
+ EFI_STATUS Status;
+ CON_SPLIT_IN *ConIn;
+ DLINK *ListPtr;
+ CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL;
+
+ if (EFI_ERROR(ConInHandleCheck(Handle)))
+ return EFI_UNSUPPORTED;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(CON_SPLIT_IN), &ConIn);
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ ConIn->SimpleIn = SimpleIn;
+ ConIn->SimpleInEx = SimpleInEx;
+ ConIn->KeycodeInEx = KeycodeIn;
+
+ ConIn->Handle = Handle;
+
+ DListAdd(&ConInList, &(ConIn->Link));
+
+ UpdateConVar(Handle, L"ConInDev");
+
+ if (SimpleInEx == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ SimpleInEx->SetState(SimpleInEx, &mCSToggleState);
+
+ for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY);
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(CON_SPLIT_IN_KEY_NOTIFY_HANDLE), &CsInNotifyHandle);
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CsInNotifyHandle->SimpleInEx = SimpleInEx;
+
+ Status = SimpleInEx->RegisterKeyNotify(SimpleInEx, &CsInKeyNotify->KeyData,
+ CsInKeyNotify->KeyNotificationFunction, &(CsInNotifyHandle->NotifyHandle));
+ if (EFI_ERROR(Status)) {
+ Status = pBS->FreePool(CsInNotifyHandle);
+ continue;
+ }
+
+ DListAdd(&(CsInKeyNotify->NotifyHandleList), &(CsInNotifyHandle->Link));
+ }
+
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConOutHandleCheck
+//
+// Description:
+// This function checks if ConOut device already present in Splitter
+//
+// Input:
+// IN EFI_HANDLE Handle - handle of device to check
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device not present
+// EFI_UNSUPPORTED - device already present
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ConOutHandleCheck(
+ IN EFI_HANDLE Handle
+)
+{
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ // if the list is empty return the status that was passed in
+ if (SimpleOut == NULL)
+ return EFI_SUCCESS;
+
+ // check for a handle that was already identified
+ while ( SimpleOut != NULL)
+ {
+ // check the handle
+ if (SimpleOut->Handle == Handle)
+ return EFI_UNSUPPORTED;
+ // go to the next element in the list
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+ }
+
+ // if it is a new handle return the status pass in
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConInHandleCheck
+//
+// Description:
+// This function checks if ConIn device already present in Splitter
+//
+// Input:
+// IN EFI_HANDLE Handle - handle of device to check
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device not present
+// EFI_UNSUPPORTED - device already present
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ConInHandleCheck(
+ IN EFI_HANDLE Handle
+)
+{
+ CON_SPLIT_IN *SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN);
+
+ // if the list is empty return the status that was passed in
+ if (SimpleIn == NULL)
+ return EFI_SUCCESS;
+
+ // check for a handle that was already identified
+ while ( SimpleIn != NULL)
+ {
+ // check the handle
+ if (SimpleIn->Handle == Handle)
+ return EFI_UNSUPPORTED;
+ // go to the next element in the list
+ SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN);
+ }
+
+ // if it is a new handle return the status pass in
+ return EFI_SUCCESS;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConSimplePointerHandleCheck
+//
+// Description:
+// This function checks if ConIn device already present in Splitter.
+//
+// Input: Handle - handle of device to check
+//
+// Output:
+// EFI_SUCCESS - device not present
+// EFI_UNSUPPORTED - device already present
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ConSimplePointerHandleCheck( IN EFI_HANDLE Handle )
+{
+ CON_SPLIT_SIMPLE_POINTER *SimplePointer;
+
+ SimplePointer = OUTTER(ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER);
+
+ // if the list is empty return the status that was passed in
+ if (SimplePointer == NULL)
+ return EFI_SUCCESS;
+
+ // check for a handle that was already identified
+ while ( SimplePointer != NULL) {
+
+ // check the handle
+ if (SimplePointer->Handle == Handle)
+ return EFI_UNSUPPORTED;
+
+ // go to the next element in the list
+ SimplePointer = OUTTER(SimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER);
+ }
+
+ // if it is a new handle return the status pass in
+ return EFI_SUCCESS;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: InitModesTable
+//
+// Description:
+// This function fills the SupportedModes table with modes supported by first
+// simple text out device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol
+// IN EFI_HANDLE Handle - handle of first ConOut device
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - table filled successfully
+// EFI_OUT_OF_RESOURCES - not enough resources to perform operation
+//
+// Modified: SupportedModes, MasterMode
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS InitModesTable(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN EFI_HANDLE Handle
+)
+{
+ INT32 MaxMode;
+ INT32 CurrentMode;
+ UINTN Rows, Columns;
+ INT32 i;
+ EFI_STATUS Status;
+
+ if(Handle == ConSplitHandle)
+ return EFI_SUCCESS;
+
+ InitModesTableCalled = TRUE;
+
+ MaxMode = This->Mode->MaxMode;
+ CurrentMode = This->Mode->Mode;
+
+ //The SupportedModes structure
+ //may have already been initialized in UpdateSystemTableConOut.
+ //If this is the case, free the memory before reinitialization.
+ if (SupportedModes!=NULL){
+ //If SupportedModes is not NULL,
+ //ResizeSplitterBuffer(0) has already been called
+ pBS->FreePool(SupportedModes);
+ SupportedModes = NULL;
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(SUPPORT_RES)* MaxMode,
+ &SupportedModes);
+ if(EFI_ERROR(Status))
+ {
+ MasterMode.MaxMode = 1;
+ return EFI_SUCCESS;
+ }
+
+ MasterMode.MaxMode = MaxMode; //modify default value
+
+ for(i = 0; i < MaxMode; i++)
+ {
+ Status = This->QueryMode(This, i, &Columns, &Rows);
+ SupportedModes[i].Rows = (INT32)Rows;
+ SupportedModes[i].Columns = (INT32)Columns;
+ SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE;
+ }
+
+//Make sure MasterMode.Mode <> CurrentMode, otherwise ResizeSplitterBuffer won't do anything
+ MasterMode.Mode = CurrentMode + 1;
+ Status = ResizeSplitterBuffer(CurrentMode);
+ MasterMode.Mode = CurrentMode;
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: IsModeSupported
+//
+// Description:
+// This function determines if mode, specified by ModeNum supported by
+// simple text out device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol to check
+// IN UINTN ModeNum - mode to check
+// OUT INT32 *DeviceModeNumber - device mode number correspondent to ModeNum
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - mode supported by device
+// EFI_UNSUPPORTED - mode not supported by device
+//
+// Modified:
+//
+// Referrals: SupportedModes
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS IsModeSupported(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT INT32 *DeviceModeNumber)
+{
+ INT32 MaxMode;
+ UINTN Rows, Columns;
+ INT32 i;
+ EFI_STATUS Status;
+
+ MaxMode = This->Mode->MaxMode;
+ for(i = 0; i < MaxMode; i++)
+ {
+ Status = This->QueryMode(This, i , &Columns, &Rows);
+ if (!EFI_ERROR(Status) && \
+ SupportedModes[ModeNum].Rows == (INT32)Rows && \
+ SupportedModes[ModeNum].Columns == (INT32)Columns)
+ {
+ *DeviceModeNumber = i;
+ return EFI_SUCCESS;
+ }
+
+ }
+ return EFI_UNSUPPORTED;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateModesTable
+//
+// Description:
+// This function updates supported modes table when new devices started don't
+// support some of this modes
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol to check
+// IN EFI_HANDLE Handle - handle of device
+//
+// Output:
+// VOID
+//
+// Modified: SupportedModes
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID UpdateModesTable(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN EFI_HANDLE Handle
+)
+{
+ INT32 i, ModeNumber;
+ EFI_STATUS Status;
+
+ if(Handle == ConSplitHandle)
+ return;
+
+
+ for(i = 0; i < MasterMode.MaxMode; i++) {
+ if(SupportedModes[i].AllDevices == FALSE) continue;
+ Status = IsModeSupported(This, i, &ModeNumber);
+ SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE;
+ }
+
+//update MasterMode.MaxMode value based on modes supported by different devices
+//lookup for the first mode above 1 not supported by all devices - this will be
+//new MaxMode value
+ for(i = 2; i < MasterMode.MaxMode; i++) {
+ if(SupportedModes[i].AllDevices == FALSE) {
+ MasterMode.MaxMode = i;
+ break;
+ }
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ResizeSplitterBuffer
+//
+// Description:
+// This function allocates new buffers when mode changed
+//
+// Input:
+// IN INT32 ModeNum - new mode
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - new buffers allocated
+// EFI_OUT_OF_RESOURCES - not enough resources to perform operation
+//
+// Modified: ScreenBuffer, EndOfTheScreen,AttributeBuffer
+//
+// Referrals: SupportedModes, MasterMode
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ResizeSplitterBuffer(
+ IN INT32 ModeNum
+)
+{
+ INT32 Row, Col;
+ CHAR16 *NewCharBuffer;
+ INT32 *NewAttributeBuffer;
+ EFI_STATUS Status;
+
+ if(ModeNum != MasterMode.Mode || SupportedModes == NULL) //check if it is first init
+ {
+
+ if(SupportedModes == NULL)
+ {
+ Row = 25;
+ Col = 80;
+ }
+ else
+ {
+ Row = SupportedModes[ModeNum].Rows;
+ Col = SupportedModes[ModeNum].Columns;
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(CHAR16) * Row * Col,
+ &NewCharBuffer);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(INT32) * Row * Col,
+ &NewAttributeBuffer);
+ if(EFI_ERROR(Status))
+ {
+ pBS->FreePool(NewCharBuffer);
+ return Status;
+ }
+
+ if(ScreenBuffer != NULL)
+ pBS->FreePool(ScreenBuffer);
+ ScreenBuffer = NewCharBuffer;
+ EndOfTheScreen = ScreenBuffer + (Row * Col);
+
+ if(AttributeBuffer != NULL)
+ pBS->FreePool(AttributeBuffer);
+ AttributeBuffer = NewAttributeBuffer;
+ Columns = Col;
+ }
+ MemClearScreen();
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSSetKbLayoutNotifyFn
+//
+// Description:
+// This function stores a pointer to the current keyboard layout
+//
+// Input:
+// IN EFI_EVENT Event - event that caused this function to be called
+// IN VOID *Context - context of the event
+//
+// Output:
+// VOID
+//
+// Modified:
+// gKeyDescriptorList - changed to point to the current EFI_HII_KEYBOARD_LAYOUT
+// or, NULL if no layout currently set
+// LayoutLength - set to the size of the current keyboard layout
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID CSSetKbLayoutNotifyFn(
+ IN EFI_EVENT Event,
+ IN VOID *Context)
+{
+ EFI_STATUS Status;
+
+ if(HiiDatabase == NULL) {
+ Status = pBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);
+ if(EFI_ERROR(Status))
+ return;
+ }
+
+ Status = HiiDatabase->GetKeyboardLayout(HiiDatabase, NULL, &KeyDescriptorListSize, gKeyDescriptorList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if(gKeyDescriptorList != NULL)
+ pBS->FreePool(gKeyDescriptorList);
+
+ Status = pBS->AllocatePool(EfiBootServicesData, KeyDescriptorListSize, &gKeyDescriptorList);
+ if(EFI_ERROR(Status)) {
+ KeyDescriptorListSize = 0;
+ gKeyDescriptorList = NULL;
+ } else {
+ HiiDatabase->GetKeyboardLayout(HiiDatabase, NULL, &KeyDescriptorListSize, gKeyDescriptorList);
+ }
+ } else if(Status == EFI_NOT_FOUND) {
+ if(gKeyDescriptorList != NULL) {
+ pBS->FreePool(gKeyDescriptorList);
+ KeyDescriptorListSize = 0;
+ gKeyDescriptorList = NULL;
+ }
+ }
+}
+
+VOID AdjustSupportedModes(
+ VOID
+)
+{
+ DLINK *ListPtr;
+ CON_SPLIT_OUT *SimpleOut;
+ EFI_STATUS Status;
+ INT32 i;
+ UINTN Columns;
+ UINTN Rows;
+
+ ListPtr = ConOutList.pHead;
+ SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT);
+
+//re-initialize supported modes buffer
+ if(MasterMode.MaxMode < SimpleOut->SimpleOut->Mode->MaxMode) {
+ if (SupportedModes != NULL)
+ pBS->FreePool(SupportedModes);
+ Status = pBS->AllocatePool(EfiBootServicesData, SimpleOut->SimpleOut->Mode->MaxMode * sizeof(SUPPORT_RES), &SupportedModes);
+ if(EFI_ERROR(Status))
+ return;
+ }
+ MasterMode.MaxMode = SimpleOut->SimpleOut->Mode->MaxMode;
+ for(i = 0; i < MasterMode.MaxMode; i++) {
+ Status = SimpleOut->SimpleOut->QueryMode(SimpleOut->SimpleOut, i, &Columns, &Rows);
+ SupportedModes[i].Rows = (INT32)Rows;
+ SupportedModes[i].Columns = (INT32)Columns;
+ SupportedModes[i].AllDevices = EFI_ERROR(Status) ? FALSE : TRUE;
+ }
+
+//update supported modes buffer
+ ListPtr = ListPtr->pNext;
+ while(ListPtr != NULL) {
+ SimpleOut = OUTTER(ListPtr, Link, CON_SPLIT_OUT);
+ UpdateModesTable(SimpleOut->SimpleOut, SimpleOut->Handle);
+ ListPtr = ListPtr->pNext;
+ }
+}
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: KeyboardLayoutMap
+//
+// Description:
+// This function maps an EFI_KEY to a Unicode character, based on the current
+// keyboard layout
+//
+// Input:
+// IN AMI_EFI_KEY_DATA *KeyData - pointer to the key data returned by a device
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - key was mapped successfully
+// EFI_NOT_FOUND - the key was not found in the keyboard layout
+// EFI_INVALID_PARAMETER - KeyData is NULL
+//
+// Modified:
+// AMI_EFI_KEY_DATA *KeyData - KeyData->Key.UnicodeChar is changed to match
+// the character found in the keyboard layout
+//
+// Referrals:
+// EFI_HII_KEYBOARD_LAYOUT* gKeyDescriptorList - Pointer to the current
+// keyboard layout
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS KeyboardLayoutMap(
+ IN AMI_MULTI_LANG_SUPPORT_PROTOCOL *This,
+ IN OUT AMI_EFI_KEY_DATA *KeyData)
+{
+ EFI_STATUS Status;
+ EFI_KEY_DESCRIPTOR *KeyDescriptor;
+
+ BOOLEAN AltState = FALSE;
+ BOOLEAN ShiftKeyState = FALSE;
+ BOOLEAN ShiftState = ShiftKeyState;
+
+ static UINT16 ModifierIndex = 0xFFFF;
+ static CHAR16 ModifierUnicodeChar = 0x0000;
+
+ UINT16 i = 0;
+
+ if(gKeyDescriptorList== NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ KeyDescriptor = (EFI_KEY_DESCRIPTOR*)&(gKeyDescriptorList->Descriptors);
+
+ // check alt status (left alt or right alt)
+ if( ((KeyData->KeyState.KeyShiftState)&(RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) != 0 )
+ AltState = TRUE;
+
+ if( ((KeyData->KeyState.KeyShiftState)&(RIGHT_SHIFT_PRESSED|LEFT_SHIFT_PRESSED)) != 0 )
+ ShiftKeyState = TRUE;
+
+ Status = EFI_NOT_FOUND;
+ if ( (ModifierIndex != 0xFFFF) && (KeyDescriptor[ModifierIndex].Modifier == EFI_NS_KEY_MODIFIER) ) {
+ // Previous key had a modifier, we need to find out what to do
+ // for now, only handle EFI_NS_KEY_MODIFIER
+ for (i = ModifierIndex+1; KeyDescriptor[i].Modifier == EFI_NS_KEY_DEPENDENCY_MODIFIER && i < gKeyDescriptorList->DescriptorCount; i++) {
+ if(KeyDescriptor[i].Key == KeyData->EfiKey) {
+ if ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_STANDARD_SHIFT) != 0)
+ ShiftState = ShiftKeyState;
+ else
+ ShiftState = FALSE;
+ // account for cAPS lOCK, only applicable if the affected attribute is set
+ if (!AltState && ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_CAPS_LOCK) != 0) && ((KeyData->KeyState.KeyToggleState&CAPS_LOCK_ACTIVE) != 0))
+ ShiftState = !ShiftState;
+
+ if (AltState && ShiftState && (KeyDescriptor[i].ShiftedAltGrUnicode != 0x0000)) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode;
+ Status = EFI_SUCCESS;
+ }
+ else if (AltState && !ShiftState && (KeyDescriptor[i].AltGrUnicode != 0x0000)) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].AltGrUnicode;
+ Status = EFI_SUCCESS;
+ }
+ else if (!AltState && ShiftState && (KeyDescriptor[i].ShiftedUnicode != 0x0000)) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedUnicode;
+ Status = EFI_SUCCESS;
+ }
+ else if (!AltState && !ShiftState && (KeyDescriptor[i].Unicode != 0x0000)) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].Unicode;
+ Status = EFI_SUCCESS;
+ }
+ break;
+ }
+ }
+
+ if (EFI_ERROR(Status))
+ // No match found, just return the deadkey's character
+ KeyData->Key.UnicodeChar = ModifierUnicodeChar;
+ ModifierIndex = 0xFFFF;
+ ModifierUnicodeChar = 0x0000;
+ return EFI_SUCCESS;
+ }
+
+ // Search the KeyDescriptorList for a matching key
+ for(i = 0; i < gKeyDescriptorList->DescriptorCount; i++)
+ {
+ if(KeyDescriptor[i].Key == KeyData->EfiKey || (KeyDescriptor[i].Key == 0xA5A5 && KeyData->PS2ScanCode == 0x73)) {
+ if ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_STANDARD_SHIFT) != 0)
+ ShiftState = ShiftKeyState;
+ else
+ ShiftState = FALSE;
+ // account for cAPS lOCK, only applicable if the affected attribute is set
+ if (!AltState && ((KeyDescriptor[i].AffectedAttribute&EFI_AFFECTED_BY_CAPS_LOCK) != 0) && ((KeyData->KeyState.KeyToggleState&CAPS_LOCK_ACTIVE) != 0))
+ ShiftState = !ShiftState;
+
+ switch (KeyDescriptor[i].Modifier) {
+ case EFI_NULL_MODIFIER:
+ Status = EFI_SUCCESS;
+ if (AltState && ShiftState) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode;
+ }
+ else if (AltState && !ShiftState) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].AltGrUnicode;
+ }
+ else if (!AltState && ShiftState) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].ShiftedUnicode;
+ }
+ else if (!AltState && !ShiftState) {
+ KeyData->Key.UnicodeChar = KeyDescriptor[i].Unicode;
+ }
+ break;
+ case EFI_NS_KEY_MODIFIER:
+ Status = EFI_SUCCESS;
+ if (AltState && ShiftState && (KeyDescriptor[i].ShiftedAltGrUnicode != 0x0000)) {
+ ModifierIndex = i;
+ ModifierUnicodeChar = KeyDescriptor[i].ShiftedAltGrUnicode;
+ KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character
+ }
+ else if (AltState && !ShiftState && (KeyDescriptor[i].AltGrUnicode != 0x0000)) {
+ ModifierIndex = i;
+ ModifierUnicodeChar = KeyDescriptor[i].AltGrUnicode;
+ KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character
+ }
+ else if (!AltState && ShiftState && (KeyDescriptor[i].ShiftedUnicode != 0x0000)) {
+ ModifierIndex = i;
+ ModifierUnicodeChar = KeyDescriptor[i].ShiftedUnicode;
+ KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character
+ }
+ else if (!AltState && !ShiftState && (KeyDescriptor[i].Unicode != 0x0000)) {
+ ModifierIndex = i;
+ ModifierUnicodeChar = KeyDescriptor[i].Unicode;
+ KeyData->Key.UnicodeChar = 0x0000; // don't return a character yet, the next keypress will determine the correct character
+ }
+ default:
+ case EFI_NS_KEY_DEPENDENCY_MODIFIER:
+ // skip deadkey-dependent modifiers and unknown modifiers
+ break;
+ } // switch (KeyDescriptor[i].Modifier)
+
+ if (!EFI_ERROR(Status) && (KeyData->Key.UnicodeChar != 0x0000 || ModifierUnicodeChar != 0x0000))
+ break; // successfully mapped a key, break for(...) loop
+ }
+ }
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/ConSplitter/ConSplit.h b/Core/CORE_DXE/ConSplitter/ConSplit.h
new file mode 100644
index 0000000..f64cad5
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/ConSplit.h
@@ -0,0 +1,553 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.h 4 8/02/13 4:27a Thomaschen $
+//
+// $Revision: 4 $
+//
+// $Date: 8/02/13 4:27a $
+//*****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/ConSplit.h $
+//
+// 4 8/02/13 4:27a Thomaschen
+// Add for EIP109384.
+// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c.
+//
+// 3 6/26/13 3:10a Thomaschen
+// Remove EIP109384.
+//
+// 1 6/04/13 1:53a Thomaschen
+// Fixed for EIP118202.
+//
+// 16 10/25/12 2:32a Deepthins
+// [TAG] EIP99475
+// [Category] Improvement
+// [Description] Multi language module Support in the console splitter
+// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h
+//
+// 15 8/02/12 12:14p Artems
+// [TAG] EIP95607
+// [Category] Bug Fix
+// [Symptom] Execute nsh script and redirect output to file, then exit
+// from shell, setup screen will crash
+// [RootCause] Console splitter maintains global pool of supported
+// modes.
+// It's getting adjusted every time new SimpleTextOut (STO) is installed
+// If new STO doesn't support particular mode it is getting marked as
+// unsupported in global pool
+// However once this STO is uninstalled global pool isn't updated, so mode
+// is still marked as unsupported,
+// though system can support it
+// [Solution] Added reinitilization of global pool of supported modes on
+// STO uninstall event
+// [Files] Consplit.h Consplit.c
+//
+// 14 8/12/11 12:17p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 13 5/05/11 3:52p Artems
+// Added multi-language keyboard support
+//
+// 12 6/23/10 3:02p Felixp
+// SimplePointer splitter support is added.
+//
+// 11 7/07/09 3:35p Artems
+// Added functions headers according to code standard
+//
+// 10 9/17/07 4:04p Olegi
+// Added support for AMI_EFIKEYCODE_PROTOCOL and
+// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+//
+// 9 9/05/07 11:13a Felixp
+// SimpleTextInEx support removed. It causes problems. Support will add
+// again after Core labeling.
+//
+// 8 9/04/07 2:55p Olegi
+// Added EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL support.
+//
+// 7 1/05/07 4:23p Artems
+//
+// 6 12/29/06 3:01p Felixp
+// 1. Support for GraphicsOutput protocol added
+// 2. Support for more then one text mode added
+//
+// 5 9/27/06 7:42p Felixp
+// SetMode funciton of the ConsoleControl protocol is updated to restore
+// default UGA mode when switching from grphics to text.
+//
+// 4 3/13/06 2:37a Felixp
+//
+// 3 12/12/05 9:32a Felixp
+// Support for synchronization of console devices
+// (now screen is restored after legacy OpROM execution).
+//
+// 2 11/07/05 10:37a Felixp
+// LockStdIn function of ConsoleControl protocol implemented
+//
+// 1 1/28/05 1:16p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/07/05 11:57a Felixp
+//
+// 3 1/04/05 5:15p Robert
+// Changed component name to be more consistent with the other drivers
+// that have been developed
+//
+// 2 1/03/05 5:47p Robert
+// Working beta version of the consplitter
+//
+// 1 12/30/04 9:47a Robert
+// Initial check in
+//
+//
+//*****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ConSplit.h
+//
+// Description: This file contains the structure and function prototypes needed
+// for the Console Splitter driver
+//
+//<AMI_FHDR_END>
+//*****************************************************************************
+
+#ifndef __CONSOLE_SPLITTER_H__
+#define __CONSOLE_SPLITTER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------------------
+
+#include <EFI.h>
+#include <Protocol\SimpleTextOut.h >
+#include <Protocol\SimpleTextIn.h>
+#include <Protocol\SimpleTextInEx.h>
+#include <Protocol\amikeycode.h>
+#include <Protocol\SimplePointer.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\ComponentName2.h>
+#include <AmiDxeLib.h>
+
+//--------------------------------------------------------------------------------
+
+#pragma pack (1)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT_SIMPLE_POINTER
+//
+// Description:
+// This structure represents Splitter Simple Pointer devices linked list.
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// Link DLINK Linked list pointer
+// SimplePointer EFI_SIMPLE_POINTER_PROTOCOL* Protocol pointer
+// Handle EFI_HANDLE Device handle
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _CON_SPLIT_SIMPLE_POINTER {
+ DLINK Link; //MUST BE THE FIRST FIELD
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
+ EFI_HANDLE Handle;
+} CON_SPLIT_SIMPLE_POINTER;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT_OUT
+//
+// Description:
+// This structure represents Splitter ConOut devices linked list
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// Link DLINK Linked list pointer
+// SimpleOut EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* Protocol pointer
+// Handle EFI_HANDLE Device handle
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _CON_SPLIT_OUT
+ {
+ DLINK Link; //MUST BE THE FIRST FIELD
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut;
+ EFI_HANDLE Handle;
+ } CON_SPLIT_OUT;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT_IN_KEY_NOTIFY
+//
+// Description:
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ DLINK Link; //MUST BE THE FIRST FIELD
+ EFI_KEY_DATA KeyData;
+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction;
+ DLIST NotifyHandleList;
+} CON_SPLIT_IN_KEY_NOTIFY;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT_IN_KEY_NOTIFY
+//
+// Description:
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct {
+ DLINK Link; //MUST BE THE FIRST FIELD
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx;
+ EFI_HANDLE NotifyHandle;
+} CON_SPLIT_IN_KEY_NOTIFY_HANDLE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT_IN
+//
+// Description:
+// This structure represents Splitter ConIn devices linked list
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// Link DLINK Linked list pointer
+// SimpleIn EFI_SIMPLE_TEXT_INPUT_PROTOCOL* Protocol pointer
+// SimpleInEx EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* Protocol pointer
+// KeycodeInEx AMI_EFIKEYCODE_PROTOCOL* Protocol pointer
+// Handle EFI_HANDLE Device handle
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _CON_SPLIT_IN
+ {
+ DLINK Link; //MUST BE THE FIRST FIELD
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleIn;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleInEx;
+ AMI_EFIKEYCODE_PROTOCOL *KeycodeInEx;
+ EFI_HANDLE Handle;
+ } CON_SPLIT_IN;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: CON_SPLIT
+//
+// Description:
+// This structure represents Splitter devices structure
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// Input CON_SPLIT_IN Input devices linked list
+// Output CON_SPLIT_OUT Output devices linked list
+// StdErr CON_SPLIT_OUT Error output devices linked list
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _CON_SPLIT
+ {
+ CON_SPLIT_IN Input;
+ CON_SPLIT_OUT Output;
+ CON_SPLIT_OUT StdErr;
+ } CON_SPLIT;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: SUPPORT_RES
+//
+// Description:
+// This structure represents Splitter supported resolutions database
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// Columns INT32 Max number of text columns
+// Rows INT32 Max number of text rows
+// AllDevices BOOLEAN Flag if all devices support given resolution
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct __SUPPORT_RES
+ {
+ INT32 Columns;
+ INT32 Rows;
+ BOOLEAN AllDevices;
+ } SUPPORT_RES;
+
+#pragma pack()
+
+//-----------------------------------------------------------------------------------
+
+SUPPORT_RES *SupportedModes;
+
+//virtual splitter output buffer
+CHAR16 *ScreenBuffer;
+CHAR16 *EndOfTheScreen;
+INT32 *AttributeBuffer;
+INT32 Columns;
+
+extern SIMPLE_TEXT_OUTPUT_MODE MasterMode;
+extern EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mCSOutProtocol;
+extern EFI_SIMPLE_TEXT_INPUT_PROTOCOL mCSSimpleInProtocol;
+extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL mCSSimpleInExProtocol;
+extern AMI_EFIKEYCODE_PROTOCOL mCSKeycodeInProtocol;
+extern DLIST ConInList;
+extern DLIST ConOutList;
+extern DLIST ConPointerList;
+extern DLIST ConInKeyNotifyList;
+extern BOOLEAN StdInLocked;
+extern EFI_SIMPLE_POINTER_PROTOCOL mCSSimplePointerProtocol;
+
+//-----------------------------------------------------------------------------------
+
+EFI_STATUS ConSplitterSimplePointerReset(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification );
+
+EFI_STATUS ConSplitterSimplePointerGetState(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN OUT EFI_SIMPLE_POINTER_STATE *State );
+
+VOID ConSplitterSimplePointerWaitForInput(
+ IN EFI_EVENT Event,
+ IN VOID *Context );
+
+EFI_STATUS CSSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+EFI_STATUS CSStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS CSStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS CSReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+EFI_STATUS CSOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+EFI_STATUS CSTestString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+EFI_STATUS CSQueryMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT UINTN *Col,
+ OUT UINTN *Row
+ );
+
+EFI_STATUS CSSetMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum
+ );
+
+EFI_STATUS CSSetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ );
+
+EFI_STATUS CSClearScreen(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ );
+
+EFI_STATUS CSSetCursorPosition(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ );
+
+EFI_STATUS CSEnableCursor(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ );
+
+EFI_STATUS CSInReset(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN EV
+ );
+
+EFI_STATUS CSReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+VOID CSWaitForKey(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS CSInResetEx(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN EV
+ );
+
+EFI_STATUS CSReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+ );
+
+EFI_STATUS
+CSReadEfiKey (
+ IN AMI_EFIKEYCODE_PROTOCOL *This,
+ OUT AMI_EFI_KEY_DATA *KeyData
+ );
+
+EFI_STATUS CSInSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+);
+
+EFI_STATUS CSInRegisterKeyNotify(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+);
+
+EFI_STATUS CSInUnRegisterKeyNotify(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+);
+
+VOID RestoreTheScreen(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut
+ );
+
+VOID SaveTheScreen(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut
+ );
+
+EFI_STATUS MemClearScreen(
+ VOID
+ );
+
+VOID SaveUgaMode(
+ IN EFI_HANDLE ControllerHandle
+ );
+
+VOID RestoreUgaMode(
+ IN EFI_HANDLE ControllerHandle
+ );
+
+EFI_STATUS InitModesTable(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN EFI_HANDLE Handle
+ );
+
+VOID UpdateModesTable(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN EFI_HANDLE Handle
+ );
+
+EFI_STATUS IsModeSupported(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT INT32 *DeviceModeNumber
+ );
+
+EFI_STATUS ResizeSplitterBuffer(
+ IN INT32 ModeNum
+ );
+
+VOID UpdateMasterMode(
+ IN SIMPLE_TEXT_OUTPUT_MODE *Mode
+ );
+
+EFI_STATUS CSInKeyboardLayoutMap(
+ IN OUT AMI_EFI_KEY_DATA *KeyData
+ );
+
+VOID AdjustSupportedModes(
+ VOID
+ );
+
+EFI_STATUS KeyboardLayoutMap(
+ IN AMI_MULTI_LANG_SUPPORT_PROTOCOL *This,
+ IN OUT AMI_EFI_KEY_DATA *KeyData
+ );
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/ConSplitter/ConSplitter.cif b/Core/CORE_DXE/ConSplitter/ConSplitter.cif
new file mode 100644
index 0000000..ff3fc94
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/ConSplitter.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "ConSplitter"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\ConSplitter\"
+ RefName = "ConSplitter"
+[files]
+"\ConSplitter.sdl"
+"\ConSplit.c"
+"\ConSplit.h"
+"\Out.c"
+"\In.c"
+<endComponent>
diff --git a/Core/CORE_DXE/ConSplitter/ConSplitter.sdl b/Core/CORE_DXE/ConSplitter/ConSplitter.sdl
new file mode 100644
index 0000000..730b34e
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/ConSplitter.sdl
@@ -0,0 +1,26 @@
+TOKEN
+ Name = "PAUSEKEY_SUPPORT"
+ Value = "0"
+ Help = "Pause key support. ON - Pause key causes pause during POST. OFF - Pause key ignored."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REPORT_NO_CON_OUT_ERROR"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REPORT_NO_CON_IN_ERROR"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+PATH
+ Name = "CONSOLE_SPLITTER_DIR"
+End
+
diff --git a/Core/CORE_DXE/ConSplitter/In.c b/Core/CORE_DXE/ConSplitter/In.c
new file mode 100644
index 0000000..9d8d561
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/In.c
@@ -0,0 +1,1159 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/In.c 5 7/08/15 4:32a Chienhsieh $
+//
+// $Revision: 5 $
+//
+// $Date: 7/08/15 4:32a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/ConSplitter/In.c $
+//
+// 5 7/08/15 4:32a Chienhsieh
+// Update for eip217417.
+//
+// 4 8/02/13 4:26a Thomaschen
+// Add for EIP109384.
+// [Files] ConSplit.c, ConSplit.h, In.c, CsmSimpleIn.c.
+//
+// 3 6/26/13 3:11a Thomaschen
+// Remove EIP109384.
+//
+// 1 6/04/13 1:52a Thomaschen
+// Fixed for EIP118202.
+//
+// 32 10/25/12 2:33a Deepthins
+// [TAG] EIP99475
+// [Category] Improvement
+// [Description] Multi language module Support in the console splitter
+//
+// [Files] ConSplit.c, ConSplit.h , In.c and AmiKeycode.h
+//
+// 31 7/20/12 10:38a Artems
+// [TAG] EIP93929
+// [Description] Implement support to initialize the Keyboard in first
+// call of readkeystoke in fast boot case
+// [Files] In.c
+//
+// 30 4/11/12 5:35p Artems
+// [TAG] EIPN/A
+// [Category] Bug Fix
+// [Symptom] Function SetState was not broadcasted to third party
+// drivers
+// [RootCause] Splitter uses AMI proprietary protocol to broadcast
+// SetState function
+// which is not installed by third party drivers
+// [Solution] Modified splitter to broadcast SetState function via
+// SimpleTextInEx protocol
+// [Files] in.c
+//
+// 29 3/21/12 12:53p Artems
+// EIP 83358: Fixed bug in SimplePointerGetState function, where
+// EFI_SUCCESS was lost if ohter device returns DEVICE_ERROR
+//
+// 28 9/22/11 6:29a Rameshr
+// [TAG] EIP63054
+// [Category] New Feature
+// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key
+// press
+// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c,
+// Efiusbkb.c, efiusbkb.h
+//
+// 27 7/21/11 3:41p Aaronp
+// // [TAG] EIP65187
+// // [Category] Bug Fix
+// // [Severity] Minor
+// // [Symptom] unicode character was not returned when english selected
+// // and alt key pressed
+// // [RootCause] The EFI_HII_KEYBOARD_LAYOUT table provides the
+// AltGraphic
+// // and Shifted AltGraphic unicode definitions for key combinations, and
+// // there are NULL values for undefined key combinations.
+// // [Solution] Changed how the EFI_HII_KEYBOARD_LAYOUT table is
+// consumed
+// // so that the current unicode character in the AMI_EFI_KEY_DATA
+// structure
+// // will not be overwritten when the EFI_HII_KEYBOARD_LAYOUT has a NULL
+// // value in the matching table entry.
+// // [Files] In.c
+//
+// 25 5/05/11 4:53p Artems
+// Removed unnecessary checks
+//
+// 24 5/05/11 3:54p Artems
+// Added multi-language keyboard support
+//
+// 23 8/10/10 2:29p Vyacheslava
+// Initialized default value of Status in the
+// ConSplitterSimplePointerReset function.
+//
+// 22 6/23/10 3:02p Felixp
+// SimplePointer splitter support is added.
+//
+// 21 1/18/10 3:40a Rameshr
+// NumLock,Capslock,Scroll Lock LED's synced properly between Keyboard
+// connect and disconnect.
+// EIP 27917
+//
+// 20 10/09/09 12:15p Felixp
+// SetState function is updated to process all the physical devices
+// despite the errors returned by some of them.
+//
+// 19 8/13/09 3:04p Rameshr
+// When item "num-lock status" set off, Num-lock will keep open until in
+// DOS.
+// EIP:21757
+//
+// 18 7/07/09 3:35p Artems
+// Added functions headers according to code standard
+//
+// 17 4/30/09 5:45p Felixp
+// Minor improvements on the pause key implementation.
+//
+// 16 3/30/09 10:24a Pats
+// Issue: EIP 19547 - Pause key support needed in Aptio
+// Solution: Function CsReadEfiKey modified to enter pause loop when pause
+// key detected. Requires mod in Ps2Kbd.c and efiusbkb.c.
+//
+// 15 1/23/09 9:55a Rameshr
+// Symptom:SCT failure in ReadKeystrokeEx function.
+// Solution: Validated the Input parameters Keydata for the
+// ReadKeystrokeEx Function.
+// Eip: 19039
+//
+// 14 11/17/08 10:22a Rameshraju
+// Problem:SCT failure on RegisterKeyNotify, SetState and
+// UnregisterKeyNotify.
+// Fix : Validated the input parameters for RegisterKeyNotify, SetState
+// and UnregisterKeyNotify.
+// EIP:17578
+//
+// 13 10/08/08 4:27p Olegi
+// Implemented the Register/Unregister key notofocation function in
+// SimpletextinEx protocol.
+//
+// 12 3/17/08 4:49p Rameshraju
+// ReadEfiKey doesnt not return correct key value randomly.
+//
+// 11 1/31/08 12:00p Olegi
+// Numlock bootup state made setup driven.
+//
+// 10 11/16/07 4:05p Olegi
+// Modifications in CSReadKeyStroke function.
+//
+// 9 10/23/07 4:14p Olegi
+// Modifications in CSInSetState that allow the sync between the Input
+// Devices' LEDs.
+//
+// 8 10/16/07 10:47a Olegi
+// Modification in CSReadEfiKey().
+//
+// 7 9/17/07 4:04p Olegi
+// Added support for AMI_EFIKEYCODE_PROTOCOL and
+// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+//
+// 6 9/05/07 11:13a Felixp
+// SimpleTextInEx support removed. It causes problems. Support will add
+// again after Core labeling.
+//
+// 3 3/13/06 2:37a Felixp
+//
+// 2 11/07/05 10:37a Felixp
+// LockStdIn function of ConsoleControl protocol implemented
+//
+// 1 1/28/05 1:16p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/07/05 11:57a Felixp
+//
+// 2 1/03/05 5:47p Robert
+// Working beta version of the consplitter
+//
+// 1 12/30/04 9:47a Robert
+// Initial check in
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Out.c
+//
+// Description: File contains the Simple Text Output functionality for the
+// Console Splitter Driver
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------------
+
+#include "ConSplit.h"
+#include "token.h"
+#include <Protocol/SimplePointer.h>
+
+//----------------------------------------------------------------------------
+extern EFI_HII_KEYBOARD_LAYOUT *gKeyDescriptorList;
+extern EFI_KEY_TOGGLE_STATE mCSToggleState;
+EFI_SIMPLE_POINTER_MODE gSimplePointerMode = {
+ 0x10000,
+ 0x10000,
+ 0x10000,
+ FALSE,
+ FALSE
+};
+
+VOID ConnectInputDevices(
+ VOID
+);
+
+//----------------------------------------------------------------------------
+
+EFI_SIMPLE_TEXT_INPUT_PROTOCOL mCSSimpleInProtocol = {
+ CSInReset,
+ CSReadKeyStroke,
+ NULL
+ } ;
+
+EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL mCSSimpleInExProtocol = {
+ CSInResetEx,
+ CSReadKeyStrokeEx,
+ NULL,
+ CSInSetState,
+ CSInRegisterKeyNotify,
+ CSInUnRegisterKeyNotify
+ } ;
+
+AMI_EFIKEYCODE_PROTOCOL mCSKeycodeInProtocol = {
+ CSInResetEx,
+ CSReadEfiKey,
+ NULL,
+ CSInSetState,
+ CSInRegisterKeyNotify,
+ CSInUnRegisterKeyNotify
+ } ;
+
+EFI_SIMPLE_POINTER_PROTOCOL mCSSimplePointerProtocol = {
+ ConSplitterSimplePointerReset,
+ ConSplitterSimplePointerGetState,
+ ConSplitterSimplePointerWaitForInput,
+ &gSimplePointerMode
+};
+
+//----------------------------------------------------------------------------
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConSplitterSimplePointerReset
+//
+// Description: Resets the pointer device hardware.
+//
+// Input:
+// *This - pointer to protocol instance.
+// ExtendedVerification - Driver may perform diagnostics on reset.
+//
+// Output:
+// EFI_SUCCESS - device was reset successfully
+// EFI_ERROR - some of devices returned error
+//
+//----------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ConSplitterSimplePointerReset (
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS TestStatus;
+ CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL;
+
+ if (StdInLocked)
+ return EFI_ACCESS_DENIED;
+
+ if (ConPointerList.pHead == NULL)
+ return EFI_DEVICE_ERROR;
+
+ ConSimplePointer = OUTTER(ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER);
+
+ // we need to loop through all the registered simple pointer devices
+ // and call each of their Reset function
+ while (ConSimplePointer != NULL) {
+ TestStatus = ConSimplePointer->SimplePointer->Reset(ConSimplePointer->SimplePointer, ExtendedVerification);
+ ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER );
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ return Status;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConSplitterSimplePointerGetState
+//
+// Description: Retrieves the current state of a pointer device.
+// Reads the next keystroke from the input device. The WaitForKey Event can
+// be used to test for existance of a keystroke via WaitForEvent () call.
+// If the ConIn is password locked make it look like no keystroke is availible
+//
+// Input:
+// This - Protocol instance pointer.
+// State - A pointer to the state information on the pointer device.
+//
+// Output:
+// EFI_SUCCESS - The keystroke information was returned.
+// EFI_NOT_READY - There was no keystroke data availiable.
+// EFI_DEVICE_ERROR - The keydtroke information was not returned due to
+// hardware errors.
+//
+//----------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS ConSplitterSimplePointerGetState(
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN OUT EFI_SIMPLE_POINTER_STATE *State )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE CurrentState;
+ CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL;
+ BOOLEAN EfiSuccessDetected = FALSE;
+ BOOLEAN EfiDeviceErrorDetected = FALSE;
+ BOOLEAN EfiNotReadyDetected = FALSE;
+
+ if (StdInLocked)
+ return EFI_ACCESS_DENIED;
+
+ if (ConPointerList.pHead == NULL)
+ return EFI_DEVICE_ERROR;
+
+ ConSimplePointer = OUTTER( ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER );
+
+ State->RelativeMovementX = 0;
+ State->RelativeMovementY = 0;
+ State->RelativeMovementZ = 0;
+ State->LeftButton = FALSE;
+ State->RightButton = FALSE;
+
+ // we need to loop through all the registered simple pointer devices
+ while (ConSimplePointer != NULL) {
+
+ Status = ConSimplePointer->SimplePointer->GetState(ConSimplePointer->SimplePointer, &CurrentState);
+
+ if (!EFI_ERROR(Status)) {
+
+ EfiSuccessDetected = TRUE;
+
+ if (CurrentState.LeftButton)
+ State->LeftButton = TRUE;
+
+ if (CurrentState.RightButton)
+ State->RightButton = TRUE;
+
+ if ( CurrentState.RelativeMovementX != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionX != 0 )
+ State->RelativeMovementX +=
+ (CurrentState.RelativeMovementX * (INT32)gSimplePointerMode.ResolutionX) /
+ (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionX;
+
+ if ( CurrentState.RelativeMovementY != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionY != 0 )
+ State->RelativeMovementY +=
+ (CurrentState.RelativeMovementY * (INT32)gSimplePointerMode.ResolutionY) /
+ (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionY;
+
+ if ( CurrentState.RelativeMovementZ != 0 && ConSimplePointer->SimplePointer->Mode->ResolutionZ != 0 )
+ State->RelativeMovementZ +=
+ (CurrentState.RelativeMovementZ * (INT32)gSimplePointerMode.ResolutionZ) /
+ (INT32)ConSimplePointer->SimplePointer->Mode->ResolutionZ;
+
+ } else if (Status == EFI_DEVICE_ERROR) {
+ EfiDeviceErrorDetected = TRUE;
+ } else {
+ EfiNotReadyDetected = TRUE;
+ }
+
+ ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER );
+ }
+
+ return (EfiSuccessDetected) ? EFI_SUCCESS : (EfiDeviceErrorDetected) ? EFI_DEVICE_ERROR : EFI_NOT_READY;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ConSplitterSimplePointerWaitForInput
+//
+// Description: This is callback function for WaitForInputEvent to use with
+// WaitForEvent() to wait for input from the pointer device.
+//
+// Input:
+// Event - The Event assoicated with callback.
+// Context - Context registered when Event was created.
+//
+// Output: VOID
+//
+//----------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID ConSplitterSimplePointerWaitForInput(
+ IN EFI_EVENT Event,
+ IN VOID *Context )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS TestStatus;
+ CON_SPLIT_SIMPLE_POINTER *ConSimplePointer = NULL;
+
+ if (StdInLocked)
+ return;
+
+ if (ConPointerList.pHead == NULL)
+ return;
+
+ ConSimplePointer = OUTTER( ConPointerList.pHead, Link, CON_SPLIT_SIMPLE_POINTER );
+
+ // loop through simple pointer events and check their events
+ // if one event has been signaled, signal my event and exit.
+ // we need to loop through all the registered simple pointer devices
+ while (ConSimplePointer != NULL) {
+ TestStatus = pBS->CheckEvent(ConSimplePointer->SimplePointer->WaitForInput);
+ ConSimplePointer = OUTTER( ConSimplePointer->Link.pNext, Link, CON_SPLIT_SIMPLE_POINTER );
+
+ if (!EFI_ERROR(TestStatus))
+ pBS->SignalEvent(Event);
+ }
+
+ return;
+}
+
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInReset
+//
+// Description:
+// This function resets the input device hardware. This routine is a part
+// of SimpleTextIn protocol implementation.
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - pointer to protocol instance
+// IN BOOLEAN EV - flag if Extended verification has to be performed
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device was reset successfully
+// EFI_ERROR - some of devices returned error
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSInReset(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN EV
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_IN *SimpleIn;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ if (ConInList.pHead == NULL)
+ return EFI_SUCCESS;
+
+ SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN);
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their Reset function
+ while ( SimpleIn != NULL)
+ {
+ TestStatus = SimpleIn->SimpleIn->Reset(SimpleIn->SimpleIn, EV);
+ SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ return Status;
+
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSReadKeyStroke
+//
+// Description:
+// This function reads the next keystroke from the input device. This
+// routine is a part of SimpleTextIn protocol implementation
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This - pointer to protocol instance
+// OUT EFI_INPUT_KEY *Key - key pressed information
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Keystroke data successfully retrieved
+// EFI_NOT_READY - There was no keystroke data available
+// EFI_DEVICE_ERROR - The keystroke information was not returned
+// due to hardware error
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSReadKeyStroke(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+)
+{
+ EFI_STATUS Status;
+ AMI_EFI_KEY_DATA EfiKeyData;
+
+ Status = CSReadEfiKey ( (AMI_EFIKEYCODE_PROTOCOL*) This, &EfiKeyData );
+ if (Status == EFI_SUCCESS) {
+ //
+ // Check for the Partial Key. If found, SimpleTextIn ReadKeyStroke
+ // Should not return that Key has bee found.
+ //
+ if(EfiKeyData.Key.ScanCode == 00 && EfiKeyData.Key.UnicodeChar == 0 &&
+ (EfiKeyData.KeyState.KeyToggleState & KEY_STATE_EXPOSED )) {
+ return EFI_NOT_READY;
+ }
+ *Key = EfiKeyData.Key;
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSWaitForKey
+//
+// Description:
+// This function is a callback for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
+// Checks whether the new key is available and if so - signals the event
+//
+// Input:
+// IN EFI_EVENT Event - event to signal
+// IN VOID *Context - pointer to event specific context
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID CSWaitForKey(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_IN *SimpleIn;
+
+ if (StdInLocked) return ;
+ if (ConInList.pHead == NULL) return;
+
+// loop through simple in events and check their events
+// if one event has been signaled, signal my event and exit
+
+ SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN);
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their Reset function
+ while ( SimpleIn != NULL)
+ {
+ TestStatus = pBS->CheckEvent(SimpleIn->SimpleIn->WaitForKey);
+ SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN);
+
+ if (!EFI_ERROR(TestStatus))
+ pBS->SignalEvent (Event);
+ }
+
+ return;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInResetEx
+//
+// Description:
+// This function resets the input device hardware. This routine is a part
+// of SimpleTextInEx protocol implementation
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance
+// IN BOOLEAN ExtendedVerification - flag if Extended verification has to be performed
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device was reset successfully
+// EFI_ERROR - some of devices returned error
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSInResetEx(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification )
+{
+ return CSInReset(0, ExtendedVerification);
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSReadKeyStrokeEx
+//
+// Description:
+// This function reads the next keystroke from the input device. This
+// routine is a part of SimpleTextInEx protocol implementation
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance
+// OUT EFI_KEY_DATA *KeyData - key pressed information
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Keystroke data successfully retrieved
+// EFI_NOT_READY - There was no keystroke data available
+// EFI_DEVICE_ERROR - The keystroke information was not returned
+// due to hardware error
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSReadKeyStrokeEx (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ OUT EFI_KEY_DATA *KeyData
+)
+{
+ EFI_STATUS Status;
+ AMI_EFI_KEY_DATA EfiKeyData;
+
+ if(KeyData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = CSReadEfiKey ( (AMI_EFIKEYCODE_PROTOCOL*) This, &EfiKeyData );
+ if (Status == EFI_SUCCESS) {
+ KeyData->Key = EfiKeyData.Key;
+ KeyData->KeyState = EfiKeyData.KeyState;
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSReadEfiKey
+//
+// Description:
+// This function reads the next keystroke from the input device. This
+// routine is a part of AmiKeyCode protocol implementation
+//
+// Input:
+// IN AMI_EFIKEYCODE_PROTOCOL *This - pointer to protocol instance
+// OUT AMI_EFI_KEY_DATA *KeyData - key pressed information
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Keystroke data successfully retrieved
+// EFI_NOT_READY - There was no keystroke data available
+// EFI_DEVICE_ERROR - The keystroke information was not returned
+// due to hardware error
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSReadEfiKey (
+ IN AMI_EFIKEYCODE_PROTOCOL *This,
+ OUT AMI_EFI_KEY_DATA *KeyData
+)
+{
+ AMI_EFI_KEY_DATA TempKey;
+ EFI_STATUS Status = EFI_NOT_READY;
+ CON_SPLIT_IN *SimpleIn;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ ConnectInputDevices();
+
+ if (ConInList.pHead == NULL) return EFI_NOT_READY;
+
+ SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN);
+
+ pBS->SetMem(KeyData, sizeof(AMI_EFI_KEY_DATA), 0);
+
+ // we need to loop through all the registered EfiKey, SimpleInEx and
+ // SimpleIn devices and call each of their ReadKeyStroke function
+ while (SimpleIn != NULL)
+ {
+ if (SimpleIn->KeycodeInEx) {
+ Status = SimpleIn->KeycodeInEx->ReadEfikey(SimpleIn->KeycodeInEx, &TempKey);
+ } else if(SimpleIn->SimpleInEx != NULL) {
+ Status = SimpleIn->SimpleInEx->ReadKeyStrokeEx(
+ SimpleIn->SimpleInEx, (EFI_KEY_DATA*)&TempKey);
+ } else if(SimpleIn->SimpleIn != NULL) {
+ Status = SimpleIn->SimpleIn->ReadKeyStroke(
+ SimpleIn->SimpleIn, (EFI_INPUT_KEY*)&TempKey);
+ }
+
+ // Check for the Toggle State change
+ if (!EFI_ERROR(Status) && (TempKey.KeyState.KeyToggleState & TOGGLE_STATE_VALID)) {
+ if ((TempKey.KeyState.KeyToggleState & ~KEY_STATE_EXPOSED ) != mCSToggleState) {
+ mCSToggleState = (TempKey.KeyState.KeyToggleState & ~KEY_STATE_EXPOSED);
+ CSInSetState ( (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL*) This,
+ &mCSToggleState );
+ }
+ }
+
+ if (!EFI_ERROR(Status)) {
+ *KeyData = TempKey;
+ break;
+ }
+
+ SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN);
+ }
+#if PAUSEKEY_SUPPORT
+ if (!EFI_ERROR(Status) && TempKey.EfiKey == EfiKeyPause) {
+ while(TRUE) {
+ Status = CSReadEfiKey ( This, &TempKey );
+ if ((!EFI_ERROR(Status)) && (TempKey.EfiKey != EfiKeyPause) && (TempKey.EfiKey != 0x55)) {
+ break;
+ }
+ }
+ *KeyData = TempKey;
+ }
+#endif
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInSetState
+//
+// Description:
+// This function sets certain state for input device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance
+// IN EFI_KEY_TOGGLE_STATE *KeyToggleState - pointer to state to set
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Keystroke data successfully retrieved
+// EFI_UNSUPPORTED - Given state not supported
+// EFI_INVALID_PARAMETER - KeyToggleState is NULL
+// EFI_DEVICE_ERROR - input device not found
+// EFI_ACCESS_DENIED - input device is busy
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSInSetState (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ CON_SPLIT_IN *SimpleIn;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ if (ConInList.pHead == NULL)
+ return EFI_UNSUPPORTED;
+
+ if(KeyToggleState == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!(*KeyToggleState & TOGGLE_STATE_VALID) ||
+ ((*KeyToggleState & (~(TOGGLE_STATE_VALID | KEY_STATE_EXPOSED |
+ SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE)))) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mCSToggleState = *KeyToggleState; // Update global toggle state
+
+ SimpleIn = OUTTER(ConInList.pHead, Link, CON_SPLIT_IN);
+
+ // we need to loop through all the registered KeycodeInEx devices
+ // and call each of their SetState function
+ while ( SimpleIn != NULL )
+ {
+ if (SimpleIn->SimpleInEx) {
+ SimpleIn->SimpleInEx->SetState(SimpleIn->SimpleInEx, KeyToggleState);
+ }
+ SimpleIn = OUTTER(SimpleIn->Link.pNext, Link, CON_SPLIT_IN);
+ }
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInKeyNotificationFunction
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS
+CSInKeyNotificationFunction(
+ IN EFI_KEY_DATA *KeyData
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ DLINK *ListPtr;
+ UINTN Index = 0;
+ UINTN Count = 0;
+ EFI_KEY_NOTIFY_FUNCTION *NotifyFunctionList = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ if (ConInKeyNotifyList.pHead == NULL) return EFI_DEVICE_ERROR;
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ ConInKeyNotifyList.Size * sizeof(EFI_KEY_NOTIFY_FUNCTION),
+ (VOID**)&NotifyFunctionList);
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY);
+
+ if (!MemCmp(&(CsInKeyNotify->KeyData), KeyData, sizeof(CsInKeyNotify->KeyData))) {
+ NotifyFunctionList[Count++] = CsInKeyNotify->KeyNotificationFunction;
+ }
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ NotifyFunctionList[Index](&(CsInKeyNotify->KeyData));
+ }
+
+ pBS->FreePool(NotifyFunctionList);
+
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInRegisterKeyNotify
+//
+// Description:
+// This function registers a notification function for a particular
+// keystroke of the input device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance
+// IN EFI_KEY_DATA *KeyData - key value
+// IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction - notification function
+// OUT EFI_HANDLE *NotifyHandle - returned registered handle
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - notification function registered successfully
+// EFI_INVALID_PARAMETER - KeyData/KeyNotificationFunction/NotifyHandle is NULL
+// EFI_DEVICE_ERROR - input device not found
+// EFI_ACCESS_DENIED - input device is busy
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSInRegisterKeyNotify(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_KEY_DATA *KeyData,
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
+ OUT EFI_HANDLE *NotifyHandle
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ DLINK *ListPtr = NULL;
+ CON_SPLIT_IN *ConIn = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ if(KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY);
+
+ if ((!MemCmp(&CsInKeyNotify->KeyData, KeyData, sizeof(CsInKeyNotify->KeyData))) &&
+ (CsInKeyNotify->KeyNotificationFunction == KeyNotificationFunction)) {
+ *NotifyHandle = (EFI_HANDLE)&(CsInKeyNotify->Link);
+ return EFI_SUCCESS;
+ }
+
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(CON_SPLIT_IN_KEY_NOTIFY), &CsInKeyNotify);
+ if (EFI_ERROR(Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MemCpy(&(CsInKeyNotify->KeyData), KeyData, sizeof(CsInKeyNotify->KeyData));
+ CsInKeyNotify->KeyNotificationFunction = KeyNotificationFunction;
+ DListAdd(&ConInKeyNotifyList, &(CsInKeyNotify->Link));
+ DListInit(&(CsInKeyNotify->NotifyHandleList));
+ // we need to loop through all the registered SimpleInEx
+ // and call each of their ReadKeyStroke function
+ for (ListPtr = ConInList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ ConIn = OUTTER(ListPtr, Link, CON_SPLIT_IN);
+
+ if (ConIn->SimpleInEx == NULL) {
+ continue;
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(CON_SPLIT_IN_KEY_NOTIFY_HANDLE), &CsInNotifyHandle);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ CsInNotifyHandle->SimpleInEx = ConIn->SimpleInEx;
+ DListAdd(&(CsInKeyNotify->NotifyHandleList), &(CsInNotifyHandle->Link));
+
+ Status = ConIn->SimpleInEx->RegisterKeyNotify(ConIn->SimpleInEx,
+ KeyData, CSInKeyNotificationFunction, &(CsInNotifyHandle->NotifyHandle));
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ for (ListPtr = CsInKeyNotify->NotifyHandleList.pHead;
+ ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInNotifyHandle = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE);
+
+ CsInNotifyHandle->SimpleInEx->UnregisterKeyNotify(
+ CsInNotifyHandle->SimpleInEx, CsInNotifyHandle->NotifyHandle);
+
+ DListDelete(&(CsInKeyNotify->NotifyHandleList), ListPtr);
+ pBS->FreePool(CsInNotifyHandle);
+ }
+
+ pBS->FreePool(CsInKeyNotify);
+
+ return Status;
+ }
+
+ *NotifyHandle = (EFI_HANDLE)&(CsInKeyNotify->Link);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSInUnRegisterKeyNotify
+//
+// Description:
+// This function unregisters a notification function with given handle
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This - pointer to protocol instance
+// IN EFI_HANDLE NotificationHandle - handle to unregister
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - notification function unregistered successfully
+// EFI_INVALID_PARAMETER - NotificationHandle is NULL
+// EFI_DEVICE_ERROR - input device not found
+// EFI_ACCESS_DENIED - input device is busy
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSInUnRegisterKeyNotify(
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ DLINK *ListPtr = NULL;
+ DLINK *HandleLink = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY *CsInKeyNotify = NULL;
+ CON_SPLIT_IN_KEY_NOTIFY_HANDLE *CsInNotifyHandle = NULL;
+
+ if (StdInLocked) return EFI_ACCESS_DENIED;
+
+ if (NotificationHandle == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (ListPtr = ConInKeyNotifyList.pHead; ListPtr != NULL; ListPtr = ListPtr->pNext) {
+ CsInKeyNotify = OUTTER(ListPtr, Link, CON_SPLIT_IN_KEY_NOTIFY);
+
+ if (NotificationHandle == (EFI_HANDLE)&(CsInKeyNotify->Link)) {
+ DListDelete(&ConInKeyNotifyList, ListPtr);
+ break;
+ }
+ }
+
+ if (ListPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // we need to loop through all the registered SimpleInEx
+ // and call each of their ReadKeyStroke function
+
+ for (HandleLink = CsInKeyNotify->NotifyHandleList.pHead; HandleLink != NULL;
+ HandleLink = HandleLink->pNext) {
+ CsInNotifyHandle = OUTTER(HandleLink, Link, CON_SPLIT_IN_KEY_NOTIFY_HANDLE);
+
+ Status = CsInNotifyHandle->SimpleInEx->UnregisterKeyNotify(
+ CsInNotifyHandle->SimpleInEx, CsInNotifyHandle->NotifyHandle);
+
+ DListDelete(&(CsInKeyNotify->NotifyHandleList), HandleLink);
+ Status = pBS->FreePool(CsInNotifyHandle);
+ }
+
+ Status = pBS->FreePool(CsInKeyNotify);
+
+ return Status;
+}
+
+
+#if FAST_BOOT_SUPPORT
+#include <Protocol/FastBootProtocol.h>
+static AMI_FAST_BOOT_PROTOCOL *AmiFbProtocol = NULL;
+
+VOID ConnectInputDevices(
+ VOID
+)
+{
+ EFI_STATUS Status;
+ static Executed = FALSE;
+
+ if(Executed)
+ return;
+
+ if(AmiFbProtocol == NULL) {
+ Status = pBS->LocateProtocol(&AmiFastBootProtocolGuid, NULL, &AmiFbProtocol);
+ if(EFI_ERROR(Status)) {
+ AmiFbProtocol = NULL;
+ return;
+ }
+ }
+
+ if(AmiFbProtocol->IsRuntime()) {
+ AmiFbProtocol->ConnectInputDevices();
+ Executed = TRUE;
+ }
+}
+
+#else //#if FAST_BOOT_SUPPORT
+VOID ConnectInputDevices(
+ VOID
+){return;}
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/ConSplitter/Out.c b/Core/CORE_DXE/ConSplitter/Out.c
new file mode 100644
index 0000000..d11ebc8
--- /dev/null
+++ b/Core/CORE_DXE/ConSplitter/Out.c
@@ -0,0 +1,1323 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/ConSplitter/Out.c 19 7/06/12 11:31a Artems $
+//
+// $Revision: 19 $
+//
+// $Date: 7/06/12 11:31a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/ConSplitter/Out.c $
+//
+// 19 7/06/12 11:31a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Support for monitor native resolution
+// [Files] Gc.c, Consplit.c, Out.c, Core_Dxe.sdl
+//
+// 18 10/27/11 12:50p Felixp
+// [TAG] EIP65867
+// [Category] Improvement
+// [Description] Screen content that was printed in a timer callback was
+// not getting restored after OpROM
+// execution.
+// The previous check-in didn't address all the issue.
+// This is a more sophisticated solution.
+//
+// 17 8/03/11 3:27p Felixp
+// [TAG] EIP65867
+// [Category] Improvement
+// [Description] Screen content that was printed in a timer callback was
+// not getting restored after OpROM execution.
+// RestoreTheScreen function is updated.
+//
+// 16 10/09/09 6:15p Felixp
+// UGA constant replaced with GOP constant (UEFI 2.1 compatibility)
+//
+// 15 7/07/09 3:35p Artems
+// Added functions headers according to code standard
+//
+// 14 6/16/09 5:49p Artems
+// EIP 21415 Fixed error with CursorVisible variable
+//
+// 11 10/23/07 10:13a Felixp
+// Bug fix: System was hanging in SCT during Simple Text Output protocol
+// testing
+// when "Enable Screen Ouput" SCT option was enabled.
+//
+// 10 7/20/07 12:16p Felixp
+// Clear the screen when switching from graphics screen to text screen
+// without mode switching
+//
+// 9 1/05/07 6:01p Artems
+//
+// 8 12/29/06 3:01p Felixp
+// 1. Support for GraphicsOutput protocol added
+// 2. Support for more then one text mode added
+//
+// 7 9/27/06 7:42p Felixp
+// SetMode funciton of the ConsoleControl protocol is updated to restore
+// default UGA mode when switching from grphics to text.
+//
+// 6 3/13/06 2:37a Felixp
+//
+// 5 12/12/05 8:36p Felixp
+// RestoreTheScreen update: Restore Cursor Status
+//
+// 4 12/12/05 9:32a Felixp
+// Support for synchronization of console devices
+// (now screen is restored after legacy OpROM execution).
+//
+// 3 7/21/05 5:12p Robert
+//
+// 2 1/31/05 11:31a Robert
+//
+// 1 1/28/05 1:16p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 1/07/05 11:57a Felixp
+//
+// 2 1/03/05 5:47p Robert
+// Working beta version of the consplitter
+//
+// 1 12/30/04 9:47a Robert
+// Initial check in
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Out.c
+//
+// Description: File contains the Simple Text Output functionality for the
+// Console Splitter Driver
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------------
+
+#include "ConSplit.h"
+#include <Protocol/GraphicsOutput.h>
+
+//----------------------------------------------------------------------------
+
+#define DefaultAttribute 0x0F
+#define DefaultCursorVisible TRUE
+
+SUPPORT_RES *SupportedModes = NULL;
+
+SIMPLE_TEXT_OUTPUT_MODE MasterMode =
+ {
+ 1, // MaxMode
+ 0, // Current Mode
+ 0x0F, // Attribute
+ 0, // Column
+ 0, // Row
+ 1 // CursorVisible
+ };
+
+
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mCSOutProtocol =
+ {
+ CSReset,
+ CSOutputString,
+ CSTestString,
+ CSQueryMode,
+ CSSetMode,
+ CSSetAttribute,
+ CSClearScreen,
+ CSSetCursorPosition,
+ CSEnableCursor,
+ &MasterMode
+ };
+
+//****************************** Virtual ConOut **********************//
+CHAR16 *ScreenBuffer = NULL;
+CHAR16 *SaveScreenBuffer = NULL;
+CHAR16 *EndOfTheScreen = NULL;
+INT32 *AttributeBuffer = NULL;
+INT32 *SaveAttributeBuffer = NULL;
+INT32 Columns = 0;
+BOOLEAN BlankScreen = TRUE;
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ScrollScreen
+//
+// Description:
+// This function scrolls internal splitter buffer
+//
+// Input:
+// VOID
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID ScrollScreen(
+ VOID
+)
+{
+ INT32 i;
+ CHAR16 *pChar = EndOfTheScreen - Columns;
+ INT32 *pAttr = AttributeBuffer + (pChar-ScreenBuffer);
+
+ pBS->CopyMem(
+ ScreenBuffer+Columns, ScreenBuffer,
+ sizeof(CHAR16)* (EndOfTheScreen - pChar)
+ );
+
+ for(i=0; i<Columns; i++)
+ {
+ *pChar++ = ' ';
+ *pAttr++ = MasterMode.Attribute;
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: MemOutputString
+//
+// Description:
+// This function puts string into internal splitter buffer
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN CHAR16 *String - pointer to string
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS MemOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+)
+{
+ INT32 Col = MasterMode.CursorColumn;
+ UINTN Offset = MasterMode.CursorRow * Columns;
+ CHAR16 *pChar = ScreenBuffer + Offset + Col;
+ INT32 *pAttr = AttributeBuffer + Offset + Col;
+ BlankScreen = FALSE;
+
+ while(TRUE){
+ switch(*String){
+ case 0:
+ return EFI_SUCCESS;
+ case '\n':
+ if ((pChar + Columns) >= EndOfTheScreen)
+ ScrollScreen();
+ else
+ {
+ pChar += Columns;
+ pAttr += Columns;
+ }
+ break;
+ case '\r':
+ pChar -= Col;
+ pAttr -= Col;
+ Col = 0;
+ break;
+ case '\b':
+ if (Col)
+ {
+ pChar--;
+ pAttr--;
+ Col--;
+ }
+ break;
+ default:
+ if ((pChar + 1) == EndOfTheScreen)
+ {
+ ScrollScreen();
+ pChar -= Col;
+ pAttr -= Col;
+ Col = 0;
+ }
+ else
+ {
+ *pChar++ = *String;
+ *pAttr++ = MasterMode.Attribute;
+ Col++;
+ if (Col >= Columns)
+ Col = 0;
+ }
+ break;
+ }
+ String++;
+ }
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: RestoreTextScreen
+//
+// Description:
+// This function restores screen after switching mode
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen - pointer to protocol instance
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID RestoreTextScreen(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen
+)
+{
+ CHAR16 *pChar = ScreenBuffer, *pStr = ScreenBuffer;
+ INT32 Col = 0, *pAttr = AttributeBuffer, Attr;
+ CHAR16 c;
+
+ if (BlankScreen)
+ return;
+
+ Attr = *pAttr;
+ pScreen->SetCursorPosition(pScreen,0,0);
+ pScreen->SetAttribute(pScreen,Attr);
+
+ for(; pChar<EndOfTheScreen; pChar++, pAttr++)
+ {
+ if (Col == Columns || *pAttr != Attr)
+ {
+ c = *pChar;
+ *pChar = 0;
+ pScreen->OutputString(pScreen, pStr);
+ *pChar = c;
+ pStr = pChar;
+ if (*pAttr != Attr)
+ {
+ Attr = *pAttr;
+ pScreen->SetAttribute(pScreen, Attr);
+ }
+ else
+ {
+ Col=1;
+ continue;
+ }
+ }
+ Col++;
+ }
+ //print last row
+ c = *--pChar;
+ *pChar = 0;
+ pScreen->OutputString(pScreen, pStr);
+ *pChar = c;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: MemClearScreen
+//
+// Description:
+// This function clears internal splitter buffer
+//
+// Input:
+// VOID
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS MemClearScreen(
+ VOID
+)
+{
+ CHAR16 *pChar;
+ INT32 *pAttr;
+ for( pChar = ScreenBuffer, pAttr = AttributeBuffer
+ ; pChar < EndOfTheScreen
+ ; pChar++, pAttr++ )
+ {
+ *pChar = ' ';
+ *pAttr = MasterMode.Attribute;
+ }
+ BlankScreen = TRUE;
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: MemReset
+//
+// Description:
+// This function resets internal splitter buffer
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN BOOLEAN EV - extended verification flag
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS MemReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN EV
+)
+{
+ return MemClearScreen();
+}
+
+///////////////// Uga Save/Restore
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PixelBuffer = NULL;
+UINT32 GraphicsMode, TextMode = 0;
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: RestoreUgaScreen
+//
+// Description:
+// This function restores screen after switching from text to graphics mode
+//
+// Input:
+// IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This - pointer to protocol instance
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID RestoreUgaScreen(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
+)
+{
+ if (PixelBuffer){
+ EFI_STATUS Status;
+ Status = Gop->SetMode(Gop, GraphicsMode);
+ if (!EFI_ERROR(Status))
+ Gop->Blt(
+ Gop, PixelBuffer, EfiBltBufferToVideo, 0, 0, 0, 0,
+ Gop->Mode->Info->HorizontalResolution,
+ Gop->Mode->Info->VerticalResolution, 0
+ );
+ pBS->FreePool(PixelBuffer);
+ PixelBuffer = NULL;
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SaveUgaScreen
+//
+// Description:
+// This function saves graphics screen before switching to text mode
+//
+// Input:
+// IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This - pointer to protocol instance
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID SaveUgaScreen(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
+)
+{
+ if (PixelBuffer)
+ pBS->FreePool(PixelBuffer);
+
+ GraphicsMode=Gop->Mode->Mode;
+ PixelBuffer = Malloc(
+ Gop->Mode->Info->VerticalResolution*
+ Gop->Mode->Info->HorizontalResolution*
+ sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ if (PixelBuffer)
+ {
+ EFI_STATUS Status=Gop->Blt(
+ Gop, PixelBuffer, EfiBltVideoToBltBuffer, 0, 0, 0, 0,
+ Gop->Mode->Info->HorizontalResolution,
+ Gop->Mode->Info->VerticalResolution, 0);
+
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(PixelBuffer);
+ PixelBuffer = NULL;
+ }
+ }
+}
+
+static EFI_GUID guidGop = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: RestoreTextScreenDelta
+//
+// Description:
+// This function checks to see if anything has changed on the screen since the
+// graphics output device was disabled. If something has changed, then it will
+// add that to the display.
+//
+// Input:
+// VOID
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID RestoreTextScreenDelta(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *pScreen
+)
+{
+ UINT32 i;
+ CHAR16 StrBuffer[2] = {0, 0};
+ CONST UINT32 SizeOfScreen = (UINT32)((UINT8*)EndOfTheScreen-(UINT8*)ScreenBuffer) / sizeof(CHAR16);
+
+
+ // Check for differences from the old state, one by one
+ // If anything is different, update the screen with Simple Out protocol
+ for(i = 0; i < SizeOfScreen; i++)
+ {
+ if( (*(SaveScreenBuffer+i) != *(ScreenBuffer + i)) ||
+ (*(SaveAttributeBuffer+i) != *(AttributeBuffer + i)) )
+ {
+ StrBuffer[0] = *(ScreenBuffer + i);
+ pScreen->SetCursorPosition(pScreen, i % Columns, i / Columns);
+ pScreen->SetAttribute(pScreen, (UINT8)*(AttributeBuffer + i) );
+ pScreen->OutputString(pScreen, StrBuffer );
+ }
+ }
+
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: RestoreTheScreen
+//
+// Description:
+// This function restores screen of the output device after switching modes
+//
+// Input:
+// IN EFI_HANDLE ControllerHandle - handle of output device to restore
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to protocol instance
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID RestoreTheScreen(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut
+)
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop)))
+ RestoreTextScreen(SimpleOut);
+ else
+ {
+ RestoreUgaScreen(Gop);
+ if(SaveScreenBuffer != NULL)
+ {
+ RestoreTextScreenDelta(SimpleOut);
+ pBS->FreePool(SaveScreenBuffer);
+ pBS->FreePool(SaveAttributeBuffer);
+ }
+ }
+ SimpleOut->SetAttribute(SimpleOut,MasterMode.Attribute);
+ SimpleOut->EnableCursor(SimpleOut,MasterMode.CursorVisible);
+ SimpleOut->SetCursorPosition(SimpleOut,MasterMode.CursorColumn,MasterMode.CursorRow);
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SaveTheScreen
+//
+// Description:
+// This function saves the screen of the output device before switching modes
+//
+// Input:
+// IN EFI_HANDLE ControllerHandle - handle of output device to save
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut - pointer to protocol instance
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID SaveTheScreen(
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleOut)
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+ UINT32 SizeOfScreen, SizeOfAttribute;
+ EFI_TPL OldTpl;
+
+ if (!EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop)))
+ {
+
+ SizeOfScreen = (UINT32)((UINT8*)EndOfTheScreen-(UINT8*)ScreenBuffer);
+ SizeOfAttribute = (UINT32)SizeOfScreen*(sizeof(INT32)/sizeof(CHAR16));
+
+ // Allocate memory for saving the screen state, error out if not enough memory
+ SaveScreenBuffer=Malloc(SizeOfScreen);
+ if(SaveScreenBuffer==NULL) return;
+ SaveAttributeBuffer=Malloc(SizeOfAttribute);
+ if(SaveAttributeBuffer==NULL){
+ pBS->FreePool(SaveScreenBuffer);
+ return;
+ }
+ // Make this high priority so that the saved text screen is exactly
+ // the same as graphics screen
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+
+ // Perform using MemCpy (instead of pBS->MemCopy) to prevent TPL assert
+ MemCpy(SaveScreenBuffer, ScreenBuffer, SizeOfScreen);
+ MemCpy(SaveAttributeBuffer, AttributeBuffer, SizeOfAttribute);
+
+ pBS->RestoreTPL(OldTpl);
+ SaveUgaScreen(Gop);
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: SaveUgaMode
+//
+// Description:
+// This function saves the graphics mode of the output device before switching modes
+//
+// Input:
+// IN EFI_HANDLE ControllerHandle - handle of output device to save
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID SaveUgaMode(
+ IN EFI_HANDLE ControllerHandle
+)
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop)))
+ return;
+
+ TextMode=Gop->Mode->Mode;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: RestoreUgaMode
+//
+// Description:
+// This function restores the graphics mode of the output device after switching modes
+//
+// Input:
+// IN EFI_HANDLE ControllerHandle - handle of output device to restore
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID RestoreUgaMode(
+ IN EFI_HANDLE ControllerHandle
+)
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ if (EFI_ERROR(pBS->HandleProtocol(ControllerHandle, &guidGop, &Gop)))
+ return;
+
+ if (TextMode!=Gop->Mode->Mode)
+ {
+ Gop->SetMode(Gop,TextMode);
+ }
+ else
+ {//Just clear the screen
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Buffer = {0,0,0,0};
+ Gop->Blt( Gop, &Buffer, EfiBltVideoFill,0,0,0,0,
+ Gop->Mode->Info->HorizontalResolution,
+ Gop->Mode->Info->VerticalResolution,
+ 0
+ );
+ }
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSReset
+//
+// Description:
+// This function resets the text output device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN BOOLEAN EV - extended verification flag
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - all devices, handled by splitter were reset successfully
+// EFI_DEVICE_ERROR - error occured during resetting the device
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN EV
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their Reset function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->Reset(SimpleOut->SimpleOut, EV);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ MemReset(This,EV);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSOutputString
+//
+// Description:
+// This function writes a string to the output device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN CHAR16 *String - pointer to string to write
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_DEVICE_ERROR - error occured during output string
+// EFI_WARN_UNKNOWN_GLYPH - some of characters were skipped during output
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ MemOutputString(This,String);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their OutputString function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->OutputString(SimpleOut->SimpleOut, String);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSTestString
+//
+// Description:
+// This function tests whether all characters in String can be drawn on device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN CHAR16 *String - pointer to string to test
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - all characters can be drawn
+// EFI_UNSUPPORTED - there are characters that cannot be drawn
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSTestString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their TestString function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->TestString(SimpleOut->SimpleOut, String);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSQueryMode
+//
+// Description:
+// This function returns information about text mode referred by ModeNum
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN UINTN ModeNum - mode number to obtain information about
+// OUT UINTN *Col - max number of columns supported in this mode
+// OUT UINTN *Row - max number of rows supported in this mode
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_UNSUPPORTED - given mode unsupported
+// EFI_DEVICE_ERROR - error occured during execution
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSQueryMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT UINTN *Col,
+ OUT UINTN *Row
+)
+{
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if((ModeNum >= (UINTN)MasterMode.MaxMode) || (!SupportedModes[ModeNum].AllDevices))
+ return EFI_UNSUPPORTED;
+
+ if (SimpleOut == NULL)
+ {
+ // since we use a default text mode, return that value
+ *Col = 80;
+ *Row = 25;
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ *Col = SupportedModes[ModeNum].Columns;
+ *Row = SupportedModes[ModeNum].Rows;
+ return EFI_SUCCESS;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSSetMode
+//
+// Description:
+// This function sets text mode referred by ModeNumber
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN UINTN ModeNum - mode number to set
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_UNSUPPORTED - given mode unsupported
+// EFI_DEVICE_ERROR - error occured during execution
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSSetMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ INT32 DeviceMode;
+
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if((ModeNum >= (UINTN)MasterMode.MaxMode) || (!SupportedModes[ModeNum].AllDevices))
+ return EFI_UNSUPPORTED;
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ TestStatus = ResizeSplitterBuffer((INT32)ModeNum);
+ if (EFI_ERROR(TestStatus))
+ return TestStatus;
+
+ MasterMode.Mode = (INT32)ModeNum;
+ // we need to loop through all the registered simple text out devices
+ // and call each of their SetMode function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = IsModeSupported(SimpleOut->SimpleOut, ModeNum, &DeviceMode);
+
+ TestStatus = SimpleOut->SimpleOut->SetMode(SimpleOut->SimpleOut, DeviceMode);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ return EFI_ERROR(Status);
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSSetAttribute
+//
+// Description:
+// This function sets the foreground color and background color for the screen
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN UINTN Attribute - attribute to set
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - attribute was changed successfully
+// EFI_DEVICE_ERROR - device had an error
+// EFI_UNSUPPORTED - attribute is not supported
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSSetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their SetAttribute function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->SetAttribute(SimpleOut->SimpleOut, Attribute);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSClearScreen
+//
+// Description:
+// This function clears screen of output device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_DEVICE_ERROR - error occured during execution
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSClearScreen(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their ClearScreen function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->ClearScreen(SimpleOut->SimpleOut);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ MemClearScreen();
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSSetCursorPosition
+//
+// Description:
+// This function sets cursor position of output device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN UINTN Column - column position
+// IN UINTN Row - row position
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_DEVICE_ERROR - error occured during execution
+// EFI_UNSUPPORTED - given position cannot be set
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSSetCursorPosition(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their SetCursorPosition function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->SetCursorPosition(SimpleOut->SimpleOut, Column, Row);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ UpdateMasterMode(SimpleOut->SimpleOut->Mode);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: CSEnableCursor
+//
+// Description:
+// This function enables / disables cursor on the screen
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to protocol instance
+// IN BOOLEAN Visible - if TRUE cursor will be visible, FALSE - not visible
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_DEVICE_ERROR - error occured during execution
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+EFI_STATUS CSEnableCursor(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible )
+{
+ EFI_STATUS Status = EFI_SUCCESS, TestStatus;
+ CON_SPLIT_OUT *SimpleOut = OUTTER(ConOutList.pHead, Link, CON_SPLIT_OUT);
+
+ if (SimpleOut == NULL)
+ return EFI_DEVICE_ERROR;
+
+ // we need to loop through all the registered simple text out devices
+ // and call each of their SetCursorPosition function
+ while ( SimpleOut != NULL)
+ {
+ TestStatus = SimpleOut->SimpleOut->EnableCursor(SimpleOut->SimpleOut, Visible);
+ SimpleOut = OUTTER(SimpleOut->Link.pNext, Link, CON_SPLIT_OUT);
+
+ if (EFI_ERROR(TestStatus))
+ Status = TestStatus;
+ }
+
+ MasterMode.CursorVisible = Visible;
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UpdateMasterMode
+//
+// Description:
+// This function updates splitter mode to values referred by Mode
+//
+// Input:
+// IN SIMPLE_TEXT_OUTPUT_MODE *Mode - pointer to values to be set
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// <AMI_PHDR_END>
+
+VOID UpdateMasterMode(
+ SIMPLE_TEXT_OUTPUT_MODE *Mode)
+{
+ MasterMode.Attribute = Mode->Attribute;
+ MasterMode.CursorColumn = Mode->CursorColumn;
+ MasterMode.CursorRow = Mode->CursorRow;
+ while(MasterMode.CursorColumn>=SupportedModes[MasterMode.Mode].Columns){
+ MasterMode.CursorColumn-=SupportedModes[MasterMode.Mode].Columns;
+ MasterMode.CursorRow++;
+ };
+ if (MasterMode.CursorRow>=SupportedModes[MasterMode.Mode].Rows)
+ MasterMode.CursorRow=SupportedModes[MasterMode.Mode].Rows-1;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/CoreSectionExtraction.c b/Core/CORE_DXE/CoreSectionExtraction.c
new file mode 100644
index 0000000..98f501c
--- /dev/null
+++ b/Core/CORE_DXE/CoreSectionExtraction.c
@@ -0,0 +1,1367 @@
+/*++
+
+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:
+
+ CoreSectionExtraction.c
+
+Abstract:
+
+ Section Extraction Protocol implementation.
+
+ Stream database is implemented as a linked list of section streams,
+ where each stream contains a linked list of children, which may be leaves or
+ encapsulations.
+
+ Children that are encapsulations generate new stream entries
+ when they are created. Streams can also be created by calls to
+ SEP->OpenSectionStream().
+
+ The database is only created far enough to return the requested data from
+ any given stream, or to determine that the requested data is not found.
+
+ If a GUIDed encapsulation is encountered, there are three possiblilites.
+
+ 1) A support protocol is found, in which the stream is simply processed with
+ the support protocol.
+
+ 2) A support protocol is not found, but the data is available to be read
+ without processing. In this case, the database is built up through the
+ recursions to return the data, and a RPN event is set that will enable
+ the stream in question to be refreshed if and when the required section
+ extraction protocol is published.This insures the AuthenticationStatus
+ does not become stale in the cache.
+
+ 3) A support protocol is not found, and the data is not available to be read
+ without it. This results in EFI_PROTOCOL_ERROR.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiFirmwareFileSystem.h"
+
+//
+// Comsumed protocol
+//
+#include EFI_PROTOCOL_DEFINITION (TianoDecompress)
+#include EFI_PROTOCOL_DEFINITION (GuidedSectionExtraction)
+
+//
+// Produced protocol
+//
+#include EFI_PROTOCOL_DEFINITION (SectionExtraction)
+
+//
+// Local defines and typedefs
+//
+#define CORE_SECTION_CHILD_SIGNATURE EFI_SIGNATURE_32('S','X','C','S')
+#define CHILD_SECTION_NODE_FROM_LINK(Node) \
+ CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_LIST_ENTRY Link;
+ UINT32 Type;
+ UINT32 Size;
+ //
+ // StreamBase + OffsetInStream == pointer to section header in stream. The
+ // stream base is always known when walking the sections within.
+ //
+ UINT32 OffsetInStream;
+ //
+ // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an
+ // encapsulating section. Otherwise, it contains the stream handle
+ // of the encapsulated stream. This handle is ALWAYS produced any time an
+ // encapsulating child is encountered, irrespective of whether the
+ // encapsulated stream is processed further.
+ //
+ UINTN EncapsulatedStreamHandle;
+ EFI_GUID *EncapsulationGuid;
+} CORE_SECTION_CHILD_NODE;
+
+#define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S')
+#define STREAM_NODE_FROM_LINK(Node) \
+ CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_LIST_ENTRY Link;
+ UINTN StreamHandle;
+ UINT8 *StreamBuffer;
+ UINTN StreamLength;
+ EFI_LIST Children;
+ //
+ // Authentication status is from GUIDed encapsulations.
+ //
+ UINT32 AuthenticationStatus;
+} CORE_SECTION_STREAM_NODE;
+
+#define NULL_STREAM_HANDLE 0
+
+typedef struct {
+ CORE_SECTION_CHILD_NODE *ChildNode;
+ CORE_SECTION_STREAM_NODE *ParentStream;
+ VOID *Registration;
+ EFI_EVENT Event;
+} RPN_EVENT_CONTEXT;
+
+
+
+//
+// Local prototypes
+//
+
+STATIC
+BOOLEAN
+ChildIsType (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN CORE_SECTION_CHILD_NODE *Child,
+ IN EFI_SECTION_TYPE SearchType,
+ IN EFI_GUID *SectionDefinitionGuid
+ );
+
+STATIC
+VOID
+EFIAPI
+NotifyGuidedExtraction (
+ IN EFI_EVENT Event,
+ IN VOID *RpnContext
+ );
+
+STATIC
+VOID
+CreateGuidedExtractionRpnEvent (
+ IN CORE_SECTION_STREAM_NODE *ParentStream,
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ );
+
+EFI_STATUS
+EFIAPI
+OpenSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ OUT UINTN *SectionStreamHandle
+ );
+
+EFI_STATUS
+EFIAPI
+GetSection (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamHandle,
+ IN EFI_SECTION_TYPE *SectionType,
+ IN EFI_GUID *SectionDefinitionGuid,
+ IN UINTN SectionInstance,
+ IN VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+EFI_STATUS
+EFIAPI
+CloseSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN StreamHandleToClose
+ );
+
+STATIC
+EFI_STATUS
+FindStreamNode (
+ IN UINTN SearchHandle,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream
+ );
+
+STATIC
+EFI_STATUS
+FindChildNode (
+ IN CORE_SECTION_STREAM_NODE *SourceStream,
+ IN EFI_SECTION_TYPE SearchType,
+ IN UINTN *SectionInstance,
+ IN EFI_GUID *SectionDefinitionGuid,
+ OUT CORE_SECTION_CHILD_NODE **FoundChild,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream,
+ OUT UINT32 *AuthenticationStatus
+ );
+
+STATIC
+EFI_STATUS
+CreateChildNode (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN UINT32 ChildOffset,
+ OUT CORE_SECTION_CHILD_NODE **ChildNode
+ );
+
+STATIC
+VOID
+FreeChildNode (
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ );
+
+STATIC
+EFI_STATUS
+OpenSectionStreamEx (
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ IN BOOLEAN AllocateBuffer,
+ IN UINT32 AuthenticationStatus,
+ OUT UINTN *SectionStreamHandle
+ );
+
+STATIC
+BOOLEAN
+IsValidSectionStream (
+ IN VOID *SectionStream,
+ IN UINTN SectionStreamLength
+ );
+
+//
+// Module globals
+//
+EFI_LIST mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot);
+
+EFI_HANDLE mSectionExtractionHandle = NULL;
+
+EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = {
+ OpenSectionStream,
+ GetSection,
+ CloseSectionStream
+};
+
+
+EFI_STATUS
+EFIAPI
+InitializeSectionExtraction (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Entry point of the section extraction code. Initializes an instance of the
+ section extraction interface and installs it on a new handle.
+
+Arguments:
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Install SEP to a new handle
+ //
+ Status = CoreInstallProtocolInterface (
+ &mSectionExtractionHandle,
+ &gEfiSectionExtractionProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSectionExtraction
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+OpenSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ OUT UINTN *SectionStreamHandle
+ )
+/*++
+
+Routine Description:
+ SEP member function. This function creates and returns a new section stream
+ handle to represent the new section stream.
+
+Arguments:
+ This - Indicates the calling context.
+ SectionStreamLength - Size in bytes of the section stream.
+ SectionStream - Buffer containing the new section stream.
+ SectionStreamHandle - A pointer to a caller allocated UINTN that on output
+ contains the new section stream handle.
+
+Returns:
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+ EFI_INVALID_PARAMETER - section stream does not end concident with end of
+ last section.
+
+--*/
+{
+ //
+ // Check to see section stream looks good...
+ //
+ if (!IsValidSectionStream (SectionStream, SectionStreamLength)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return OpenSectionStreamEx (
+ SectionStreamLength,
+ SectionStream,
+ TRUE,
+ 0,
+ SectionStreamHandle
+ );
+}
+
+
+EFI_STATUS
+EFIAPI
+GetSection (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN SectionStreamHandle,
+ IN EFI_SECTION_TYPE *SectionType,
+ IN EFI_GUID *SectionDefinitionGuid,
+ IN UINTN SectionInstance,
+ IN VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ SEP member function. Retrieves requested section from section stream.
+
+Arguments:
+ This: Pointer to SEP instance.
+ SectionStreamHandle: The section stream from which to extract the requested
+ section.
+ SectionType: A pointer to the type of section to search for.
+ SectionDefinitionGuid: If the section type is EFI_SECTION_GUID_DEFINED, then
+ SectionDefinitionGuid indicates which of these types
+ of sections to search for.
+ SectionInstance: Indicates which instance of the requested section to
+ return.
+ Buffer: Double indirection to buffer. If *Buffer is non-null on
+ input, then the buffer is caller allocated. If
+ *Buffer is NULL, then the buffer is callee allocated.
+ In either case, the requried buffer size is returned
+ in *BufferSize.
+ BufferSize: On input, indicates the size of *Buffer if *Buffer is
+ non-null on input. On output, indicates the required
+ size (allocated size if callee allocated) of *Buffer.
+ AuthenticationStatus: Indicates the authentication status of the retrieved
+ section.
+
+Returns:
+ EFI_SUCCESS: Section was retrieved successfully
+ EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section
+ stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED
+ bit set, but there was no corresponding GUIDed Section
+ Extraction Protocol in the handle database. *Buffer is
+ unmodified.
+ EFI_NOT_FOUND: An error was encountered when parsing the SectionStream.
+ This indicates the SectionStream is not correctly
+ formatted.
+ EFI_NOT_FOUND: The requested section does not exist.
+ EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the
+ request.
+ EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist.
+ EFI_WARN_TOO_SMALL: The size of the caller allocated input buffer is
+ insufficient to contain the requested section. The
+ input buffer is filled and contents are section contents
+ are truncated.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ CORE_SECTION_CHILD_NODE *ChildNode;
+ CORE_SECTION_STREAM_NODE *ChildStreamNode;
+ UINTN CopySize;
+ UINT32 ExtractedAuthenticationStatus;
+ UINTN Instance;
+ UINT8 *CopyBuffer;
+ UINTN SectionSize;
+
+
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ Instance = SectionInstance + 1;
+
+ //
+ // Locate target stream
+ //
+ Status = FindStreamNode (SectionStreamHandle, &StreamNode);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto GetSection_Done;
+ }
+
+ //
+ // Found the stream, now locate and return the appropriate section
+ //
+ if (SectionType == NULL) {
+ //
+ // SectionType == NULL means return the WHOLE section stream...
+ //
+ CopySize = StreamNode->StreamLength;
+ CopyBuffer = StreamNode->StreamBuffer;
+ *AuthenticationStatus = StreamNode->AuthenticationStatus;
+ } else {
+ //
+ // There's a requested section type, so go find it and return it...
+ //
+ Status = FindChildNode (
+ StreamNode,
+ *SectionType,
+ &Instance,
+ SectionDefinitionGuid,
+ &ChildNode,
+ &ChildStreamNode,
+ &ExtractedAuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ goto GetSection_Done;
+ }
+ CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER);
+ CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER);
+ *AuthenticationStatus = ExtractedAuthenticationStatus;
+ }
+
+ SectionSize = CopySize;
+ if (*Buffer != NULL) {
+ //
+ // Caller allocated buffer. Fill to size and return required size...
+ //
+ if (*BufferSize < CopySize) {
+ Status = EFI_WARN_BUFFER_TOO_SMALL;
+ CopySize = *BufferSize;
+ }
+ } else {
+ //
+ // Callee allocated buffer. Allocate buffer and return size.
+ //
+ *Buffer = CoreAllocateBootServicesPool (CopySize);
+ if (*Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto GetSection_Done;
+ }
+ }
+ EfiCommonLibCopyMem (*Buffer, CopyBuffer, CopySize);
+ *BufferSize = SectionSize;
+
+GetSection_Done:
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CloseSectionStream (
+ IN EFI_SECTION_EXTRACTION_PROTOCOL *This,
+ IN UINTN StreamHandleToClose
+ )
+/*++
+
+Routine Description:
+ SEP member function. Deletes an existing section stream
+
+Arguments:
+ This - Indicates the calling context.
+ StreamHandleToClose - Indicates the stream to close
+
+Returns:
+ EFI_SUCCESS
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+ EFI_INVALID_PARAMETER - section stream does not end concident with end of
+ last section.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ EFI_LIST *Link;
+ CORE_SECTION_CHILD_NODE *ChildNode;
+
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+
+ //
+ // Locate target stream
+ //
+ Status = FindStreamNode (StreamHandleToClose, &StreamNode);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Found the stream, so close it
+ //
+ RemoveEntryList (&StreamNode->Link);
+ while (!IsListEmpty (&StreamNode->Children)) {
+ Link = GetFirstNode (&StreamNode->Children);
+ ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);
+ FreeChildNode (ChildNode);
+ }
+ CoreFreePool (StreamNode->StreamBuffer);
+ CoreFreePool (StreamNode);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+
+STATIC
+BOOLEAN
+ChildIsType (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN CORE_SECTION_CHILD_NODE *Child,
+ IN EFI_SECTION_TYPE SearchType,
+ IN EFI_GUID *SectionDefinitionGuid
+ )
+/*++
+
+Routine Description:
+ Worker function. Determine if the input stream:child matches the input type.
+
+Arguments:
+ Stream - Indicates the section stream associated with the child
+ Child - Indicates the child to check
+ SearchType - Indicates the type of section to check against for
+ SectionDefinitionGuid - Indicates the GUID to check against if the type is
+ EFI_SECTION_GUID_DEFINED
+Returns:
+ TRUE - The child matches
+ FALSE - The child doesn't match
+
+--*/
+{
+ EFI_GUID_DEFINED_SECTION *GuidedSection;
+
+ if (SearchType == EFI_SECTION_ALL) {
+ return TRUE;
+ }
+ if (Child->Type != SearchType) {
+ return FALSE;
+ }
+//*** AMI PORTING BEGIN ***//
+// Bug fix: ReadSection function of the FV protocol (FvReadFileSection)
+// didn't work for GUID defined sections (always returned EFI_NOT_FOUND).
+// When this function is called from FvReadFileSection, SectionDefinitionGuid is always NULL.
+// If SectionDefinitionGuid is NULL, return TRUE (the section type matches).
+// if (SearchType != EFI_SECTION_GUID_DEFINED) {
+ if (SearchType != EFI_SECTION_GUID_DEFINED || SectionDefinitionGuid == NULL) {
+//*** AMI PORTING END *****//
+ return TRUE;
+ }
+ GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream);
+ return EfiCompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid);
+}
+
+
+STATIC
+EFI_STATUS
+FindChildNode (
+ IN CORE_SECTION_STREAM_NODE *SourceStream,
+ IN EFI_SECTION_TYPE SearchType,
+ IN OUT UINTN *SectionInstance,
+ IN EFI_GUID *SectionDefinitionGuid,
+ OUT CORE_SECTION_CHILD_NODE **FoundChild,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Worker function Recursively searches / builds section stream database
+ looking for requested section.
+
+Arguments:
+ SourceStream - Indicates the section stream in which to do the search.
+ SearchType - Indicates the type of section to search for.
+ SectionInstance - Indicates which instance of section to find. This is
+ an in/out parameter to deal with recursions.
+ SectionDefinitionGuid - Guid of section definition
+ FoundChild - Output indicating the child node that is found.
+ FoundStream - Output indicating which section stream the child was
+ found in. If this stream was generated as a result of
+ an encapsulation section, the streamhandle is visible
+ within the SEP driver only.
+ AuthenticationStatus- Indicates the authentication status of the found section.
+
+Returns:
+ EFI_SUCCESS - Child node was found and returned.
+ EFI_OUT_OF_RESOURCES- Memory allocation failed.
+ EFI_NOT_FOUND - Requested child node does not exist.
+ EFI_PROTOCOL_ERROR - a required GUIDED section extraction protocol does not
+ exist
+
+--*/
+{
+ CORE_SECTION_CHILD_NODE *CurrentChildNode;
+ CORE_SECTION_CHILD_NODE *RecursedChildNode;
+ CORE_SECTION_STREAM_NODE *RecursedFoundStream;
+ UINT32 NextChildOffset;
+ EFI_STATUS ErrorStatus;
+ EFI_STATUS Status;
+
+ CurrentChildNode = NULL;
+ ErrorStatus = EFI_NOT_FOUND;
+
+ if (SourceStream->StreamLength == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (IsListEmpty (&SourceStream->Children) &&
+ SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) {
+ //
+ // This occurs when a section stream exists, but no child sections
+ // have been parsed out yet. Therefore, extract the first child and add it
+ // to the list of children so we can get started.
+ //
+ Status = CreateChildNode (SourceStream, 0, &CurrentChildNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // At least one child has been parsed out of the section stream. So, walk
+ // through the sections that have already been parsed out looking for the
+ // requested section, if necessary, continue parsing section stream and
+ // adding children until either the requested section is found, or we run
+ // out of data
+ //
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children));
+
+ for (;;) {
+ if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) {
+ //
+ // The type matches, so check the instance count to see if it's the one we want
+ //
+ (*SectionInstance)--;
+ if (*SectionInstance == 0) {
+ //
+ // Got it!
+ //
+ *FoundChild = CurrentChildNode;
+ *FoundStream = SourceStream;
+ *AuthenticationStatus = SourceStream->AuthenticationStatus;
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
+ //
+ // If the current node is an encapsulating node, recurse into it...
+ //
+ Status = FindChildNode (
+ (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle,
+ SearchType,
+ SectionInstance,
+ SectionDefinitionGuid,
+ &RecursedChildNode,
+ &RecursedFoundStream,
+ AuthenticationStatus
+ );
+ //
+ // If the status is not EFI_SUCCESS, just save the error code and continue
+ // to find the request child node in the rest stream.
+ //
+ if (*SectionInstance == 0) {
+ ASSERT_EFI_ERROR (Status);
+ *FoundChild = RecursedChildNode;
+ *FoundStream = RecursedFoundStream;
+ return EFI_SUCCESS;
+ } else {
+ ErrorStatus = Status;
+ }
+ }
+
+ if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) {
+ //
+ // We haven't found the child node we're interested in yet, but there's
+ // still more nodes that have already been parsed so get the next one
+ // and continue searching..
+ //
+ CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link));
+ } else {
+ //
+ // We've exhausted children that have already been parsed, so see if
+ // there's any more data and continue parsing out more children if there
+ // is.
+ //
+ NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size;
+ //
+ // Round up to 4 byte boundary
+ //
+ NextChildOffset += 3;
+ NextChildOffset &= ~(UINTN)3;
+ if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) {
+ //
+ // There's an unparsed child remaining in the stream, so create a new child node
+ //
+ Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ ASSERT (EFI_ERROR (ErrorStatus));
+ return ErrorStatus;
+ }
+ }
+ }
+}
+
+
+STATIC
+EFI_STATUS
+CreateChildNode (
+ IN CORE_SECTION_STREAM_NODE *Stream,
+ IN UINT32 ChildOffset,
+ OUT CORE_SECTION_CHILD_NODE **ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Constructor for new child nodes.
+
+Arguments:
+ Stream - Indicates the section stream in which to add the child.
+ ChildOffset - Indicates the offset in Stream that is the beginning
+ of the child section.
+ ChildNode - Indicates the Callee allocated and initialized child.
+
+Returns:
+ EFI_SUCCESS - Child node was found and returned.
+ EFI_OUT_OF_RESOURCES- Memory allocation failed.
+ EFI_PROTOCOL_ERROR - Encapsulation sections produce new stream handles when
+ the child node is created. If the section type is GUID
+ defined, and the extraction GUID does not exist, and
+ producing the stream requires the GUID, then a protocol
+ error is generated and no child is produced.
+ Values returned by OpenSectionStreamEx.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMPRESSION_SECTION *CompressionHeader;
+ EFI_GUID_DEFINED_SECTION *GuidedHeader;
+ EFI_TIANO_DECOMPRESS_PROTOCOL *Decompress;
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
+ VOID *NewStreamBuffer;
+ VOID *ScratchBuffer;
+ UINT32 ScratchSize;
+ UINTN NewStreamBufferSize;
+ UINT32 AuthenticationStatus;
+ UINT32 SectionLength;
+
+ CORE_SECTION_CHILD_NODE *Node;
+
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset);
+
+ //
+ // Allocate a new node
+ //
+ *ChildNode = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_CHILD_NODE));
+ Node = *ChildNode;
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Now initialize it
+ //
+ Node->Signature = CORE_SECTION_CHILD_SIGNATURE;
+ Node->Type = SectionHeader->Type;
+ Node->Size = SECTION_SIZE (SectionHeader);
+ Node->OffsetInStream = ChildOffset;
+ Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE;
+ Node->EncapsulationGuid = NULL;
+
+ //
+ // If it's an encapsulating section, then create the new section stream also
+ //
+ switch (Node->Type) {
+ case EFI_SECTION_COMPRESSION:
+ //
+ // Get the CompressionSectionHeader
+ //
+ ASSERT (Node->Size >= sizeof (EFI_COMPRESSION_SECTION));
+
+ CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader;
+
+ //
+ // Allocate space for the new stream
+ //
+ if (CompressionHeader->UncompressedLength > 0) {
+ NewStreamBufferSize = CompressionHeader->UncompressedLength;
+ NewStreamBuffer = CoreAllocateBootServicesPool (NewStreamBufferSize);
+ if (NewStreamBuffer == NULL) {
+ CoreFreePool (Node);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (CompressionHeader->CompressionType == EFI_NOT_COMPRESSED) {
+ //
+ // stream is not actually compressed, just encapsulated. So just copy it.
+ //
+ EfiCommonLibCopyMem (NewStreamBuffer, CompressionHeader + 1, NewStreamBufferSize);
+ } else if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION ||
+ CompressionHeader->CompressionType == EFI_CUSTOMIZED_COMPRESSION) {
+ //
+ // Decompress the stream
+ //
+ if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION) {
+ Status = CoreLocateProtocol (&gEfiTianoDecompressProtocolGuid, NULL, &Decompress);
+ } else {
+ Status = CoreLocateProtocol (&gEfiCustomizedDecompressProtocolGuid, NULL, &Decompress);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+//*** AMI PORTING BEGIN ***//
+// Bug fix: What if the protocol has not been found?
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return EFI_PROTOCOL_ERROR;
+ }
+//*** AMI PORTING END *****//
+
+ Status = Decompress->GetInfo (
+ Decompress,
+ CompressionHeader + 1,
+ Node->Size - sizeof (EFI_COMPRESSION_SECTION),
+ (UINT32 *)&NewStreamBufferSize,
+ &ScratchSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (NewStreamBufferSize == CompressionHeader->UncompressedLength);
+
+ ScratchBuffer = CoreAllocateBootServicesPool (ScratchSize);
+ if (ScratchBuffer == NULL) {
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Decompress->Decompress (
+ Decompress,
+ CompressionHeader + 1,
+ Node->Size - sizeof (EFI_COMPRESSION_SECTION),
+ NewStreamBuffer,
+ (UINT32)NewStreamBufferSize,
+ ScratchBuffer,
+ ScratchSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ CoreFreePool (ScratchBuffer);
+ }
+ } else {
+ NewStreamBuffer = NULL;
+ NewStreamBufferSize = 0;
+ }
+
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ Stream->AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ CoreFreePool (NewStreamBuffer);
+ return Status;
+ }
+ break;
+
+ case EFI_SECTION_GUID_DEFINED:
+ GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader;
+ Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid;
+ Status = CoreLocateProtocol (Node->EncapsulationGuid, NULL, &GuidedExtraction);
+ if (!EFI_ERROR (Status)) {
+ //
+ // NewStreamBuffer is always allocated by ExtractSection... No caller
+ // allocation here.
+ //
+ Status = GuidedExtraction->ExtractSection (
+ GuidedExtraction,
+ GuidedHeader,
+ &NewStreamBuffer,
+ &NewStreamBufferSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (*ChildNode);
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Make sure we initialize the new stream with the correct
+ // authentication status for both aggregate and local status fields.
+ //
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
+ //
+ // OR in the parent stream's aggregate status.
+ //
+ AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;
+ } else {
+ //
+ // since there's no authentication data contributed by the section,
+ // just inherit the full value from our immediate parent.
+ //
+ AuthenticationStatus = Stream->AuthenticationStatus;
+ }
+
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (*ChildNode);
+ CoreFreePool (NewStreamBuffer);
+ return Status;
+ }
+ } else {
+ //
+ // There's no GUIDed section extraction protocol available.
+ //
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
+ //
+ // If the section REQUIRES an extraction protocol, then we're toast
+ //
+ CoreFreePool (*ChildNode);
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Figure out the proper authentication status
+ //
+ AuthenticationStatus = Stream->AuthenticationStatus;
+ if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
+ //
+ // The local status of the new stream is contained in
+ // AuthenticaionStatus. This value needs to be ORed into the
+ // Aggregate bits also...
+ //
+
+ //
+ // Clear out and initialize the local status
+ //
+ AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL;
+ AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED;
+ //
+ // OR local status into aggregate status
+ //
+ AuthenticationStatus |= AuthenticationStatus >> 16;
+ }
+
+ SectionLength = SECTION_SIZE (GuidedHeader);
+ Status = OpenSectionStreamEx (
+ SectionLength - GuidedHeader->DataOffset,
+ (UINT8 *) GuidedHeader + GuidedHeader->DataOffset,
+ TRUE,
+ AuthenticationStatus,
+ &Node->EncapsulatedStreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Node);
+ return Status;
+ }
+ }
+
+ if ((AuthenticationStatus & EFI_LOCAL_AUTH_STATUS_ALL) ==
+ (EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED)) {
+ //
+ // Need to register for RPN for when the required GUIDed extraction
+ // protocol becomes available. This will enable us to refresh the
+ // AuthenticationStatus cached in the Stream if it's ever requested
+ // again.
+ //
+ CreateGuidedExtractionRpnEvent (Stream, Node);
+ }
+
+ break;
+
+ default:
+
+ //
+ // Nothing to do if it's a leaf
+ //
+ break;
+ }
+
+ //
+ // Last, add the new child node to the stream
+ //
+ InsertTailList (&Stream->Children, &Node->Link);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+VOID
+CreateGuidedExtractionRpnEvent (
+ IN CORE_SECTION_STREAM_NODE *ParentStream,
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Constructor for RPN event if needed to keep AuthenticationStatus
+ cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears...
+
+Arguments:
+ ParentStream - Indicates the parent of the ecnapsulation section (child)
+ ChildNode - Indicates the child node that is the encapsulation section.
+
+Returns:
+ None
+
+--*/
+{
+ RPN_EVENT_CONTEXT *Context;
+
+ //
+ // Allocate new event structure and context
+ //
+ Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT));
+ ASSERT (Context != NULL);
+
+ Context->ChildNode = ChildNode;
+ Context->ParentStream = ParentStream;
+
+ Context->Event = CoreCreateProtocolNotifyEvent (
+ Context->ChildNode->EncapsulationGuid,
+ EFI_TPL_NOTIFY,
+ NotifyGuidedExtraction,
+ Context,
+ &Context->Registration,
+ FALSE
+ );
+}
+
+
+STATIC
+VOID
+EFIAPI
+NotifyGuidedExtraction (
+ IN EFI_EVENT Event,
+ IN VOID *RpnContext
+ )
+/*++
+
+Routine Description:
+ RPN callback function. Removes a stale section stream and re-initializes it
+ with an updated AuthenticationStatus.
+
+Arguments:
+ Event - The event that fired
+ RpnContext - A pointer to the context that allows us to identify
+ the relevent encapsulation...
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GUID_DEFINED_SECTION *GuidedHeader;
+ EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction;
+ VOID *NewStreamBuffer;
+ UINTN NewStreamBufferSize;
+ UINT32 AuthenticationStatus;
+ RPN_EVENT_CONTEXT *Context;
+
+ Context = RpnContext;
+
+ Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle);
+ if (!EFI_ERROR (Status)) {
+ //
+ // The stream closed successfully, so re-open the stream with correct AuthenticationStatus
+ //
+
+ GuidedHeader = (EFI_GUID_DEFINED_SECTION *)
+ (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream);
+ ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED);
+
+ Status = CoreLocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, &GuidedExtraction);
+ ASSERT_EFI_ERROR (Status);
+
+
+ Status = GuidedExtraction->ExtractSection (
+ GuidedExtraction,
+ GuidedHeader,
+ &NewStreamBuffer,
+ &NewStreamBufferSize,
+ &AuthenticationStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // OR in the parent stream's aggregagate status.
+ //
+ AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL;
+ Status = OpenSectionStreamEx (
+ NewStreamBufferSize,
+ NewStreamBuffer,
+ FALSE,
+ AuthenticationStatus,
+ &Context->ChildNode->EncapsulatedStreamHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // If above, the stream did not close successfully, it indicates it's
+ // alread been closed by someone, so just destroy the event and be done with
+ // it.
+ //
+
+ CoreCloseEvent (Event);
+ CoreFreePool (Context);
+}
+
+
+STATIC
+VOID
+FreeChildNode (
+ IN CORE_SECTION_CHILD_NODE *ChildNode
+ )
+/*++
+
+Routine Description:
+ Worker function. Destructor for child nodes.
+
+Arguments:
+ ChildNode - Indicates the node to destroy
+
+Returns:
+ none
+
+--*/
+{
+ ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE);
+ //
+ // Remove the child from it's list
+ //
+ RemoveEntryList (&ChildNode->Link);
+
+ if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
+ //
+ // If it's an encapsulating section, we close the resulting section stream.
+ // CloseSectionStream will free all memory associated with the stream.
+ //
+ CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle);
+ }
+ //
+ // Last, free the child node itself
+ //
+ CoreFreePool (ChildNode);
+}
+
+
+STATIC
+EFI_STATUS
+OpenSectionStreamEx (
+ IN UINTN SectionStreamLength,
+ IN VOID *SectionStream,
+ IN BOOLEAN AllocateBuffer,
+ IN UINT32 AuthenticationStatus,
+ OUT UINTN *SectionStreamHandle
+ )
+/*++
+
+ Routine Description:
+ Worker function. Constructor for section streams.
+
+ Arguments:
+ SectionStreamLength - Size in bytes of the section stream.
+ SectionStream - Buffer containing the new section stream.
+ AllocateBuffer - Indicates whether the stream buffer is to be copied
+ or the input buffer is to be used in place.
+ AuthenticationStatus- Indicates the default authentication status for the
+ new stream.
+ SectionStreamHandle - A pointer to a caller allocated section stream handle.
+
+ Returns:
+ EFI_SUCCESS - Stream was added to stream database.
+ EFI_OUT_OF_RESOURCES - memory allocation failed.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *NewStream;
+ EFI_TPL OldTpl;
+
+ //
+ // Allocate a new stream
+ //
+ NewStream = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE));
+ if (NewStream == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (AllocateBuffer) {
+ //
+ // if we're here, we're double buffering, allocate the buffer and copy the
+ // data in
+ //
+ if (SectionStreamLength > 0) {
+ NewStream->StreamBuffer = CoreAllocateBootServicesPool (SectionStreamLength);
+ if (NewStream->StreamBuffer == NULL) {
+ CoreFreePool (NewStream);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy in stream data
+ //
+ EfiCommonLibCopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength);
+ } else {
+ //
+ // It's possible to have a zero length section stream.
+ //
+ NewStream->StreamBuffer = NULL;
+ }
+ } else {
+ //
+ // If were here, the caller has supplied the buffer (it's an internal call)
+ // so just assign the buffer. This happens when we open section streams
+ // as a result of expanding an encapsulating section.
+ //
+ NewStream->StreamBuffer = SectionStream;
+ }
+
+ //
+ // Initialize the rest of the section stream
+ //
+ NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE;
+ NewStream->StreamHandle = (UINTN) NewStream;
+ NewStream->StreamLength = SectionStreamLength;
+ InitializeListHead (&NewStream->Children);
+ NewStream->AuthenticationStatus = AuthenticationStatus;
+
+ //
+ // Add new stream to stream list
+ //
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ InsertTailList (&mStreamRoot, &NewStream->Link);
+ CoreRestoreTpl (OldTpl);
+
+ *SectionStreamHandle = NewStream->StreamHandle;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+FindStreamNode (
+ IN UINTN SearchHandle,
+ OUT CORE_SECTION_STREAM_NODE **FoundStream
+ )
+/*++
+
+ Routine Description:
+ Worker function. Search stream database for requested stream handle.
+
+ Arguments:
+ SearchHandle - Indicates which stream to look for.
+ FoundStream - Output pointer to the found stream.
+
+ Returns:
+ EFI_SUCCESS - StreamHandle was found and *FoundStream contains
+ the stream node.
+ EFI_NOT_FOUND - SearchHandle was not found in the stream database.
+
+--*/
+{
+ CORE_SECTION_STREAM_NODE *StreamNode;
+
+ if (!IsListEmpty (&mStreamRoot)) {
+ StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot));
+ for (;;) {
+ if (StreamNode->StreamHandle == SearchHandle) {
+ *FoundStream = StreamNode;
+ return EFI_SUCCESS;
+ } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) {
+ break;
+ } else {
+ StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link));
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+STATIC
+BOOLEAN
+IsValidSectionStream (
+ IN VOID *SectionStream,
+ IN UINTN SectionStreamLength
+ )
+/*++
+
+Routine Description:
+ Check if a stream is valid.
+
+Arguments:
+ SectionStream - The section stream to be checked
+ SectionStreamLength - The length of section stream
+
+Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ UINTN TotalLength;
+ UINTN SectionLength;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;
+
+ TotalLength = 0;
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream;
+
+ while (TotalLength < SectionStreamLength) {
+ SectionLength = SECTION_SIZE (SectionHeader);
+ TotalLength += SectionLength;
+
+ if (TotalLength == SectionStreamLength) {
+ return TRUE;
+ }
+
+ //
+ // Move to the next byte following the section...
+ //
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
+
+ //
+ // Figure out where the next section begins
+ //
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3);
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3);
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
+ SectionHeader = NextSectionHeader;
+ }
+
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/Core/CORE_DXE/DataHub.c b/Core/CORE_DXE/DataHub.c
new file mode 100644
index 0000000..c2aa760
--- /dev/null
+++ b/Core/CORE_DXE/DataHub.c
@@ -0,0 +1,681 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/DataHub.c 5 7/08/09 5:54p Vyacheslava $
+//
+// $Revision: 5 $
+//
+// $Date: 7/08/09 5:54p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/DataHub.c $
+//
+// 5 7/08/09 5:54p Vyacheslava
+// Updated according to the coding standards.
+//
+// 4 12/16/08 1:32a Iminglin
+// The function value of FindNextFiltermatch for compliance.
+//
+// 3 11/07/07 12:13p Felixp
+// Bug fixes in record filtering logic.
+// Old code was treating FilterClass parameter passed into
+// RegisterFilterDriver routine as requested class value.
+// However, data hub specification defines this parameter as a bit map of
+// requested data classes.
+//
+// 2 9/05/07 5:51p Felixp
+// 1. LogData routine is updated.
+// Core that initializes RecordSize field of the data hub record
+// header is updated to include header size (the header size was excluded
+// in the previous Core verions).<br />
+// DataHub specification is vague regarding the RecordSize field.
+// It says RecordSize is "Size of the data in the record in
+// bytes".
+// It's not clear if it should include or exclude the header size.
+// In EDK DataHub implenetation RecordSize includes the header.
+// Aptio implementation is updated to comply with EDK
+// implementation.
+// 2. When time is not available initialize time fields with default
+// values
+//
+// 1 1/28/05 12:45p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 12/22/04 6:19p Admin
+//
+// 1 12/22/04 6:18p Admin
+//
+// 6 11/12/04 3:13p Markw
+// Added signal event, to get previously logged data.
+//
+// 5 4/17/04 4:23p Felixp
+//
+// 4 3/24/04 10:17a Markw
+// Using AmiDxeLib instead AmiLib.
+//
+// 3 3/23/04 5:45p Markw
+// Added function and table headers (comments) to the file.
+//
+// 2 3/20/04 10:46a Felixp
+//
+// 1 3/16/04 2:38p Markw
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: DataHub_c
+//
+// Description: Log data to be retrieved by functions or call events
+// for data matching filter.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <AmiDxeLib.h>
+#include <Protocol\DataHub.h>
+
+EFI_GUID gDataHubProtocolGuid = EFI_DATA_HUB_PROTOCOL_GUID;
+
+//**********************************************************************
+//<AMI_THDR_START>
+//
+// Name: DATA_RECORD
+//
+// Description: This structure describes the Data Record header and data.
+//
+// Fields:
+// Name Type Description
+// ------------------------------------------------------------
+// Link DATA_RECORD* Next link
+// RecordHeader EFI_DATA_RECORD_HEADER Log Record Header
+///
+// Directly following Header (&RecordHeader + 1) is the data.
+//
+//<AMI_THDR_END>
+//**********************************************************************
+
+typedef struct _DATA_RECORD DATA_RECORD;
+struct _DATA_RECORD {
+ DATA_RECORD *Link;
+ EFI_DATA_RECORD_HEADER RecordHeader;
+};
+
+//**********************************************************************
+//<AMI_THDR_START>
+//
+// Name: FILTER
+//
+// Description: This structure describes the filter link.
+//
+// Fields:
+// Name Type Description
+// ------------------------------------------------------------
+// Link FILTER* Next link
+// Event EFI_EVENT Event
+// Class UINT64 Class (0 if no class filtering)
+// DataRecordGuid EFI_GUID Guid (undefined in no guid filtering)
+// isGuid BOOLEAN TRUE if guid filtering.
+// LastRead DATA_RECORD* Last read record for the filter.
+//
+//<AMI_THDR_END>
+//**********************************************************************
+
+typedef struct _FILTER FILTER;
+struct _FILTER {
+ FILTER *Link;
+ EFI_EVENT Event;
+ UINT64 Class;
+ EFI_GUID DataRecordGuid;
+ BOOLEAN isGuid;
+ DATA_RECORD *LastRead;
+};
+
+
+FILTER *gFilHead = 0; //Filter Head
+DATA_RECORD *gHead = 0; //Data Record Head
+DATA_RECORD *gTail = 0; //Data Record Count
+UINT64 gLogCount = 0; //Unique log count.
+DATA_RECORD *gCache = 0; //Last reocrd cache.
+
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: FindNextFilterMatch
+//
+// Description: Search log to find next record that matches filter.
+//
+// Input:
+// DATA_RECORD *Record
+// FILTER *Filter
+//
+// Output: DATA_RECORD*
+//
+// Referrals: guidcmp
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Starting at the current record for filter matching.
+// 2. If Class and Class doesn't match continue at step 1 for next record.
+// 3. If guid and DataRecordGuid doesn't match continue at step 1 for next record.
+// 4. Match, return record.
+// 5. If Steps 1-4, doesn't find any matching filter, return 0.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+DATA_RECORD* FindNextFilterMatch(
+ DATA_RECORD *Record,
+ FILTER *Filter)
+{
+ for (; Record; Record=Record->Link) {
+ if ( Filter->Class &&
+ !(Filter->Class & Record->RecordHeader.DataRecordClass) )
+ continue;
+
+ if ( Filter->isGuid &&
+ guidcmp(&Filter->DataRecordGuid,&Record->RecordHeader.DataRecordGuid) != 0 )
+ continue;
+
+ return Record;
+ }
+
+ return NULL;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: LogData
+//
+// Description: Log the record. If matching event, signal it.
+//
+// Input:
+// IN EFI_DATA_HUB_PROTOCOL *This
+// IN EFI_GUID *DataRecordGuid
+// IN EFI_GUID *ProducerName
+// IN UINT64 DataRecordClass
+// IN VOID *RawData
+// IN UINT32 RawDataSize
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Event logged.
+// * EFI_OUT_OF_RESOUCES - Not enough resources to log data.
+//
+// Modified: gHead gTail
+//
+// Referrals: AllocatePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Allocate memory enough for data record. If not enough memory, return EFI_OUT_OF_RESOURCES.
+// 2. Fill data record header and increase log count.
+// 3. Fill data to log.
+// 4. Add record to log.
+// 5. Check for a matching filter.
+// 6. If matching filter, signal event.
+// 7. Return EFI_SUCCESS.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS LogData(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_GUID *DataRecordGuid,
+ IN EFI_GUID *ProducerName,
+ IN UINT64 DataRecordClass,
+ IN VOID *RawData,
+ IN UINT32 RawDataSize
+)
+{
+ EFI_DATA_RECORD_HEADER *RcdHdr;
+ DATA_RECORD *Record;
+ FILTER *Filter;
+ UINT8 *Data;
+ EFI_STATUS Status;
+
+ //16 dummy bytes to make sure struct alignment isn't an issue in platform.
+ if ( pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(DATA_RECORD) + RawDataSize + 16,
+ &Record ) != EFI_SUCCESS )
+ return EFI_OUT_OF_RESOURCES;
+
+ RcdHdr = &Record->RecordHeader;
+
+ Record->Link = 0;
+ RcdHdr->Version = EFI_DATA_RECORD_HEADER_VERSION;
+ RcdHdr->HeaderSize = sizeof(EFI_DATA_RECORD_HEADER);
+//DataHub specification is vague regarding the RecordSize field.
+//It says RecordSize is "Size of the data in the record in bytes".
+//It's not clear if it should include or exclude the header size.
+//It's sounds more like it should not, however,
+//in EDK DataHub implenetation RecordSize includes the header.
+//For the sake of compatibility let's do the same.
+ RcdHdr->RecordSize = RawDataSize+sizeof(EFI_DATA_RECORD_HEADER);
+ RcdHdr->DataRecordGuid = *DataRecordGuid;
+ RcdHdr->ProducerName = *ProducerName;
+ RcdHdr->DataRecordClass = DataRecordClass;
+ RcdHdr->LogMonotonicCount = ++gLogCount; //Each log count must be unique.
+ Status = pRS->GetTime(&(RcdHdr->LogTime),NULL);
+
+ if (EFI_ERROR(Status)) { //time not available, set default values
+ RcdHdr->LogTime.Year = 0;
+ RcdHdr->LogTime.Month = 1;
+ RcdHdr->LogTime.Day = 1;
+ RcdHdr->LogTime.Hour = 0;
+ RcdHdr->LogTime.Minute = 0;
+ RcdHdr->LogTime.Second = 0;
+ }
+
+ //Store data to be logged.
+ Data = (UINT8*)(RcdHdr + 1);
+ MemCpy(
+ Data,
+ RawData,
+ RawDataSize
+ );
+
+ //Add record to log.
+ if (!gHead)
+ gHead = Record;
+ else
+ gTail->Link = Record;
+
+ gTail = Record;
+
+ //Check for matching filter.
+ for (Filter = gFilHead; Filter; Filter = Filter->Link) {
+ if ( Filter->Class &&
+ !(Filter->Class & DataRecordClass) )
+ continue;
+
+ if ( Filter->isGuid &&
+ guidcmp(&Filter->DataRecordGuid, DataRecordGuid) != 0 )
+ continue;
+
+ pBS->SignalEvent(Filter->Event);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: GetNextDataRecord
+//
+// Description: Search log to find next record that matches Count or filter.
+// Return next record or if Filter, next record matching filter.
+//
+// Input:
+// IN EFI_DATA_HUB_PROTOCOL *This
+// IN OUT UINT64 *MonotonicCount
+// IN EFI_EVENT *FilterDriver OPTIONAL
+// OUT EFI_DATA_RECORD_HEADER **Record
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - If Data Record returned.
+// * EFI_NOT_FOUND - Data Record not found.
+// * EFI_INVALID_PARAMETER - *FilterDriver doesn't match registered filters.
+//
+// Modified: gCache
+//
+// Referrals: FindNextFilterMatch
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If no logged records, return EFI_NOT_FOUND.
+// 2. If using FilterDriver, find filter. If filter not found, return EFI_INVALID_PARAMETER;
+// 3. If *MonotonicCount != 0, go to step 14.
+// ---*MonotonicCount = 0---
+// 4. If no filter driver, set *MonotonicCount = 1, go to step 14.
+// ---Filter Driver---
+// 5. If no last read, start at Head.
+// 6. If last read, start at the next. If no next, return EFI_NOT_FOUND.
+// 7. Find record matching filter.
+// 8. If no match, set last read to tail, and return EFI_NOT_FOUND.
+// 9. Set *Record to found record, and set LastRead to record.
+// 10. Find next match, to get *MonotonicCount.
+// 11. If not found, set *MonotonicCount = 0.
+// 12. Set cache to link.
+// 13. Return EFI_SUCCESS.
+// ---MontonicCount exists---
+// 14. Get starting link. If after cache, use cache, otherwise use head.
+// 15. Search until log count is found, regardless of filter.
+// 16. If not found, return EFI_NOT_FOUND.
+// 17. If filter set LastRead.
+// 18. If last link, *MontonicCount = 0. Go to step 21.
+// ---If not last link,---
+// 19. If FilterDriver, find next match for *MonotonicCounter.
+// 20. If no next match, set *MonotonicCounter = 0.
+// -------
+// 21. Set cache. Return EFI_SUCCESS.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS GetNextDataRecord(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN OUT UINT64 *MonotonicCount,
+ IN EFI_EVENT *FilterDriver OPTIONAL,
+ OUT EFI_DATA_RECORD_HEADER **Record
+)
+{
+ DATA_RECORD *Link;
+ FILTER *Filter;
+
+ if (!gHead)
+ return EFI_NOT_FOUND; //Any records logged?
+
+ //Find Matching filter
+ if (FilterDriver) {
+ //In future, binary search may be more efficient, or some caching.
+ for (Filter = gFilHead; Filter && Filter->Event != *FilterDriver; Filter = Filter->Link)
+ ; //Find matching Filter for Event.
+
+ if (!Filter)
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //If monotonic count is zero?
+ if (!*MonotonicCount) {
+ //If filter driver, get first unread record matching filter.
+ if (!FilterDriver) {
+ *MonotonicCount = 1; //If not filter driver, get first record.
+
+ } else {
+ //Get the record after the last read record. If not, get the first record.
+ if (Filter->LastRead)
+ Link = Filter->LastRead->Link;
+ else
+ Link = gHead;
+
+ if (!Link)
+ return EFI_NOT_FOUND; //If record doesn't exist, return EFI_NOT_FOUND.
+
+ if ( !(Link = FindNextFilterMatch(Link, Filter)) ) { //Get record matching filter, zero if no match.
+ //No matching record. Set LastRead to tail, and return EFI_NOT_FOUND.
+ Filter->LastRead = gTail;
+ return EFI_NOT_FOUND;
+ }
+
+ //Save pointer to matching record, and last read record.
+ *Record = &Link->RecordHeader;
+ Filter->LastRead = Link;
+
+ //Find the next matching record to return the next Monotonic Count.
+ if ( Link = FindNextFilterMatch(Link->Link, Filter) ) //zero if no match.
+ *MonotonicCount = Link->RecordHeader.LogMonotonicCount;
+ else
+ *MonotonicCount = 0; //If no matching record, set last read to end.
+
+ gCache = Link; //Set cache to find the next record.
+ return EFI_SUCCESS;
+ }
+ }
+
+ //Find a specific MonotonicCount.
+ //If Count is same or after cache, start with cache. Otherwise start at beginning.
+ if (gCache && gCache->RecordHeader.LogMonotonicCount <= *MonotonicCount)
+ Link = gCache;
+ else
+ Link = gHead;
+
+ //Search for Log.
+ for (; Link; Link = Link->Link) {
+ if (Link->RecordHeader.LogMonotonicCount == *MonotonicCount) {
+ *Record = &Link->RecordHeader; //Save pointer to matching record.
+
+ if (Link == gTail) { //If last log, Count = 0.
+ *MonotonicCount = 0;
+
+ if (FilterDriver)
+ Filter->LastRead = Link; //If filter, store last read.
+
+ } else { //If not last log.
+ if (FilterDriver) {
+ Filter->LastRead = Link; //Set last read.
+
+ if ( Link = FindNextFilterMatch(Link->Link, Filter) )
+ *MonotonicCount = Link->RecordHeader.LogMonotonicCount; //Get count of next matching record.
+ else
+ *MonotonicCount = 0; //If no more matching record, set count to 0.
+
+ } else
+ ++*MonotonicCount; //If not filter driver, increase count.
+ }
+
+ gCache = Link; //Set cache.
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND; //Record does't exist.
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: RegisterFilterDriver
+//
+// Description: Register new filter driver.
+//
+// Input:
+// IN EFI_DATA_HUB_PROTOCOL *This
+// IN EFI_EVENT FilterEvent
+// IN EFI_TPL FilterTpl
+// IN UINT64 FilterClass
+// IN EFI_GUID *FilterDataRecordGuid OPTIONAL
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Filter driver registered.
+// * EFI_ALREADY_STARTED - Filter driver was already registered.
+// * EFI_OUT_OF_RESOURCES - Not enough resources to allocate Link.
+//
+// Modified: gFilHead
+//
+// Referrals: AllocatePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Search filters for matching Event. If Event return return EFI_ALREADY_STARTED.
+// 2. Allocate Link for filter. If out of resources, return EFI_OUT_OF_RESOURCES.
+// 3. Fill in filter data.
+// 4. Add link to end.
+// 5. Return EFI_SUCCESS.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS RegisterFilterDriver(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_EVENT FilterEvent,
+ IN EFI_TPL FilterTpl,
+ IN UINT64 FilterClass,
+ IN EFI_GUID *FilterDataRecordGuid OPTIONAL
+)
+{
+ FILTER *Filter;
+ FILTER *Link, *PLink;
+ FILTER **Ptr;
+
+ if (gFilHead) {
+ for (Link = gFilHead; Link; Link = Link->Link) {
+ if (Link->Event == FilterEvent)
+ return EFI_ALREADY_STARTED;
+
+ PLink = Link;
+ }
+
+ Ptr = &PLink->Link;
+
+ } else
+ Ptr = &gFilHead;
+
+ if ( pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(FILTER),
+ &Filter) != EFI_SUCCESS )
+ return EFI_OUT_OF_RESOURCES;
+
+ Filter->Link = 0;
+ Filter->Event = FilterEvent;
+ Filter->Class = FilterClass;
+ Filter->LastRead = NULL;
+
+ if (FilterDataRecordGuid) { //Guid is optional. isGuid, determines if to test Guid.
+ Filter->DataRecordGuid = *FilterDataRecordGuid;
+ Filter->isGuid = TRUE;
+
+ } else
+ Filter->isGuid = FALSE;
+
+ *Ptr = Filter;
+
+ // Signal the Filter driver to get all the previous logged data. Otherwise,
+ // One must wait until the next signal to get the previous logged data.
+ pBS->SignalEvent(FilterEvent);
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: UnregisterFilterDriver
+//
+// Description: Unregister a filter driver.
+//
+// Input:
+// IN EFI_DATA_HUB_PROTOCOL *This
+// IN EFI_EVENT FilterEvent
+//
+// Output:
+// EFI_STATUS
+// * EFI_SUCCESS - Filter driver removed.
+// * EFI_NOT_FOUND - Filter driver not found.
+//
+// Modified: gFilHead
+//
+// Referrals: FreePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. If no filter drivers, return EFI_NOT_FOUND.
+// 2. If filter stored in Filter Driver Head, free filter driver
+// and set Head to next link.
+// 3. Find filter driver.
+// 4. If found, remove link, then free link. Return EFI_SUCCESS.
+// 5. If not found, return EFI_NOT_FOUND.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS UnregisterFilterDriver(
+ IN EFI_DATA_HUB_PROTOCOL *This,
+ IN EFI_EVENT FilterEvent
+)
+{
+ FILTER *Link, *PLink;
+
+ PLink = gFilHead;
+
+ if (!gFilHead)
+ return EFI_NOT_FOUND;
+
+ if (gFilHead->Event == FilterEvent) {
+ gFilHead = gFilHead->Link;
+ pBS->FreePool(PLink);
+ return EFI_SUCCESS;
+ }
+
+ for (Link = gFilHead->Link; Link; Link = Link->Link) {
+ if (Link->Event == FilterEvent) {
+ PLink->Link = Link->Link;
+ pBS->FreePool(Link);
+ return EFI_SUCCESS;
+ }
+
+ PLink = Link;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_DATA_HUB_PROTOCOL gDataHub = {
+ LogData,
+ GetNextDataRecord,
+ RegisterFilterDriver,
+ UnregisterFilterDriver
+};
+
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: InitDataHub
+//
+// Description: Install Data Hub Protocol.
+//
+// Input:
+// IN EFI_HANDLE ImageHandle
+// IN EFI_SYSTEM_TABLE *SystemTable
+//
+// Output: EFI_STATUS
+//
+// Referrals: InstallMultipleProtocolInterfaces
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Install Data Hub Protocol.
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS InitDataHub(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ InitAmiLib(ImageHandle, SystemTable);
+
+ return pBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gDataHubProtocolGuid,
+ &gDataHub,
+ NULL
+ );
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/DebugImageInfo.c b/Core/CORE_DXE/DebugImageInfo.c
new file mode 100644
index 0000000..c1a81a3
--- /dev/null
+++ b/Core/CORE_DXE/DebugImageInfo.c
@@ -0,0 +1,262 @@
+/*++
+
+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:
+
+ DebugImageInfo.c
+
+Abstract:
+
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "DebugImageInfo.h"
+
+
+static EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {
+ 0, // volatile UINT32 UpdateStatus;
+ 0, // UINT32 TableSize;
+ NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
+};
+
+static EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;
+
+
+VOID
+CoreInitializeDebugImageInfoTable (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Creates and initializes the DebugImageInfo Table. Also creates the configuration
+ table and registers it into the system table.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+Notes:
+ This function allocates memory, frees it, and then allocates memory at an
+ address within the initial allocation. Since this function is called early
+ in DXE core initialization (before drivers are dispatched), this should not
+ be a problem.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Mem;
+ UINTN NumberOfPages;
+
+ //
+ // Allocate boot services memory for the structure. It's required to be aligned on
+ // a 4M boundary, so allocate a 4M block (plus what we require), free it up, calculate
+ // a 4M aligned address within the memory we just freed, and then allocate memory at that
+ // address for our initial structure.
+ //
+ NumberOfPages = FOUR_MEG_PAGES + EFI_SIZE_TO_PAGES(sizeof (EFI_SYSTEM_TABLE_POINTER));
+
+ Status = CoreAllocatePages (AllocateAnyPages, EfiBootServicesData, NumberOfPages , &Mem);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ Status = CoreFreePages (Mem, NumberOfPages);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ //
+ // Now get a 4M aligned address within the memory range we were given.
+ // Then allocate memory at that address
+ //
+ Mem = (Mem + FOUR_MEG_MASK) & (~FOUR_MEG_MASK);
+
+ Status = CoreAllocatePages (AllocateAddress, EfiBootServicesData, NumberOfPages - FOUR_MEG_PAGES, &Mem);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ //
+ // We now have a 4M aligned page allocated, so fill in the data structure.
+ // Ideally we would update the CRC now as well, but the service may not yet be available.
+ // See comments in the CoreUpdateDebugTableCrc32() function below for details.
+ //
+ mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(UINTN)Mem;
+ mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE;
+ mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) gST;
+ mDebugTable->Crc32 = 0;
+ Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+CoreUpdateDebugTableCrc32 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Update the CRC32 in the Debug Table.
+ Since the CRC32 service is made available by the Runtime driver, we have to
+ wait for the Runtime Driver to be installed before the CRC32 can be computed.
+ This function is called elsewhere by the core when the runtime architectural
+ protocol is produced.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+{
+ ASSERT(mDebugTable != NULL);
+ mDebugTable->Crc32 = 0;
+ gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32);
+}
+
+VOID
+CoreNewDebugImageInfoEntry (
+ IN UINT32 ImageInfoType,
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
+ the table if it's not large enough to accomidate another entry.
+
+Arguments:
+
+ ImageInfoType - type of debug image information
+ LoadedImage - pointer to the loaded image protocol for the image being loaded
+ ImageHandle - image handle for the image being loaded
+
+Returns:
+ NA
+
+--*/
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ EFI_DEBUG_IMAGE_INFO *NewTable;
+ UINTN Index;
+ UINTN MaxTableIndex;
+ UINTN TableSize;
+
+ //
+ // Set the flag indicating that we're in the process of updating the table.
+ //
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+ MaxTableIndex = mDebugInfoTableHeader.TableSize;
+
+ for (Index = 0; Index < MaxTableIndex; Index++) {
+ if (Table[Index].NormalImage == NULL) {
+ //
+ // We have found a free entry so exit the loop
+ //
+ break;
+ }
+ }
+ if (Index == MaxTableIndex) {
+ //
+ // Table is full, so re-allocate another page for a larger table...
+ //
+ TableSize = MaxTableIndex * EFI_DEBUG_TABLE_ENTRY_SIZE;
+ NewTable = CoreAllocateZeroBootServicesPool (TableSize + EFI_PAGE_SIZE);
+ if (NewTable == NULL) {
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+ return;
+ }
+ //
+ // Copy the old table into the new one
+ //
+ EfiCommonLibCopyMem (NewTable, Table, TableSize);
+ //
+ // Free the old table
+ //
+ CoreFreePool (Table);
+ //
+ // Update the table header
+ //
+ Table = NewTable;
+ mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
+ mDebugInfoTableHeader.TableSize += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+ }
+ //
+ // Allocate data for new entry
+ //
+ Table[Index].NormalImage = CoreAllocateZeroBootServicesPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
+ if (Table[Index].NormalImage != NULL) {
+ //
+ // Update the entry
+ //
+ Table[Index].NormalImage->ImageInfoType = ImageInfoType;
+ Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
+ Table[Index].NormalImage->ImageHandle = ImageHandle;
+ }
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
+
+
+VOID
+CoreRemoveDebugImageInfoEntry (
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Removes and frees an entry from the DebugImageInfo Table.
+
+Arguments:
+
+ ImageHandle - image handle for the image being unloaded
+
+Returns:
+
+ NA
+
+--*/
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ UINTN Index;
+
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+
+ for (Index = 0; Index < mDebugInfoTableHeader.TableSize; Index++) {
+ if (Table[Index].NormalImage != NULL && Table[Index].NormalImage->ImageHandle == ImageHandle) {
+ //
+ // Found a match. Free up the record, then NULL the pointer to indicate the slot
+ // is free.
+ //
+ CoreFreePool (Table[Index].NormalImage);
+ Table[Index].NormalImage = NULL;
+ break;
+ }
+ }
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
+
diff --git a/Core/CORE_DXE/DebugImageInfo.h b/Core/CORE_DXE/DebugImageInfo.h
new file mode 100644
index 0000000..a4e86e7
--- /dev/null
+++ b/Core/CORE_DXE/DebugImageInfo.h
@@ -0,0 +1,129 @@
+/*++
+
+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:
+
+ DebugImageInfo.h
+
+Abstract:
+
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+--*/
+
+#ifndef __DEBUG_IMAGE_INFO_H__
+#define __DEBUG_IMAGE_INFO_H__
+
+#include EFI_PROTOCOL_DEFINITION(LoadedImage)
+#include EFI_GUID_DEFINITION(DebugImageInfoTable)
+
+#define FOUR_MEG_PAGES 0x400
+#define FOUR_MEG_MASK ((FOUR_MEG_PAGES * EFI_PAGE_SIZE) - 1)
+
+#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
+
+VOID
+CoreInitializeDebugImageInfoTable (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Creates and initializes the DebugImageInfo Table. Also creates the configuration
+ table and registers it into the system table.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+Notes:
+ This function allocates memory, frees it, and then allocates memory at an
+ address within the initial allocation. Since this function is called early
+ in DXE core initialization (before drivers are dispatched), this should not
+ be a problem.
+
+--*/
+;
+
+VOID
+CoreUpdateDebugTableCrc32 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Update the CRC32 in the Debug Table.
+ Since the CRC32 service is made available by the Runtime driver, we have to
+ wait for the Runtime Driver to be installed before the CRC32 can be computed.
+ This function is called elsewhere by the core when the runtime architectural
+ protocol is produced.
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+;
+
+VOID
+CoreNewDebugImageInfoEntry (
+ UINT32 ImageInfoType,
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
+ the table if it's not large enough to accomidate another entry.
+
+Arguments:
+
+ ImageInfoType - type of debug image information
+ LoadedImage - pointer to the loaded image protocol for the image being loaded
+ ImageHandle - image handle for the image being loaded
+
+Returns:
+ NA
+
+--*/
+;
+
+VOID
+CoreRemoveDebugImageInfoEntry (
+ EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Removes and frees an entry from the DebugImageInfo Table.
+
+Arguments:
+
+ ImageHandle - image handle for the image being unloaded
+
+Returns:
+
+ NA
+
+--*/
+;
+
+#endif
diff --git a/Core/CORE_DXE/DebugMask.c b/Core/CORE_DXE/DebugMask.c
new file mode 100644
index 0000000..f9b0cf4
--- /dev/null
+++ b/Core/CORE_DXE/DebugMask.c
@@ -0,0 +1,399 @@
+/*++
+
+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:
+
+ DebugMask.c
+
+Abstract:
+
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "DebugMask.h"
+#include EFI_GUID_DEFINITION (GenericVariable)
+
+extern UINTN mErrorLevel;
+static VOID *mVariableReadyNotify;
+
+VOID
+EFIAPI
+UpdateDebugMask (
+ EFI_EVENT Event,
+ VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+GetDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN OUT UINTN *CurrentDebugMask // Ptr to store current debug mask
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Gets the current debug mask for an image, on which this protocol has been installed.
+
+Arguments:
+
+ This - Indicates calling context
+ CurrentDebugMask - Ptr to store current debug mask
+
+Returns:
+ EFI_SUCCESS - Debug mask is retrieved successfully
+ EFI_INVALID_PARAMETER - CurrentDebugMask is NULL.
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ DEBUG_MASK_PRIVATE_DATA *Private;
+ //
+ // Check Parameter
+ //
+ if (CurrentDebugMask == NULL){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get Private Data
+ //
+ Private = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(This);
+ *CurrentDebugMask = Private->ImageDebugMask;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+SetDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN UINTN NewDebugMask // New Debug Mask value to set
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Updates the current debug mask for an image, on which this protocol has been installed.
+
+Arguments:
+
+ This - Calling context
+ NewDebugMask - New Debug Mask value to set
+
+Returns:
+ EFI_SUCCESS - Debug mask is updated with the new value successfully
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ DEBUG_MASK_PRIVATE_DATA *Private;
+ //
+ // Set Private Data
+ //
+ Private = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(This);
+ Private->ImageDebugMask = NewDebugMask;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+SetCoreDebugMask (
+ IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context
+ IN UINTN NewDebugMask // New Debug Mask value to set
+ )
+/*++
+
+Routine Description:
+ DebugMask protocol member function.
+ Updates the current debug mask for core.
+
+Arguments:
+
+ This - Calling context
+ NewDebugMask - New Debug Mask value to set
+
+Returns:
+ EFI_SUCCESS - Debug mask is updated with the new value successfully
+ EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle.
+
+--*/
+{
+ mErrorLevel = NewDebugMask;
+ return SetDebugMask(This, NewDebugMask);
+}
+
+EFI_STATUS
+InstallDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadImageInterface;
+ DEBUG_MASK_PRIVATE_DATA *DebugMaskPrivate;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check Image Handle
+ //
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID*)&LoadImageInterface
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Create Pool for Private Data
+ //
+ DebugMaskPrivate = CoreAllocateZeroBootServicesPool (sizeof (DEBUG_MASK_PRIVATE_DATA));
+
+ if (DebugMaskPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Fill in private data structure
+ //
+ DebugMaskPrivate->Signature = DEBUGMASK_PRIVATE_DATA_SIGNATURE;
+ DebugMaskPrivate->ImageDebugMask = mErrorLevel;
+ DebugMaskPrivate->DebugMaskInterface.Revision = EFI_DEBUG_MASK_REVISION;
+ DebugMaskPrivate->DebugMaskInterface.GetDebugMask = GetDebugMask;
+ DebugMaskPrivate->DebugMaskInterface.SetDebugMask = SetDebugMask;
+ //
+ // Install Debug Mask Protocol in Image Handle
+ //
+ Status = CoreInstallProtocolInterface (
+ &ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(DebugMaskPrivate->DebugMaskInterface)
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+UninstallDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Uninstall debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will uninstall on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_SUCCESS - Debug mask protocol successfully uninstalled
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskInterface;
+ DEBUG_MASK_PRIVATE_DATA *DebugMaskPrivate;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get Protocol from ImageHandle
+ //
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)&DebugMaskInterface
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DebugMaskPrivate = DEBUG_MASK_PRIVATE_DATA_FROM_THIS(DebugMaskInterface);
+ //
+ // Remove Protocol from ImageHandle
+ //
+ Status = CoreUninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)DebugMaskInterface
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Free Private Data Pool
+ //
+ Status = CoreFreePool(DebugMaskPrivate);
+ return Status;
+}
+
+EFI_STATUS
+InstallCoreDebugMaskProtocol(
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on core.
+
+Arguments:
+
+ ImageHandle - Core handle
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+{
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskInterface;
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = InstallDebugMaskProtocol(ImageHandle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Check Image Handle
+ //
+ CoreHandleProtocol (
+ ImageHandle,
+ &gEfiDebugMaskProtocolGuid,
+ (VOID*)&DebugMaskInterface
+ );
+ DebugMaskInterface->SetDebugMask = SetCoreDebugMask;
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ UpdateDebugMask,
+ mVariableReadyNotify,
+ &Event
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = CoreRegisterProtocolNotify (
+ &gEfiVariableArchProtocolGuid,
+ Event,
+ &mVariableReadyNotify
+ );
+ }
+
+ return Status;
+}
+
+VOID
+EFIAPI
+UpdateDebugMask (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Event callback function to update the debug mask when the variable service is ready.
+
+Arguments:
+
+ Event - The Event
+ Context - The event's context
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN NoHandles;
+ EFI_STATUS Status;
+ UINTN DebugMask;
+ UINTN Index;
+ UINTN DataSize;
+ EFI_HANDLE *Buffer;
+ EFI_DEBUG_MASK_PROTOCOL *DebugMaskProtocol;
+
+ DataSize = sizeof(UINTN);
+ Status = gRT->GetVariable(
+ L"EFIDebug",
+ &gEfiGenericVariableGuid,
+ NULL,
+ &DataSize,
+ &DebugMask
+ );
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+
+ Status = CoreLocateHandleBuffer (
+ AllHandles,
+ &gEfiDebugMaskProtocolGuid,
+ NULL,
+ &NoHandles,
+ &Buffer
+ );
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ for (Index = 0; Index < NoHandles; Index ++) {
+ Status = CoreHandleProtocol (
+ Buffer[Index],
+ &gEfiDebugMaskProtocolGuid,
+ &DebugMaskProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ DebugMaskProtocol->SetDebugMask(DebugMaskProtocol, DebugMask);
+ }
+ CoreFreePool(Buffer);
+}
diff --git a/Core/CORE_DXE/DebugMask.h b/Core/CORE_DXE/DebugMask.h
new file mode 100644
index 0000000..18dbef5
--- /dev/null
+++ b/Core/CORE_DXE/DebugMask.h
@@ -0,0 +1,122 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ DebugMask.h
+
+Abstract:
+
+
+--*/
+
+#ifndef __DEBUG_MASK_INFO_H__
+#define __DEBUG_MASK_INFO_H__
+
+#include EFI_PROTOCOL_CONSUMER (DebugMask)
+
+//
+// local type definitions
+//
+#define DEBUGMASK_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('D','M','S','K')
+
+//
+// Private structure used by driver
+//
+typedef struct {
+ UINT32 Signature;
+ UINTN ImageDebugMask;
+ EFI_DEBUG_MASK_PROTOCOL DebugMaskInterface;
+}DEBUG_MASK_PRIVATE_DATA;
+
+#define DEBUG_MASK_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, DEBUG_MASK_PRIVATE_DATA, DebugMaskInterface, DEBUGMASK_PRIVATE_DATA_SIGNATURE)
+
+//
+// Internal DebugMask Procotol Install/Uninstall Function
+//
+EFI_STATUS
+InstallDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+;
+
+//
+// Internal DebugMask Procotol Install/Uninstall Function
+//
+EFI_STATUS
+InstallCoreDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Install debug mask protocol on Dxe Core.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will install on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated
+
+ EFI_SUCCESS - Debug mask protocol successfully installed
+
+--*/
+;
+
+EFI_STATUS
+UninstallDebugMaskProtocol (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Uninstall debug mask protocol on an image handle.
+
+Arguments:
+
+ ImageHandle - Image handle which debug mask protocol will uninstall on
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid image handle
+
+ EFI_SUCCESS - Debug mask protocol successfully uninstalled
+
+--*/
+;
+
+#endif
diff --git a/Core/CORE_DXE/DevicePath.h b/Core/CORE_DXE/DevicePath.h
new file mode 100644
index 0000000..1f0afcc
--- /dev/null
+++ b/Core/CORE_DXE/DevicePath.h
@@ -0,0 +1,470 @@
+/** @file
+ Definition for Device Path Utilities driver
+
+Copyright (c) 2006 - 2010, Intel Corporation. <BR>
+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.
+
+**/
+
+#ifndef _DEVICE_PATH_DRIVER_H_
+#define _DEVICE_PATH_DRIVER_H_
+
+#include <Tiano.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DevicePathFromText.h>
+
+
+#define MAX_CHAR 480
+
+#define IS_COMMA(a) ((a) == L',')
+#define IS_HYPHEN(a) ((a) == L'-')
+#define IS_DOT(a) ((a) == L'.')
+#define IS_LEFT_PARENTH(a) ((a) == L'(')
+#define IS_RIGHT_PARENTH(a) ((a) == L')')
+#define IS_SLASH(a) ((a) == L'/')
+#define IS_NULL(a) ((a) == L'\0')
+
+
+#define SET_DEVICE_PATH_INSTANCE_END_NODE(a) { \
+ (a)->Type = END_DEVICE_PATH_TYPE; \
+ (a)->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; \
+ (a)->Length[0] = sizeof (EFI_DEVICE_PATH_PROTOCOL); \
+ (a)->Length[1] = 0; \
+ }
+
+#define BBS_TYPE_FLOPPY 0x01
+#define BBS_TYPE_HARDDRIVE 0x02
+#define BBS_TYPE_CDROM 0x03
+#define BBS_TYPE_PCMCIA 0x04
+#define BBS_TYPE_USB 0x05
+#define BBS_TYPE_EMBEDDED_NETWORK 0x06
+#define BBS_TYPE_BEV 0x80
+#define BBS_TYPE_UNKNOWN 0xFF
+
+#pragma pack (push, 1)
+
+typedef struct {
+ UINT8 Addr[4];
+} EFI_IPV4_ADDRESS;
+
+typedef struct{
+ UINT8 Addr[16];
+} EFI_IPV6_ADDRESS;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_IPV4_ADDRESS LocalIpAddress;
+ EFI_IPV4_ADDRESS RemoteIpAddress;
+ UINT16 LocalPort;
+ UINT16 RemotePort;
+ UINT16 Protocol;
+ BOOLEAN StaticIpAddress;
+ EFI_IPV4_ADDRESS GatewayIpAddress;
+ EFI_IPV4_ADDRESS SubnetMask;
+} IPV4_DEVICE_PATH;
+
+//Messaging Device Path Type
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_IPV6_ADDRESS LocalIpAddress;
+ EFI_IPV6_ADDRESS RemoteIpAddress;
+ UINT16 LocalPort;
+ UINT16 RemotePort;
+ UINT16 Protocol;
+ UINT8 IpAddressOrigin;
+ UINT8 PrefixLength;
+ EFI_IPV6_ADDRESS GatewayIpAddress;
+} IPV6_DEVICE_PATH;
+
+#pragma pack (pop)
+
+//
+// Private Data structure
+//
+typedef struct {
+ CHAR16 *Str;
+ UINTN Len;
+ UINTN MaxLen;
+} POOL_PRINT;
+
+typedef
+EFI_DEVICE_PATH_PROTOCOL *
+(*DUMP_NODE) (
+ IN CHAR16 *DeviceNodeStr
+ );
+
+typedef
+VOID
+(*DEVICE_PATH_TO_TEXT_FUNC) (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ );
+
+typedef struct {
+ UINT8 Type;
+ UINT8 SubType;
+ DEVICE_PATH_TO_TEXT_FUNC Function;
+} DEVICE_PATH_TO_TEXT_TABLE;
+
+typedef struct {
+ CHAR16 *DevicePathNodeText;
+ DUMP_NODE Function;
+} DEVICE_PATH_FROM_TEXT_TABLE;
+
+typedef struct {
+ BOOLEAN ClassExist;
+ UINT8 Class;
+ BOOLEAN SubClassExist;
+ UINT8 SubClass;
+} USB_CLASS_TEXT;
+
+#define USB_CLASS_AUDIO 1
+#define USB_CLASS_CDCCONTROL 2
+#define USB_CLASS_HID 3
+#define USB_CLASS_IMAGE 6
+#define USB_CLASS_PRINTER 7
+#define USB_CLASS_MASS_STORAGE 8
+#define USB_CLASS_HUB 9
+#define USB_CLASS_CDCDATA 10
+#define USB_CLASS_SMART_CARD 11
+#define USB_CLASS_VIDEO 14
+#define USB_CLASS_DIAGNOSTIC 220
+#define USB_CLASS_WIRELESS 224
+
+#define USB_CLASS_RESERVE 254
+#define USB_SUBCLASS_FW_UPDATE 1
+#define USB_SUBCLASS_IRDA_BRIDGE 2
+#define USB_SUBCLASS_TEST 3
+
+#define RFC_1700_UDP_PROTOCOL 17
+#define RFC_1700_TCP_PROTOCOL 6
+
+#pragma pack(1)
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_GUID Guid;
+ UINT8 VendorDefinedData[1];
+} VENDOR_DEFINED_HARDWARE_DEVICE_PATH;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_GUID Guid;
+ UINT8 VendorDefinedData[1];
+} VENDOR_DEFINED_MESSAGING_DEVICE_PATH;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_GUID Guid;
+ UINT8 VendorDefinedData[1];
+} VENDOR_DEFINED_MEDIA_DEVICE_PATH;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ UINT32 Hid;
+ UINT32 Uid;
+ UINT32 Cid;
+ CHAR8 HidUidCidStr[3];
+} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ UINT16 NetworkProtocol;
+ UINT16 LoginOption;
+ UINT64 Lun;
+ UINT16 TargetPortalGroupTag;
+ CHAR8 TargetName[1];
+} ISCSI_DEVICE_PATH_WITH_NAME;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_GUID Guid;
+ UINT8 VendorDefinedData[1];
+} VENDOR_DEVICE_PATH_WITH_DATA;
+
+#pragma pack()
+
+/**
+ Converts a device node to its string representation.
+
+ @param DeviceNode A Pointer to the device node to be converted.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+ @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
+ is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+ConvertDeviceNodeToText (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ );
+
+/**
+ Converts a device path to its text representation.
+
+ @param DevicePath A Pointer to the device to be converted.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+ @return A pointer to the allocated text representation of the device path or
+ NULL if DeviceNode is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+ConvertDevicePathToText (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ );
+
+/**
+ Convert text to the binary representation of a device node.
+
+ @param TextDeviceNode TextDeviceNode points to the text representation of a device
+ node. Conversion starts with the first character and continues
+ until the first non-device node character.
+
+ @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
+ insufficient memory or text unsupported.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+ConvertTextToDeviceNode (
+ IN CONST CHAR16 *TextDeviceNode
+ );
+
+/**
+ Convert text to the binary representation of a device path.
+
+
+ @param TextDevicePath TextDevicePath points to the text representation of a device
+ path. Conversion starts with the first character and continues
+ until the first non-device node character.
+
+ @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
+ there was insufficient memory.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+ConvertTextToDevicePath (
+ IN CONST CHAR16 *TextDevicePath
+ );
+
+/**
+ Returns the size of a device path in bytes.
+
+ This function returns the size, in bytes, of the device path data structure specified by
+ DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned.
+
+ @param DevicePath A pointer to a device path data structure.
+
+ @return The size of a device path in bytes.
+
+**/
+UINTN
+EFIAPI
+GetDevicePathSizeProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Creates a new device path by appending a second device path to a first device path.
+
+ This function allocates space for a new copy of the device path specified by DevicePath. If
+ DevicePath is NULL, then NULL is returned. If the memory is successfully allocated, then the
+ contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer
+ is returned. Otherwise, NULL is returned.
+
+ @param DevicePath A pointer to a device path data structure.
+
+ @return A pointer to the duplicated device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+DuplicateDevicePathProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Creates a new device path by appending a second device path to a first device path.
+
+ This function creates a new device path by appending a copy of SecondDevicePath to a copy of
+ FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from
+ SecondDevicePath is retained. The newly created device path is returned.
+ If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned.
+ If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned.
+ If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is
+ returned.
+ If there is not enough memory for the newly allocated buffer, then NULL is returned.
+ The memory for the new device path is allocated from EFI boot services memory. It is the
+ responsibility of the caller to free the memory allocated.
+
+ @param FirstDevicePath A pointer to a device path data structure.
+ @param SecondDevicePath A pointer to a device path data structure.
+
+ @return A pointer to the new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+AppendDevicePathProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
+ );
+
+/**
+ Creates a new path by appending the device node to the device path.
+
+ This function creates a new device path by appending a copy of the device node specified by
+ DevicePathNode to a copy of the device path specified by DevicePath in an allocated buffer.
+ The end-of-device-path device node is moved after the end of the appended device node.
+ If DevicePathNode is NULL then a copy of DevicePath is returned.
+ If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device path device
+ node is returned.
+ If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path device node
+ is returned.
+ If there is not enough memory to allocate space for the new device path, then NULL is returned.
+ The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
+ free the memory allocated.
+
+ @param DevicePath A pointer to a device path data structure.
+ @param DevicePathNode A pointer to a single device path node.
+
+ @return A pointer to the new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+AppendDeviceNodeProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
+ );
+
+/**
+ Creates a new device path by appending the specified device path instance to the specified device
+ path.
+
+ This function creates a new device path by appending a copy of the device path instance specified
+ by DevicePathInstance to a copy of the device path specified by DevicePath in a allocated buffer.
+ The end-of-device-path device node is moved after the end of the appended device path instance
+ and a new end-of-device-path-instance node is inserted between.
+ If DevicePath is NULL, then a copy if DevicePathInstance is returned.
+ If DevicePathInstance is NULL, then NULL is returned.
+ If there is not enough memory to allocate space for the new device path, then NULL is returned.
+ The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
+ free the memory allocated.
+
+ @param DevicePath A pointer to a device path data structure.
+ @param DevicePathInstance A pointer to a device path instance.
+
+ @return A pointer to the new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+AppendDevicePathInstanceProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
+ );
+
+/**
+ Creates a copy of the current device path instance and returns a pointer to the next device path
+ instance.
+
+ This function creates a copy of the current device path instance. It also updates DevicePath to
+ point to the next device path instance in the device path (or NULL if no more) and updates Size
+ to hold the size of the device path instance copy.
+ If DevicePath is NULL, then NULL is returned.
+ If there is not enough memory to allocate space for the new device path, then NULL is returned.
+ The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
+ free the memory allocated.
+ If Size is NULL, then ASSERT().
+
+ @param DevicePath On input, this holds the pointer to the current device path
+ instance. On output, this holds the pointer to the next device
+ path instance or NULL if there are no more device path
+ instances in the device path pointer to a device path data
+ structure.
+ @param Size On output, this holds the size of the device path instance, in
+ bytes or zero, if DevicePath is NULL.
+
+ @return A pointer to the current device path instance.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+GetNextDevicePathInstanceProtocolInterface (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT UINTN *Size
+ );
+
+/**
+ Determines if a device path is single or multi-instance.
+
+ This function returns TRUE if the device path specified by DevicePath is multi-instance.
+ Otherwise, FALSE is returned. If DevicePath is NULL, then FALSE is returned.
+
+ @param DevicePath A pointer to a device path data structure.
+
+ @retval TRUE DevicePath is multi-instance.
+ @retval FALSE DevicePath is not multi-instance or DevicePath is NULL.
+
+**/
+BOOLEAN
+EFIAPI
+IsDevicePathMultiInstanceProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Creates a copy of the current device path instance and returns a pointer to the next device path
+ instance.
+
+ This function creates a new device node in a newly allocated buffer of size NodeLength and
+ initializes the device path node header with NodeType and NodeSubType. The new device path node
+ is returned.
+ If NodeLength is smaller than a device path header, then NULL is returned.
+ If there is not enough memory to allocate space for the new device path, then NULL is returned.
+ The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
+ free the memory allocated.
+
+ @param NodeType The device node type for the new device node.
+ @param NodeSubType The device node sub-type for the new device node.
+ @param NodeLength The length of the new device node.
+
+ @return The new device path.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+CreateDeviceNodeProtocolInterface (
+ IN UINT8 NodeType,
+ IN UINT8 NodeSubType,
+ IN UINT16 NodeLength
+ );
+
+#endif
diff --git a/Core/CORE_DXE/DevicePathFromText.c b/Core/CORE_DXE/DevicePathFromText.c
new file mode 100644
index 0000000..5f4e4d1
--- /dev/null
+++ b/Core/CORE_DXE/DevicePathFromText.c
@@ -0,0 +1,3310 @@
+/** @file
+ DevicePathFromText protocol as defined in the UEFI 2.0 specification.
+
+Copyright (c) 2006 - 2010, Intel Corporation. <BR>
+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.
+
+**/
+
+
+#include "DevicePath.h"
+#include "EdkIICommon.h"
+
+
+UINT64
+LShiftU64 (
+ IN UINT64 Operand,
+ IN UINTN Count
+ );
+
+VOID*
+DPCreateNode (
+ IN UINT8 Type,
+ IN UINT8 SubType,
+ IN UINT16 Length
+ );
+
+VOID*
+DPAddNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *pDp1,
+ IN EFI_DEVICE_PATH_PROTOCOL *pDp2
+ );
+
+EFI_STATUS
+HexStringToBuf (
+ IN OUT UINT8 *Buf,
+ IN OUT UINTN *Len,
+ IN CHAR16 *Str,
+ OUT UINTN *ConvertedStrLen OPTIONAL
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreateDeviceNode (
+ IN UINT8 Type,
+ IN UINT8 SubType,
+ IN UINT16 Length
+ )
+{
+ return (EFI_DEVICE_PATH_PROTOCOL *) DPCreateNode(Type, SubType, Length);
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDeviceNodeProtocolInterface (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
+ )
+{
+ return (EFI_DEVICE_PATH_PROTOCOL *) DPAddNode (
+ (EFI_DEVICE_PATH_PROTOCOL *)DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)DevicePathNode );
+}
+
+
+/**
+
+ Duplicates a string.
+
+ @param Src Source string.
+
+ @return The duplicated string.
+
+**/
+CHAR16 *
+StrDuplicate (
+ IN CONST CHAR16 *Src
+ )
+{
+ return AllocateCopyPool (StrSize ((CHAR16 *)Src), Src);
+}
+
+/**
+
+ Get parameter in a pair of parentheses follow the given node name.
+ For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1".
+
+ @param Str Device Path Text.
+ @param NodeName Name of the node.
+
+ @return Parameter text for the node.
+
+**/
+CHAR16 *
+GetParamByNodeName (
+ IN CHAR16 *Str,
+ IN CHAR16 *NodeName
+ )
+{
+ CHAR16 *ParamStr;
+ CHAR16 *StrPointer;
+ UINTN NodeNameLength;
+ UINTN ParameterLength;
+
+ //
+ // Check whether the node name matchs
+ //
+ NodeNameLength = StrLen (NodeName);
+ if (CompareMem (Str, NodeName, NodeNameLength * sizeof (CHAR16)) != 0) {
+ return NULL;
+ }
+
+ ParamStr = Str + NodeNameLength;
+ if (!IS_LEFT_PARENTH (*ParamStr)) {
+ return NULL;
+ }
+
+ //
+ // Skip the found '(' and find first occurrence of ')'
+ //
+ ParamStr++;
+ ParameterLength = 0;
+ StrPointer = ParamStr;
+ while (!IS_NULL (*StrPointer)) {
+ if (IS_RIGHT_PARENTH (*StrPointer)) {
+ break;
+ }
+ StrPointer++;
+ ParameterLength++;
+ }
+ if (IS_NULL (*StrPointer)) {
+ //
+ // ')' not found
+ //
+ return NULL;
+ }
+
+ ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr);
+ if (ParamStr == NULL) {
+ return NULL;
+ }
+ //
+ // Terminate the parameter string
+ //
+ ParamStr[ParameterLength] = L'\0';
+
+ return ParamStr;
+}
+
+/**
+ Gets current sub-string from a string list, before return
+ the list header is moved to next sub-string. The sub-string is separated
+ by the specified character. For example, the separator is ',', the string
+ list is "2,0,3", it returns "2", the remain list move to "0,3"
+
+ @param List A string list separated by the specified separator
+ @param Separator The separator character
+
+ @return A pointer to the current sub-string
+
+**/
+CHAR16 *
+SplitStr (
+ IN OUT CHAR16 **List,
+ IN CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ReturnStr;
+
+ Str = *List;
+ ReturnStr = Str;
+
+ if (IS_NULL (*Str)) {
+ return ReturnStr;
+ }
+
+ //
+ // Find first occurrence of the separator
+ //
+ while (!IS_NULL (*Str)) {
+ if (*Str == Separator) {
+ break;
+ }
+ Str++;
+ }
+
+ if (*Str == Separator) {
+ //
+ // Find a sub-string, terminate it
+ //
+ *Str = L'\0';
+ Str++;
+ }
+
+ //
+ // Move to next sub-string
+ //
+ *List = Str;
+
+ return ReturnStr;
+}
+
+/**
+ Gets the next parameter string from the list.
+
+ @param List A string list separated by the specified separator
+
+ @return A pointer to the current sub-string
+
+**/
+CHAR16 *
+GetNextParamStr (
+ IN OUT CHAR16 **List
+ )
+{
+ //
+ // The separator is comma
+ //
+ return SplitStr (List, L',');
+}
+
+/**
+ Get one device node from entire device path text.
+
+ @param DevicePath On input, the current Device Path node; on output, the next device path node
+ @param IsInstanceEnd This node is the end of a device path instance
+
+ @return A device node text or NULL if no more device node available
+
+**/
+CHAR16 *
+GetNextDeviceNodeStr (
+ IN OUT CHAR16 **DevicePath,
+ OUT BOOLEAN *IsInstanceEnd
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ReturnStr;
+ UINTN ParenthesesStack;
+
+ Str = *DevicePath;
+ if (IS_NULL (*Str)) {
+ return NULL;
+ }
+
+ //
+ // Skip the leading '/', '(', ')' and ','
+ //
+ while (!IS_NULL (*Str)) {
+ if (!IS_SLASH (*Str) &&
+ !IS_COMMA (*Str) &&
+ !IS_LEFT_PARENTH (*Str) &&
+ !IS_RIGHT_PARENTH (*Str)) {
+ break;
+ }
+ Str++;
+ }
+
+ ReturnStr = Str;
+
+ //
+ // Scan for the separator of this device node, '/' or ','
+ //
+ ParenthesesStack = 0;
+ while (!IS_NULL (*Str)) {
+ if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) {
+ break;
+ }
+
+ if (IS_LEFT_PARENTH (*Str)) {
+ ParenthesesStack++;
+ } else if (IS_RIGHT_PARENTH (*Str)) {
+ ParenthesesStack--;
+ }
+
+ Str++;
+ }
+
+ if (ParenthesesStack != 0) {
+ //
+ // The '(' doesn't pair with ')', invalid device path text
+ //
+ return NULL;
+ }
+
+ if (IS_COMMA (*Str)) {
+ *IsInstanceEnd = TRUE;
+ *Str = L'\0';
+ Str++;
+ } else {
+ *IsInstanceEnd = FALSE;
+ if (!IS_NULL (*Str)) {
+ *Str = L'\0';
+ Str++;
+ }
+ }
+
+ *DevicePath = Str;
+
+ return ReturnStr;
+}
+
+
+/**
+ Skip the leading white space and '0x' or '0X' of a integer string
+
+ @param Str The integer string
+ @param IsHex TRUE: Hex string, FALSE: Decimal string
+
+ @return The trimmed Hex string.
+
+**/
+CHAR16 *
+TrimHexStr (
+ IN CHAR16 *Str,
+ OUT BOOLEAN *IsHex
+ )
+{
+ *IsHex = FALSE;
+
+ //
+ // skip preceeding white space
+ //
+ while ((*Str != 0) && *Str == ' ') {
+ Str += 1;
+ }
+ //
+ // skip preceeding zeros
+ //
+ while ((*Str != 0) && *Str == '0') {
+ Str += 1;
+ }
+ //
+ // skip preceeding character 'x' or 'X'
+ //
+ if ((*Str != 0) && (*Str == 'x' || *Str == 'X')) {
+ Str += 1;
+ *IsHex = TRUE;
+ }
+
+ return Str;
+}
+
+/**
+
+ Convert hex string to uint.
+
+ @param Str The hex string
+
+ @return A UINTN value represented by Str
+
+**/
+UINTN
+Xtoi (
+ IN CHAR16 *Str
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN Result = 0;
+ UINTN Length = sizeof(UINTN);
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*Str == L' ') || (*Str == L'\t')) {
+ Str++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*Str == L'0') {
+ Str++;
+ }
+
+ if ((*Str == L'X') || (*Str == L'x')) {
+ if (*(Str - 1) != L'0') {
+ return 0;
+ }
+ //
+ // Skip the 'X'
+ //
+ Str++;
+ }
+
+ Buffer = (UINT8 *)&Result;
+ Status = HexStringToBuf(Buffer, &Length, Str, NULL);
+ if(EFI_ERROR(Status))
+ return ~0;
+
+ return Result;
+}
+
+/**
+
+ Convert hex string to 64 bit data.
+
+ @param Str The hex string
+ @param Data A pointer to the UINT64 value represented by Str
+
+**/
+VOID
+Xtoi64 (
+ IN CHAR16 *Str,
+ OUT UINT64 *Data
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINT64 Result = 0;
+ UINTN Length = 8;
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*Str == L' ') || (*Str == L'\t')) {
+ Str++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*Str == L'0') {
+ Str++;
+ }
+
+ if ((*Str == L'X') || (*Str == L'x')) {
+ if (*(Str - 1) != L'0') {
+ *Data = 0;
+ return;
+ }
+ //
+ // Skip the 'X'
+ //
+ Str++;
+ }
+
+ Buffer = (UINT8 *)&Result;
+ Status = HexStringToBuf(Buffer, &Length, Str, NULL);
+
+ *Data = (EFI_ERROR(Status)) ? ~0 : Result;
+}
+
+/**
+
+ Convert decimal string to uint.
+
+ @param Str The decimal string
+
+ @return A UINTN value represented by Str
+
+**/
+UINTN
+Dtoi (
+ IN CHAR16 *Str
+ )
+{
+ UINTN Rvalue;
+ CHAR16 Char;
+ UINTN High;
+ UINTN Low;
+
+ ASSERT (Str != NULL);
+
+ High = (UINTN) -1 / 10;
+ Low = (UINTN) -1 % 10;
+ //
+ // skip preceeding white space
+ //
+ while ((*Str != 0) && *Str == ' ') {
+ Str += 1;
+ }
+ //
+ // convert digits
+ //
+ Rvalue = 0;
+ Char = *(Str++);
+ while (Char != 0) {
+ if (Char >= '0' && Char <= '9') {
+ if ((Rvalue > High || Rvalue == High) && (Char - '0' > (INTN) Low)) {
+ return (UINTN) -1;
+ }
+
+ Rvalue = (Rvalue * 10) + Char - '0';
+ } else {
+ break;
+ }
+
+ Char = *(Str++);
+ }
+
+ return Rvalue;
+}
+
+/**
+
+ Convert decimal string to uint.
+
+ @param Str The decimal string
+ @param Data A pointer to the UINT64 value represented by Str
+
+**/
+VOID
+Dtoi64 (
+ IN CHAR16 *Str,
+ OUT UINT64 *Data
+ )
+{
+ UINT64 Rvalue;
+ CHAR16 Char;
+ UINT64 High;
+ UINT64 Low;
+
+ ASSERT (Str != NULL);
+ ASSERT (Data != NULL);
+
+ //
+ // skip preceeding white space
+ //
+ while ((*Str != 0) && *Str == ' ') {
+ Str += 1;
+ }
+ //
+ // convert digits
+ //
+ Rvalue = 0;
+ Char = *(Str++);
+ while (Char != 0) {
+ if (Char >= '0' && Char <= '9') {
+ High = LShiftU64 (Rvalue, 3);
+ Low = LShiftU64 (Rvalue, 1);
+ Rvalue = High + Low + Char - '0';
+ } else {
+ break;
+ }
+
+ Char = *(Str++);
+ }
+
+ *Data = Rvalue;
+}
+
+/**
+
+ Convert integer string to uint.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+
+ @return A UINTN value represented by Str
+
+**/
+UINTN
+Strtoi (
+ IN CHAR16 *Str
+ )
+{
+ BOOLEAN IsHex;
+
+ Str = TrimHexStr (Str, &IsHex);
+
+ if (IsHex) {
+ return Xtoi (Str);
+ } else {
+ return Dtoi (Str);
+ }
+}
+
+/**
+
+ Convert integer string to 64 bit data.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+ @param Data A pointer to the UINT64 value represented by Str
+
+**/
+VOID
+Strtoi64 (
+ IN CHAR16 *Str,
+ OUT UINT64 *Data
+ )
+{
+ BOOLEAN IsHex;
+
+ Str = TrimHexStr (Str, &IsHex);
+
+ if (IsHex) {
+ Xtoi64 (Str, Data);
+ } else {
+ Dtoi64 (Str, Data);
+ }
+}
+
+/**
+ Converts a list of string to a specified buffer.
+
+ @param Buf The output buffer that contains the string.
+ @param BufferLength The length of the buffer
+ @param Str The input string that contains the hex number
+
+ @retval EFI_SUCCESS The string was successfully converted to the buffer.
+
+**/
+EFI_STATUS
+StrToBuf (
+ OUT UINT8 *Buf,
+ IN UINTN BufferLength,
+ IN CHAR16 *Str
+ )
+{
+ UINTN Index;
+ UINTN StrLength;
+ UINT8 Digit;
+ UINT8 Byte;
+
+ Digit = 0;
+
+ //
+ // Two hex char make up one byte
+ //
+ StrLength = BufferLength * sizeof (CHAR16);
+
+ for(Index = 0; Index < StrLength; Index++, Str++) {
+
+ if ((*Str >= L'a') && (*Str <= L'f')) {
+ Digit = (UINT8) (*Str - L'a' + 0x0A);
+ } else if ((*Str >= L'A') && (*Str <= L'F')) {
+ Digit = (UINT8) (*Str - L'A' + 0x0A);
+ } else if ((*Str >= L'0') && (*Str <= L'9')) {
+ Digit = (UINT8) (*Str - L'0');
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For odd characters, write the upper nibble for each buffer byte,
+ // and for even characters, the lower nibble.
+ //
+ if ((Index & 1) == 0) {
+ Byte = (UINT8) (Digit << 4);
+ } else {
+ Byte = Buf[Index / 2];
+ Byte &= 0xF0;
+ Byte = (UINT8) (Byte | Digit);
+ }
+
+ Buf[Index / 2] = Byte;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts a string to GUID value.
+ Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+
+ @param Str The registry format GUID string that contains the GUID value.
+ @param Guid A pointer to the converted GUID value.
+
+ @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.
+ @retval EFI_UNSUPPORTED The input string is not in registry format.
+ @return others Some error occurred when converting part of GUID value.
+
+**/
+EFI_STATUS
+StrToGuid (
+ IN CHAR16 *Str,
+ OUT EFI_GUID *Guid
+ )
+{
+ //
+ // Get the first UINT32 data
+ //
+ Guid->Data1 = (UINT32) Xtoi (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the second UINT16 data
+ //
+ Guid->Data2 = (UINT16) Xtoi (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the third UINT16 data
+ //
+ Guid->Data3 = (UINT16) Xtoi (Str);
+ while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
+ Str ++;
+ }
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the following 8 bytes data
+ //
+ StrToBuf (&Guid->Data4[0], 2, Str);
+ //
+ // Skip 2 byte hex chars
+ //
+ Str += 2 * 2;
+
+ if (IS_HYPHEN (*Str)) {
+ Str++;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ StrToBuf (&Guid->Data4[2], 6, Str);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Converts a string to IPv4 address
+
+ @param Str A string representation of IPv4 address.
+ @param IPv4Addr A pointer to the converted IPv4 address.
+
+**/
+VOID
+StrToIPv4Addr (
+ IN OUT CHAR16 **Str,
+ OUT EFI_IPV4_ADDRESS *IPv4Addr
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < 4; Index++) {
+ IPv4Addr->Addr[Index] = (UINT8) Dtoi (SplitStr (Str, L'.'));
+ }
+}
+
+/**
+ Converts a string to IPv4 address
+
+ @param Str A string representation of IPv6 address.
+ @param IPv6Addr A pointer to the converted IPv6 address.
+
+**/
+VOID
+StrToIPv6Addr (
+ IN OUT CHAR16 **Str,
+ OUT EFI_IPV6_ADDRESS *IPv6Addr
+ )
+{
+ UINTN Index;
+ UINT16 Data;
+
+ for (Index = 0; Index < 8; Index++) {
+ Data = (UINT16) Xtoi (SplitStr (Str, L':'));
+ IPv6Addr->Addr[Index * 2] = (UINT8) (Data >> 8);
+ IPv6Addr->Addr[Index * 2 + 1] = (UINT8) (Data & 0xff);
+ }
+}
+
+/**
+ Converts a Unicode string to ASCII string.
+
+ @param Str The equivalent Unicode string
+ @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
+ to the next ASCII string next to it
+
+**/
+VOID
+StrToAscii (
+ IN CHAR16 *Str,
+ IN OUT CHAR8 **AsciiStr
+ )
+{
+ CHAR8 *Dest;
+
+ Dest = *AsciiStr;
+ while (!IS_NULL (*Str)) {
+ *(Dest++) = (CHAR8) *(Str++);
+ }
+ *Dest = 0;
+
+ //
+ // Return the string next to it
+ //
+ *AsciiStr = Dest + 1;
+}
+
+/**
+ Swaps the byte order in given input
+
+ @param Input Byte order to swap
+
+ @return UINT64 value with swapped bytes
+
+**/
+UINT64
+SwapBytes64 (
+ IN UINT64 Input
+ )
+{
+ UINT64 Output = 0;
+ UINT8 *Inp;
+ UINT8 *Outp;
+
+ Inp = (UINT8 *) &Input;
+ Outp = (UINT8 *) &Output;
+
+ Outp[0] = Inp[7];
+ Outp[1] = Inp[6];
+ Outp[2] = Inp[5];
+ Outp[3] = Inp[4];
+ Outp[4] = Inp[3];
+ Outp[5] = Inp[2];
+ Outp[6] = Inp[1];
+ Outp[7] = Inp[0];
+
+ return Output;
+}
+
+/**
+ Converts a text device path node to Hardware PCI device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to Hardware PCI device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPci (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *FunctionStr;
+ CHAR16 *DeviceStr;
+ PCI_DEVICE_PATH *Pci;
+
+ DeviceStr = GetNextParamStr (&TextDeviceNode);
+ FunctionStr = GetNextParamStr (&TextDeviceNode);
+ Pci = (PCI_DEVICE_PATH *) CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ sizeof (PCI_DEVICE_PATH)
+ );
+
+ Pci->Function = (UINT8) Strtoi (FunctionStr);
+ Pci->Device = (UINT8) Strtoi (DeviceStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Pci;
+}
+
+/**
+ Converts a text device path node to Hardware PC card device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to Hardware PC card device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcCard (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *FunctionNumberStr;
+ PCCARD_DEVICE_PATH *Pccard;
+
+ FunctionNumberStr = GetNextParamStr (&TextDeviceNode);
+ Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_PCCARD_DP,
+ sizeof (PCCARD_DEVICE_PATH)
+ );
+
+ Pccard->Function = (UINT8) Strtoi (FunctionNumberStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Pccard;
+}
+
+/**
+ Converts a text device path node to Hardware memory map device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to Hardware memory map device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMemoryMapped (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *MemoryTypeStr;
+ CHAR16 *StartingAddressStr;
+ CHAR16 *EndingAddressStr;
+ MEMMAP_DEVICE_PATH *MemMap;
+
+ MemoryTypeStr = GetNextParamStr (&TextDeviceNode);
+ StartingAddressStr = GetNextParamStr (&TextDeviceNode);
+ EndingAddressStr = GetNextParamStr (&TextDeviceNode);
+ MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ sizeof (MEMMAP_DEVICE_PATH)
+ );
+
+ MemMap->MemoryType = (UINT32) Strtoi (MemoryTypeStr);
+ Strtoi64 (StartingAddressStr, &MemMap->StartingAddress);
+ Strtoi64 (EndingAddressStr, &MemMap->EndingAddress);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) MemMap;
+}
+
+/**
+ Converts a text device path node to Vendor device path structure based on the input Type
+ and SubType.
+
+ @param TextDeviceNode The input Text device path node.
+ @param Type The type of device path node.
+ @param SubType The subtype of device path node.
+
+ @return A pointer to the newly-created Vendor device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextVendor (
+ IN CHAR16 *TextDeviceNode,
+ IN UINT8 Type,
+ IN UINT8 SubType
+ )
+{
+ CHAR16 *GuidStr;
+ CHAR16 *DataStr;
+ UINTN Length;
+ VENDOR_DEVICE_PATH *Vendor;
+
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+
+ DataStr = GetNextParamStr (&TextDeviceNode);
+ Length = StrLen (DataStr);
+ //
+ // Two hex characters make up 1 buffer byte
+ //
+ Length = (Length + 1) / 2;
+
+ Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+ Type,
+ SubType,
+ (UINT16) (sizeof (VENDOR_DEVICE_PATH) + Length)
+ );
+
+ StrToGuid (GuidStr, &Vendor->Guid);
+ StrToBuf (((UINT8 *) Vendor) + sizeof (VENDOR_DEVICE_PATH), Length, DataStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+ Converts a text device path node to Vendor Hardware device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor Hardware device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenHw (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextVendor (
+ TextDeviceNode,
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP
+ );
+}
+
+/**
+ Converts a text device path node to Hardware Controller device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Hardware Controller device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCtrl (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *ControllerStr;
+ CONTROLLER_DEVICE_PATH *Controller;
+
+ ControllerStr = GetNextParamStr (&TextDeviceNode);
+ Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode (
+ HARDWARE_DEVICE_PATH,
+ HW_CONTROLLER_DP,
+ sizeof (CONTROLLER_DEVICE_PATH)
+ );
+ Controller->Controller = (UINT32) Strtoi (ControllerStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Controller;
+}
+
+/**
+ Converts a string to EisaId.
+
+ @param Text The input string.
+ @param EisaId A pointer to the output EisaId.
+
+**/
+VOID
+EisaIdFromText (
+ IN CHAR16 *Text,
+ OUT UINT32 *EisaId
+ )
+{
+ UINTN PnpId;
+
+ PnpId = Xtoi (Text + 3);
+ *EisaId = (((Text[0] - '@') & 0x1f) << 10) +
+ (((Text[1] - '@') & 0x1f) << 5) +
+ ((Text[2] - '@') & 0x1f) +
+ (UINT32) (PnpId << 16);
+}
+
+/**
+ Converts a text device path node to ACPI HID device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created ACPI HID device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpi (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *HIDStr;
+ CHAR16 *UIDStr;
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ HIDStr = GetNextParamStr (&TextDeviceNode);
+ UIDStr = GetNextParamStr (&TextDeviceNode);
+ Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ sizeof (ACPI_HID_DEVICE_PATH)
+ );
+
+ EisaIdFromText (HIDStr, &Acpi->HID);
+ Acpi->UID = (UINT32) Strtoi (UIDStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
+}
+
+/**
+ Converts a text device path node to ACPI HID device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+ @param PnPId The input plug and play identification.
+
+ @return A pointer to the newly-created ACPI HID device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextAcpi (
+ IN CHAR16 *TextDeviceNode,
+ IN UINT32 PnPId
+ )
+{
+ CHAR16 *UIDStr;
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ UIDStr = GetNextParamStr (&TextDeviceNode);
+ Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ sizeof (ACPI_HID_DEVICE_PATH)
+ );
+
+ Acpi->HID = EFI_PNP_ID (PnPId);
+ Acpi->UID = (UINT32) Strtoi (UIDStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
+}
+
+/**
+ Converts a text device path node to PCI root device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created PCI root device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPciRoot (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0a03);
+}
+
+/**
+ Converts a text device path node to PCIE root device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created PCIE root device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextPcieRoot (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0a08);
+}
+
+/**
+ Converts a text device path node to Floppy device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Floppy device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFloppy (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0604);
+}
+
+/**
+ Converts a text device path node to Keyboard device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Keyboard device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextKeyboard (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0301);
+}
+
+/**
+ Converts a text device path node to Serial device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Serial device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSerial (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0501);
+}
+
+/**
+ Converts a text device path node to Parallel Port device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Parallel Port device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextParallelPort (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextAcpi (TextDeviceNode, 0x0401);
+}
+
+/**
+ Converts a text device path node to ACPI extension device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created ACPI extension device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiEx (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *HIDStr;
+ CHAR16 *CIDStr;
+ CHAR16 *UIDStr;
+ CHAR16 *HIDSTRStr;
+ CHAR16 *CIDSTRStr;
+ CHAR16 *UIDSTRStr;
+ CHAR8 *AsciiStr;
+ UINT16 Length;
+ ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
+
+ HIDStr = GetNextParamStr (&TextDeviceNode);
+ CIDStr = GetNextParamStr (&TextDeviceNode);
+ UIDStr = GetNextParamStr (&TextDeviceNode);
+ HIDSTRStr = GetNextParamStr (&TextDeviceNode);
+ CIDSTRStr = GetNextParamStr (&TextDeviceNode);
+ UIDSTRStr = GetNextParamStr (&TextDeviceNode);
+
+ Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1);
+ Length = (UINT16) (Length + StrLen (UIDSTRStr) + 1);
+ Length = (UINT16) (Length + StrLen (CIDSTRStr) + 1);
+ AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
+ ACPI_DEVICE_PATH,
+ ACPI_EXTENDED_DP,
+ Length
+ );
+
+ EisaIdFromText (HIDStr, &AcpiEx->HID);
+ EisaIdFromText (CIDStr, &AcpiEx->CID);
+ AcpiEx->UID = (UINT32) Strtoi (UIDStr);
+
+ AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+ StrToAscii (HIDSTRStr, &AsciiStr);
+ StrToAscii (UIDSTRStr, &AsciiStr);
+ StrToAscii (CIDSTRStr, &AsciiStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
+}
+
+/**
+ Converts a text device path node to ACPI extension device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created ACPI extension device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiExp (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *HIDStr;
+ CHAR16 *CIDStr;
+ CHAR16 *UIDSTRStr;
+ CHAR8 *AsciiStr;
+ UINT16 Length;
+ ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
+
+ HIDStr = GetNextParamStr (&TextDeviceNode);
+ CIDStr = GetNextParamStr (&TextDeviceNode);
+ UIDSTRStr = GetNextParamStr (&TextDeviceNode);
+ Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3);
+ AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
+ ACPI_DEVICE_PATH,
+ ACPI_EXTENDED_DP,
+ Length
+ );
+
+ EisaIdFromText (HIDStr, &AcpiEx->HID);
+ EisaIdFromText (CIDStr, &AcpiEx->CID);
+ AcpiEx->UID = 0;
+
+ AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+ //
+ // HID string is NULL
+ //
+ *AsciiStr = '\0';
+ //
+ // Convert UID string
+ //
+ AsciiStr++;
+ StrToAscii (UIDSTRStr, &AsciiStr);
+ //
+ // CID string is NULL
+ //
+ *AsciiStr = '\0';
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
+}
+
+/**
+ Converts a text device path node to ACPI _ADR device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created ACPI _ADR device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAcpiAdr (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *DisplayDeviceStr;
+ ACPI_ADR_DEVICE_PATH *AcpiAdr;
+ UINTN Index;
+ UINTN Length;
+
+ AcpiAdr = (ACPI_ADR_DEVICE_PATH *) CreateDeviceNode (
+ ACPI_DEVICE_PATH,
+ ACPI_ADR_DP,
+ (UINT16) sizeof (ACPI_ADR_DEVICE_PATH)
+ );
+ ASSERT (AcpiAdr != NULL);
+
+ for (Index = 0; ; Index++) {
+ DisplayDeviceStr = GetNextParamStr (&TextDeviceNode);
+ if (IS_NULL (*DisplayDeviceStr)) {
+ break;
+ }
+ if (Index > 0) {
+ Length = DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)AcpiAdr);
+ AcpiAdr = ReallocatePool (
+ Length,
+ Length + sizeof (UINT32),
+ AcpiAdr
+ );
+ ASSERT (AcpiAdr != NULL);
+ SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)AcpiAdr, Length + sizeof (UINT32));
+ }
+
+ (&AcpiAdr->ADR)[Index] = (UINT32) Strtoi (DisplayDeviceStr);
+ }
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr;
+}
+
+/**
+ Converts a text device path node to Parallel Port device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Parallel Port device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextAta (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *PrimarySecondaryStr;
+ CHAR16 *SlaveMasterStr;
+ CHAR16 *LunStr;
+ ATAPI_DEVICE_PATH *Atapi;
+
+ Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_ATAPI_DP,
+ sizeof (ATAPI_DEVICE_PATH)
+ );
+
+ PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode);
+ SlaveMasterStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+
+ Atapi->PrimarySecondary = (UINT8) ((StrCmp (PrimarySecondaryStr, L"Primary") == 0) ? 0 : 1);
+ Atapi->SlaveMaster = (UINT8) ((StrCmp (SlaveMasterStr, L"Master") == 0) ? 0 : 1);
+ Atapi->Lun = (UINT16) Strtoi (LunStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Atapi;
+}
+
+/**
+ Converts a text device path node to SCSI device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created SCSI device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextScsi (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *PunStr;
+ CHAR16 *LunStr;
+ SCSI_DEVICE_PATH *Scsi;
+
+ PunStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_SCSI_DP,
+ sizeof (SCSI_DEVICE_PATH)
+ );
+
+ Scsi->Pun = (UINT16) Strtoi (PunStr);
+ Scsi->Lun = (UINT16) Strtoi (LunStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Scsi;
+}
+
+/**
+ Converts a text device path node to Fibre device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Fibre device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibre (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *WWNStr;
+ CHAR16 *LunStr;
+ FIBRECHANNEL_DEVICE_PATH *Fibre;
+
+ WWNStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_FIBRECHANNEL_DP,
+ sizeof (FIBRECHANNEL_DEVICE_PATH)
+ );
+
+ Fibre->Reserved = 0;
+ Strtoi64 (WWNStr, &Fibre->WWN);
+ Strtoi64 (LunStr, &Fibre->Lun);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Fibre;
+}
+
+/**
+ Converts a text device path node to FibreEx device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created FibreEx device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFibreEx (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *WWNStr;
+ CHAR16 *LunStr;
+ FIBRECHANNELEX_DEVICE_PATH *FibreEx;
+
+ WWNStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ FibreEx = (FIBRECHANNELEX_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_FIBRECHANNELEX_DP,
+ (UINT16) sizeof (FIBRECHANNELEX_DEVICE_PATH)
+ );
+
+ FibreEx->Reserved = 0;
+ Strtoi64 (WWNStr, (UINT64 *) (&FibreEx->WWN));
+ Strtoi64 (LunStr, (UINT64 *) (&FibreEx->Lun));
+
+ *(UINT64 *) (&FibreEx->WWN) = SwapBytes64 (*(UINT64 *) (&FibreEx->WWN));
+ *(UINT64 *) (&FibreEx->Lun) = SwapBytes64 (*(UINT64 *) (&FibreEx->Lun));
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) FibreEx;
+}
+
+/**
+ Converts a text device path node to 1394 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created 1394 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromText1394 (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *GuidStr;
+ F1394_DEVICE_PATH *F1394DevPath;
+
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+ F1394DevPath = (F1394_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_1394_DP,
+ sizeof (F1394_DEVICE_PATH)
+ );
+
+ F1394DevPath->Reserved = 0;
+ Xtoi64 (GuidStr, &F1394DevPath->Guid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) F1394DevPath;
+}
+
+/**
+ Converts a text device path node to USB device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsb (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *PortStr;
+ CHAR16 *InterfaceStr;
+ USB_DEVICE_PATH *Usb;
+
+ PortStr = GetNextParamStr (&TextDeviceNode);
+ InterfaceStr = GetNextParamStr (&TextDeviceNode);
+ Usb = (USB_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_DP,
+ sizeof (USB_DEVICE_PATH)
+ );
+
+ Usb->ParentPortNumber = (UINT8) Strtoi (PortStr);
+ Usb->InterfaceNumber = (UINT8) Strtoi (InterfaceStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Usb;
+}
+
+/**
+ Converts a text device path node to I20 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created I20 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextI2O (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *TIDStr;
+ I20_DEVICE_PATH *I2ODevPath;
+
+ TIDStr = GetNextParamStr (&TextDeviceNode);
+ I2ODevPath = (I20_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_I2O_DP,
+ sizeof (I20_DEVICE_PATH)
+ );
+
+ I2ODevPath->Tid = (UINT32) Strtoi (TIDStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) I2ODevPath;
+}
+
+/**
+ Converts a text device path node to Infini Band device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Infini Band device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextInfiniband (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *FlagsStr;
+ CHAR16 *GuidStr;
+ CHAR16 *SidStr;
+ CHAR16 *TidStr;
+ CHAR16 *DidStr;
+ EFI_GUID PortGid;
+ INFINIBAND_DEVICE_PATH *InfiniBand;
+
+ FlagsStr = GetNextParamStr (&TextDeviceNode);
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+ SidStr = GetNextParamStr (&TextDeviceNode);
+ TidStr = GetNextParamStr (&TextDeviceNode);
+ DidStr = GetNextParamStr (&TextDeviceNode);
+ InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_INFINIBAND_DP,
+ sizeof (INFINIBAND_DEVICE_PATH)
+ );
+
+ InfiniBand->ResourceFlags = (UINT32) Strtoi (FlagsStr);
+ StrToGuid (GuidStr, &PortGid);
+ CopyMem (InfiniBand->PortGid, &PortGid, sizeof (EFI_GUID));
+ Strtoi64 (SidStr, &InfiniBand->ServiceId);
+ Strtoi64 (TidStr, &InfiniBand->TargetPortId);
+ Strtoi64 (DidStr, &InfiniBand->DeviceId);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand;
+}
+
+/**
+ Converts a text device path node to Vendor-Defined Messaging device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor-Defined Messaging device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMsg (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextVendor (
+ TextDeviceNode,
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP
+ );
+}
+
+/**
+ Converts a text device path node to Vendor defined PC-ANSI device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor defined PC-ANSI device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenPcAnsi (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+
+ Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (VENDOR_DEVICE_PATH));
+ CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+ Converts a text device path node to Vendor defined VT100 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor defined VT100 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100 (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+
+ Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (VENDOR_DEVICE_PATH));
+ CopyGuid (&Vendor->Guid, &gEfiVT100Guid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+ Converts a text device path node to Vendor defined VT100 Plus device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor defined VT100 Plus device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenVt100Plus (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+
+ Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (VENDOR_DEVICE_PATH));
+ CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+ Converts a text device path node to Vendor defined UTF8 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor defined UTF8 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenUtf8 (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+
+ Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (VENDOR_DEVICE_PATH));
+ CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
+}
+
+/**
+ Converts a text device path node to UART Flow Control device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created UART Flow Control device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUartFlowCtrl (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *ValueStr;
+ UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl;
+
+ ValueStr = GetNextParamStr (&TextDeviceNode);
+ UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (UART_FLOW_CONTROL_DEVICE_PATH)
+ );
+
+ CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid);
+ if (StrCmp (ValueStr, L"XonXoff") == 0) {
+ UartFlowControl->FlowControlMap = 2;
+ } else if (StrCmp (ValueStr, L"Hardware") == 0) {
+ UartFlowControl->FlowControlMap = 1;
+ } else {
+ UartFlowControl->FlowControlMap = 0;
+ }
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl;
+}
+
+/**
+ Converts a text device path node to Serial Attached SCSI device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Serial Attached SCSI device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSAS (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *AddressStr;
+ CHAR16 *LunStr;
+ CHAR16 *RTPStr;
+ CHAR16 *SASSATAStr;
+ CHAR16 *LocationStr;
+ CHAR16 *ConnectStr;
+ CHAR16 *DriveBayStr;
+ CHAR16 *ReservedStr;
+ UINT16 Info;
+ SAS_DEVICE_PATH *Sas;
+
+ AddressStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ RTPStr = GetNextParamStr (&TextDeviceNode);
+ SASSATAStr = GetNextParamStr (&TextDeviceNode);
+ LocationStr = GetNextParamStr (&TextDeviceNode);
+ ConnectStr = GetNextParamStr (&TextDeviceNode);
+ DriveBayStr = GetNextParamStr (&TextDeviceNode);
+ ReservedStr = GetNextParamStr (&TextDeviceNode);
+ Info = 0x0000;
+ Sas = (SAS_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (SAS_DEVICE_PATH)
+ );
+
+ CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid);
+ Strtoi64 (AddressStr, &Sas->SasAddress);
+ Strtoi64 (LunStr, &Sas->Lun);
+ Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
+ if (StrCmp (SASSATAStr, L"NoTopology") != 0) {
+ if (StrCmp (DriveBayStr, L"0") == 0) {
+ Info |= 0x0001;
+ } else {
+ Info |= 0x0002;
+ Info = (UINT16) (Info | (Strtoi (DriveBayStr) << 8));
+ }
+
+ if (StrCmp (SASSATAStr, L"SATA") == 0) {
+ Info |= 0x0010;
+ }
+
+ if (StrCmp (LocationStr, L"External") == 0) {
+ Info |= 0x0020;
+ }
+
+ if (StrCmp (ConnectStr, L"Expanded") == 0) {
+ Info |= 0x0040;
+ }
+ }
+
+ Sas->DeviceTopology = Info;
+ Sas->Reserved = (UINT32) Strtoi (ReservedStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Sas;
+}
+
+/**
+ Converts a text device path node to Serial Attached SCSI Ex device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Serial Attached SCSI Ex device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSasEx (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *AddressStr;
+ CHAR16 *LunStr;
+ CHAR16 *RTPStr;
+ CHAR16 *SASSATAStr;
+ CHAR16 *LocationStr;
+ CHAR16 *ConnectStr;
+ CHAR16 *DriveBayStr;
+ UINT16 Info;
+ SASEX_DEVICE_PATH *SasEx;
+
+ AddressStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ RTPStr = GetNextParamStr (&TextDeviceNode);
+ SASSATAStr = GetNextParamStr (&TextDeviceNode);
+ LocationStr = GetNextParamStr (&TextDeviceNode);
+ ConnectStr = GetNextParamStr (&TextDeviceNode);
+ DriveBayStr = GetNextParamStr (&TextDeviceNode);
+ Info = 0x0000;
+ SasEx = (SASEX_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_SASEX_DP,
+ (UINT16) sizeof (SASEX_DEVICE_PATH)
+ );
+
+ Strtoi64 (AddressStr, (UINT64 *) &SasEx->SasAddress);
+ Strtoi64 (LunStr, (UINT64 *) &SasEx->Lun);
+ *(UINT64 *) &SasEx->SasAddress = SwapBytes64 (*(UINT64 *) &SasEx->SasAddress);
+ *(UINT64 *) &SasEx->Lun = SwapBytes64 (*(UINT64 *) &SasEx->Lun);
+ SasEx->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
+ if (StrCmp (SASSATAStr, L"NoTopology") != 0) {
+ if (StrCmp (DriveBayStr, L"0") == 0) {
+ Info |= 0x0001;
+ } else {
+ Info |= 0x0002;
+ Info = (UINT16) (Info | (Strtoi (DriveBayStr) << 8));
+ }
+
+ if (StrCmp (SASSATAStr, L"SATA") == 0) {
+ Info |= 0x0010;
+ }
+
+ if (StrCmp (LocationStr, L"External") == 0) {
+ Info |= 0x0020;
+ }
+
+ if (StrCmp (ConnectStr, L"Expanded") == 0) {
+ Info |= 0x0040;
+ }
+ }
+
+ SasEx->DeviceTopology = Info;
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) SasEx;
+}
+
+/**
+ Converts a text device path node to Debug Port device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Debug Port device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextDebugPort (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ VENDOR_DEFINED_MESSAGING_DEVICE_PATH *Vend;
+
+ Vend = (VENDOR_DEFINED_MESSAGING_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ sizeof (VENDOR_DEFINED_MESSAGING_DEVICE_PATH)
+ );
+
+ CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vend;
+}
+
+/**
+ Converts a text device path node to MAC device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created MAC device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMAC (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *AddressStr;
+ CHAR16 *IfTypeStr;
+ UINTN Length;
+ MAC_ADDRESS_DEVICE_PATH *MACDevPath;
+
+ AddressStr = GetNextParamStr (&TextDeviceNode);
+ IfTypeStr = GetNextParamStr (&TextDeviceNode);
+ MACDevPath = (MAC_ADDRESS_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_MAC_ADDR_DP,
+ sizeof (MAC_ADDRESS_DEVICE_PATH)
+ );
+
+ MACDevPath->IfType = (UINT8) Strtoi (IfTypeStr);
+
+ Length = sizeof (EFI_MAC_ADDRESS);
+ StrToBuf (&MACDevPath->MacAddr.mac[0], Length, AddressStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) MACDevPath;
+}
+
+
+/**
+ Converts a text format to the network protocol ID.
+
+ @param Text String of protocol field.
+
+ @return Network protocol ID .
+
+**/
+UINTN
+NetworkProtocolFromText (
+ IN CHAR16 *Text
+ )
+{
+ if (StrCmp (Text, L"UDP") == 0) {
+ return RFC_1700_UDP_PROTOCOL;
+ }
+
+ if (StrCmp (Text, L"TCP") == 0) {
+ return RFC_1700_TCP_PROTOCOL;
+ }
+
+ return Strtoi (Text);
+}
+
+
+/**
+ Converts a text device path node to IPV4 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created IPV4 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv4 (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *RemoteIPStr;
+ CHAR16 *ProtocolStr;
+ CHAR16 *TypeStr;
+ CHAR16 *LocalIPStr;
+ CHAR16 *GatewayIPStr;
+ CHAR16 *SubnetMaskStr;
+ IPV4_DEVICE_PATH *IPv4;
+
+ RemoteIPStr = GetNextParamStr (&TextDeviceNode);
+ ProtocolStr = GetNextParamStr (&TextDeviceNode);
+ TypeStr = GetNextParamStr (&TextDeviceNode);
+ LocalIPStr = GetNextParamStr (&TextDeviceNode);
+ GatewayIPStr = GetNextParamStr (&TextDeviceNode);
+ SubnetMaskStr = GetNextParamStr (&TextDeviceNode);
+ IPv4 = (IPV4_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv4_DP,
+ sizeof (IPV4_DEVICE_PATH)
+ );
+
+ StrToIPv4Addr (&RemoteIPStr, &IPv4->RemoteIpAddress);
+ IPv4->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr);
+ if (StrCmp (TypeStr, L"Static") == 0) {
+ IPv4->StaticIpAddress = TRUE;
+ } else {
+ IPv4->StaticIpAddress = FALSE;
+ }
+
+ StrToIPv4Addr (&LocalIPStr, &IPv4->LocalIpAddress);
+ if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) {
+ StrToIPv4Addr (&GatewayIPStr, &IPv4->GatewayIpAddress);
+ StrToIPv4Addr (&SubnetMaskStr, &IPv4->SubnetMask);
+ } else {
+ ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress));
+ ZeroMem (&IPv4->SubnetMask, sizeof (IPv4->SubnetMask));
+ }
+
+ IPv4->LocalPort = 0;
+ IPv4->RemotePort = 0;
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) IPv4;
+}
+
+/**
+ Converts a text device path node to IPV6 device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created IPV6 device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextIPv6 (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *RemoteIPStr;
+ CHAR16 *ProtocolStr;
+ CHAR16 *TypeStr;
+ CHAR16 *LocalIPStr;
+ CHAR16 *GatewayIPStr;
+ CHAR16 *PrefixLengthStr;
+ IPV6_DEVICE_PATH *IPv6;
+
+ RemoteIPStr = GetNextParamStr (&TextDeviceNode);
+ ProtocolStr = GetNextParamStr (&TextDeviceNode);
+ TypeStr = GetNextParamStr (&TextDeviceNode);
+ LocalIPStr = GetNextParamStr (&TextDeviceNode);
+ PrefixLengthStr = GetNextParamStr (&TextDeviceNode);
+ GatewayIPStr = GetNextParamStr (&TextDeviceNode);
+ IPv6 = (IPV6_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv6_DP,
+ sizeof (IPV6_DEVICE_PATH)
+ );
+
+ StrToIPv6Addr (&RemoteIPStr, &IPv6->RemoteIpAddress);
+ IPv6->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr);
+ if (StrCmp (TypeStr, L"Static") == 0) {
+ IPv6->IpAddressOrigin = 0;
+ } else if (StrCmp (TypeStr, L"StatelessAutoConfigure") == 0) {
+ IPv6->IpAddressOrigin = 1;
+ } else {
+ IPv6->IpAddressOrigin = 2;
+ }
+
+ StrToIPv6Addr (&LocalIPStr, &IPv6->LocalIpAddress);
+ if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) {
+ StrToIPv6Addr (&GatewayIPStr, &IPv6->GatewayIpAddress);
+ IPv6->PrefixLength = (UINT8) Strtoi (PrefixLengthStr);
+ } else {
+ ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress));
+ IPv6->PrefixLength = 0;
+ }
+
+ IPv6->LocalPort = 0;
+ IPv6->RemotePort = 0;
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) IPv6;
+}
+
+/**
+ Converts a text device path node to UART device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created UART device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUart (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *BaudStr;
+ CHAR16 *DataBitsStr;
+ CHAR16 *ParityStr;
+ CHAR16 *StopBitsStr;
+ UART_DEVICE_PATH *Uart;
+
+ BaudStr = GetNextParamStr (&TextDeviceNode);
+ DataBitsStr = GetNextParamStr (&TextDeviceNode);
+ ParityStr = GetNextParamStr (&TextDeviceNode);
+ StopBitsStr = GetNextParamStr (&TextDeviceNode);
+ Uart = (UART_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ sizeof (UART_DEVICE_PATH)
+ );
+
+ Uart->BaudRate = (StrCmp (BaudStr, L"DEFAULT") == 0) ? 115200 : Dtoi (BaudStr);
+ Uart->DataBits = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Dtoi (DataBitsStr));
+ switch (*ParityStr) {
+ case L'D':
+ Uart->Parity = 0;
+ break;
+
+ case L'N':
+ Uart->Parity = 1;
+ break;
+
+ case L'E':
+ Uart->Parity = 2;
+ break;
+
+ case L'O':
+ Uart->Parity = 3;
+ break;
+
+ case L'M':
+ Uart->Parity = 4;
+ break;
+
+ case L'S':
+ Uart->Parity = 5;
+
+ default:
+ Uart->Parity = 0xff;
+ }
+
+ if (StrCmp (StopBitsStr, L"D") == 0) {
+ Uart->StopBits = (UINT8) 0;
+ } else if (StrCmp (StopBitsStr, L"1") == 0) {
+ Uart->StopBits = (UINT8) 1;
+ } else if (StrCmp (StopBitsStr, L"1.5") == 0) {
+ Uart->StopBits = (UINT8) 2;
+ } else if (StrCmp (StopBitsStr, L"2") == 0) {
+ Uart->StopBits = (UINT8) 3;
+ } else {
+ Uart->StopBits = 0xff;
+ }
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Uart;
+}
+
+/**
+ Converts a text device path node to USB class device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+ @param UsbClassText A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text.
+
+ @return A pointer to the newly-created USB class device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+ConvertFromTextUsbClass (
+ IN CHAR16 *TextDeviceNode,
+ IN USB_CLASS_TEXT *UsbClassText
+ )
+{
+ CHAR16 *VIDStr;
+ CHAR16 *PIDStr;
+ CHAR16 *ClassStr;
+ CHAR16 *SubClassStr;
+ CHAR16 *ProtocolStr;
+ USB_CLASS_DEVICE_PATH *UsbClass;
+
+ UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ sizeof (USB_CLASS_DEVICE_PATH)
+ );
+
+ VIDStr = GetNextParamStr (&TextDeviceNode);
+ PIDStr = GetNextParamStr (&TextDeviceNode);
+ if (UsbClassText->ClassExist) {
+ ClassStr = GetNextParamStr (&TextDeviceNode);
+ UsbClass->DeviceClass = (UINT8) Strtoi (ClassStr);
+ } else {
+ UsbClass->DeviceClass = UsbClassText->Class;
+ }
+ if (UsbClassText->SubClassExist) {
+ SubClassStr = GetNextParamStr (&TextDeviceNode);
+ UsbClass->DeviceSubClass = (UINT8) Strtoi (SubClassStr);
+ } else {
+ UsbClass->DeviceSubClass = UsbClassText->SubClass;
+ }
+
+ ProtocolStr = GetNextParamStr (&TextDeviceNode);
+
+ UsbClass->VendorId = (UINT16) Strtoi (VIDStr);
+ UsbClass->ProductId = (UINT16) Strtoi (PIDStr);
+ UsbClass->DeviceProtocol = (UINT8) Strtoi (ProtocolStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass;
+}
+
+
+/**
+ Converts a text device path node to USB class device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB class device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbClass (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = TRUE;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB audio device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB audio device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbAudio (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_AUDIO;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB CDC Control device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB CDC Control device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCControl (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_CDCCONTROL;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB HID device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB HID device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHID (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_HID;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB Image device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB Image device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbImage (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_IMAGE;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB Print device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB Print device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbPrinter (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_PRINTER;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB mass storage device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB mass storage device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbMassStorage (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_MASS_STORAGE;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB HUB device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB HUB device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbHub (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_HUB;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB CDC data device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB CDC data device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbCDCData (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_CDCDATA;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB smart card device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB smart card device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbSmartCard (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_SMART_CARD;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB video device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB video device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbVideo (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_VIDEO;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB diagnostic device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB diagnostic device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDiagnostic (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_DIAGNOSTIC;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB wireless device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB wireless device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWireless (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_WIRELESS;
+ UsbClassText.SubClassExist = TRUE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB device firmware update device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB device firmware update device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbDeviceFirmwareUpdate (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_RESERVE;
+ UsbClassText.SubClassExist = FALSE;
+ UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB IRDA bridge device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB IRDA bridge device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbIrdaBridge (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_RESERVE;
+ UsbClassText.SubClassExist = FALSE;
+ UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB text and measurement device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB text and measurement device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbTestAndMeasurement (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ USB_CLASS_TEXT UsbClassText;
+
+ UsbClassText.ClassExist = FALSE;
+ UsbClassText.Class = USB_CLASS_RESERVE;
+ UsbClassText.SubClassExist = FALSE;
+ UsbClassText.SubClass = USB_SUBCLASS_TEST;
+
+ return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
+}
+
+/**
+ Converts a text device path node to USB WWID device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created USB WWID device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUsbWwid (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *VIDStr;
+ CHAR16 *PIDStr;
+ CHAR16 *InterfaceNumStr;
+ CHAR16 *SerialNumberStr;
+ USB_WWID_DEVICE_PATH *UsbWwid;
+
+ VIDStr = GetNextParamStr (&TextDeviceNode);
+ PIDStr = GetNextParamStr (&TextDeviceNode);
+ InterfaceNumStr = GetNextParamStr (&TextDeviceNode);
+ SerialNumberStr = GetNextParamStr (&TextDeviceNode);
+ UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_WWID_CLASS_DP,
+ (UINT16) (sizeof (USB_WWID_DEVICE_PATH) + StrSize (SerialNumberStr))
+ );
+
+ UsbWwid->VendorId = (UINT16) Strtoi (VIDStr);
+ UsbWwid->ProductId = (UINT16) Strtoi (PIDStr);
+ UsbWwid->InterfaceNumber = (UINT16) Strtoi (InterfaceNumStr);
+ StrCpy ((CHAR16 *) ((UINT8 *) UsbWwid + sizeof (USB_WWID_DEVICE_PATH)), SerialNumberStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid;
+}
+
+/**
+ Converts a text device path node to Logic Unit device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Logic Unit device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextUnit (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *LunStr;
+ LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
+
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ LogicalUnit = (LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_LOGICAL_UNIT_CLASS_DP,
+ (UINT16) sizeof (LOGICAL_UNIT_DEVICE_PATH)
+ );
+
+ LogicalUnit->Lun = (UINT8) Strtoi (LunStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit;
+}
+
+/**
+ Converts a text device path node to iSCSI device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created iSCSI device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextiSCSI (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ UINT16 Options;
+ CHAR16 *NameStr;
+ CHAR16 *PortalGroupStr;
+ CHAR16 *LunStr;
+ CHAR16 *HeaderDigestStr;
+ CHAR16 *DataDigestStr;
+ CHAR16 *AuthenticationStr;
+ CHAR16 *ProtocolStr;
+ CHAR8 *AsciiStr;
+ ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
+
+ NameStr = GetNextParamStr (&TextDeviceNode);
+ PortalGroupStr = GetNextParamStr (&TextDeviceNode);
+ LunStr = GetNextParamStr (&TextDeviceNode);
+ HeaderDigestStr = GetNextParamStr (&TextDeviceNode);
+ DataDigestStr = GetNextParamStr (&TextDeviceNode);
+ AuthenticationStr = GetNextParamStr (&TextDeviceNode);
+ ProtocolStr = GetNextParamStr (&TextDeviceNode);
+ ISCSIDevPath = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_ISCSI_DP,
+ (UINT16) (sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr))
+ );
+
+ AsciiStr = ISCSIDevPath->TargetName;
+ StrToAscii (NameStr, &AsciiStr);
+
+ ISCSIDevPath->TargetPortalGroupTag = (UINT16) Strtoi (PortalGroupStr);
+ Strtoi64 (LunStr, &ISCSIDevPath->Lun);
+
+ Options = 0x0000;
+ if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) {
+ Options |= 0x0002;
+ }
+
+ if (StrCmp (DataDigestStr, L"CRC32C") == 0) {
+ Options |= 0x0008;
+ }
+
+ if (StrCmp (AuthenticationStr, L"None") == 0) {
+ Options |= 0x0800;
+ }
+
+ if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) {
+ Options |= 0x1000;
+ }
+
+ ISCSIDevPath->LoginOption = (UINT16) Options;
+
+ ISCSIDevPath->NetworkProtocol = (UINT16) StrCmp (ProtocolStr, L"TCP");
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) ISCSIDevPath;
+}
+
+/**
+ Converts a text device path node to VLAN device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created VLAN device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVlan (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *VlanStr;
+ VLAN_DEVICE_PATH *Vlan;
+
+ VlanStr = GetNextParamStr (&TextDeviceNode);
+ Vlan = (VLAN_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_VLAN_DP,
+ sizeof (VLAN_DEVICE_PATH)
+ );
+
+ Vlan->VlanId = (UINT16) Strtoi (VlanStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Vlan;
+}
+
+/**
+ Converts a text device path node to HD device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created HD device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextHD (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *PartitionStr;
+ CHAR16 *TypeStr;
+ CHAR16 *SignatureStr;
+ CHAR16 *StartStr;
+ CHAR16 *SizeStr;
+ UINT32 Signature32;
+ EFI_GUID SignatureGuid;
+ HARDDRIVE_DEVICE_PATH *Hd;
+
+ PartitionStr = GetNextParamStr (&TextDeviceNode);
+ TypeStr = GetNextParamStr (&TextDeviceNode);
+ SignatureStr = GetNextParamStr (&TextDeviceNode);
+ StartStr = GetNextParamStr (&TextDeviceNode);
+ SizeStr = GetNextParamStr (&TextDeviceNode);
+ Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_HARDDRIVE_DP,
+ sizeof (HARDDRIVE_DEVICE_PATH)
+ );
+
+ Hd->PartitionNumber = (UINT32) Dtoi (PartitionStr);
+
+ ZeroMem (Hd->Signature, 16);
+ Hd->MBRType = (UINT8) 0;
+
+ if (StrCmp (TypeStr, L"MBR") == 0) {
+ Hd->SignatureType = SIGNATURE_TYPE_MBR;
+ Hd->MBRType = 0x01;
+
+ Signature32 = (UINT32) Strtoi (SignatureStr);
+ CopyMem (Hd->Signature, &Signature32, sizeof (UINT32));
+ } else if (StrCmp (TypeStr, L"GPT") == 0) {
+ Hd->SignatureType = SIGNATURE_TYPE_GUID;
+ Hd->MBRType = 0x02;
+
+ StrToGuid (SignatureStr, &SignatureGuid);
+ CopyMem (Hd->Signature, &SignatureGuid, sizeof (EFI_GUID));
+ } else {
+ Hd->SignatureType = (UINT8) Strtoi (TypeStr);
+ }
+
+ Strtoi64 (StartStr, &Hd->PartitionStart);
+ Strtoi64 (SizeStr, &Hd->PartitionSize);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Hd;
+}
+
+/**
+ Converts a text device path node to CDROM device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created CDROM device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextCDROM (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *EntryStr;
+ CHAR16 *StartStr;
+ CHAR16 *SizeStr;
+ CDROM_DEVICE_PATH *CDROMDevPath;
+
+ EntryStr = GetNextParamStr (&TextDeviceNode);
+ StartStr = GetNextParamStr (&TextDeviceNode);
+ SizeStr = GetNextParamStr (&TextDeviceNode);
+ CDROMDevPath = (CDROM_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_CDROM_DP,
+ sizeof (CDROM_DEVICE_PATH)
+ );
+
+ CDROMDevPath->BootEntry = (UINT32) Strtoi (EntryStr);
+ Strtoi64 (StartStr, &CDROMDevPath->PartitionStart);
+ Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) CDROMDevPath;
+}
+
+/**
+ Converts a text device path node to Vendor-defined media device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Vendor-defined media device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextVenMEDIA (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ return ConvertFromTextVendor (
+ TextDeviceNode,
+ MEDIA_DEVICE_PATH,
+ MEDIA_VENDOR_DP
+ );
+}
+
+/**
+ Converts a text device path node to File device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created File device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFilePath (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ FILEPATH_DEVICE_PATH *File;
+
+ File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_FILEPATH_DP,
+ (UINT16) (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2)
+ );
+
+ StrCpy (File->PathName, TextDeviceNode);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) File;
+}
+
+/**
+ Converts a text device path node to Media protocol device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Media protocol device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextMedia (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *GuidStr;
+ PROTOCOL_DEVICE_PATH *Media;
+
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+ Media = (PROTOCOL_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_PROTOCOL_DP,
+ sizeof (PROTOCOL_DEVICE_PATH)
+ );
+
+ StrToGuid (GuidStr, &Media->ProtocolGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Media;
+}
+
+/**
+ Converts a text device path node to firmware volume device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created firmware volume device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFv (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *GuidStr;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *Fv;
+
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+ Fv = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_FV_DP,
+ sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
+ );
+
+ StrToGuid (GuidStr, &Fv->NameGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Fv;
+}
+
+/**
+ Converts a text device path node to firmware file device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created firmware file device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextFvFile (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *GuidStr;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile;
+
+ GuidStr = GetNextParamStr (&TextDeviceNode);
+ FvFile = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_FV_FILEPATH_DP,
+ sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
+ );
+
+ StrToGuid (GuidStr, &FvFile->NameGuid);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) FvFile;
+}
+
+/**
+ Converts a text device path node to text relative offset device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created Text device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextRelativeOffsetRange (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *StartingOffsetStr;
+ CHAR16 *EndingOffsetStr;
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
+
+ StartingOffsetStr = GetNextParamStr (&TextDeviceNode);
+ EndingOffsetStr = GetNextParamStr (&TextDeviceNode);
+ Offset = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) CreateDeviceNode (
+ MEDIA_DEVICE_PATH,
+ MEDIA_RELATIVE_OFFSET_RANGE_DP,
+ sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)
+ );
+
+ Strtoi64 (StartingOffsetStr, &Offset->StartingOffset);
+ Strtoi64 (EndingOffsetStr, &Offset->EndingOffset);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Offset;
+}
+
+/**
+ Converts a text device path node to BIOS Boot Specification device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created BIOS Boot Specification device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextBBS (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ CHAR16 *TypeStr;
+ CHAR16 *IdStr;
+ CHAR16 *FlagsStr;
+ CHAR8 *AsciiStr;
+ BBS_BBS_DEVICE_PATH *Bbs;
+
+ TypeStr = GetNextParamStr (&TextDeviceNode);
+ IdStr = GetNextParamStr (&TextDeviceNode);
+ FlagsStr = GetNextParamStr (&TextDeviceNode);
+ Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode (
+ BBS_DEVICE_PATH,
+ BBS_BBS_DP,
+ (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr))
+ );
+
+ if (StrCmp (TypeStr, L"Floppy") == 0) {
+ Bbs->DeviceType = BBS_TYPE_FLOPPY;
+ } else if (StrCmp (TypeStr, L"HD") == 0) {
+ Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
+ } else if (StrCmp (TypeStr, L"CDROM") == 0) {
+ Bbs->DeviceType = BBS_TYPE_CDROM;
+ } else if (StrCmp (TypeStr, L"PCMCIA") == 0) {
+ Bbs->DeviceType = BBS_TYPE_PCMCIA;
+ } else if (StrCmp (TypeStr, L"USB") == 0) {
+ Bbs->DeviceType = BBS_TYPE_USB;
+ } else if (StrCmp (TypeStr, L"Network") == 0) {
+ Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK;
+ } else {
+ Bbs->DeviceType = (UINT16) Strtoi (TypeStr);
+ }
+
+ AsciiStr = Bbs->String;
+ StrToAscii (IdStr, &AsciiStr);
+
+ Bbs->StatusFlag = (UINT16) Strtoi (FlagsStr);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Bbs;
+}
+
+/**
+ Converts a text device path node to SATA device path structure.
+
+ @param TextDeviceNode The input Text device path node.
+
+ @return A pointer to the newly-created SATA device path structure.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+DevPathFromTextSata (
+ IN CHAR16 *TextDeviceNode
+ )
+{
+ SATA_DEVICE_PATH *Sata;
+ CHAR16 *Param1;
+ CHAR16 *Param2;
+ CHAR16 *Param3;
+
+ //
+ // The PMPN is optional.
+ //
+ Param1 = GetNextParamStr (&TextDeviceNode);
+ Param2 = GetNextParamStr (&TextDeviceNode);
+ Param3 = NULL;
+ if (!IS_NULL (TextDeviceNode)) {
+ Param3 = GetNextParamStr (&TextDeviceNode);
+ }
+
+ Sata = (SATA_DEVICE_PATH *) CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_SATA_DP,
+ sizeof (SATA_DEVICE_PATH)
+ );
+ Sata->PortNumber = (UINT16) Xtoi (Param1);
+ if (Param3 != NULL) {
+ Sata->MultiplierPortNumber = (UINT16) Xtoi (Param2);
+ Param2 = Param3;
+ } else {
+ Sata->MultiplierPortNumber = SATA_HBA_DIRECT_CONNECT_FLAG;
+ }
+ Sata->LogicalUnitNumber = (UINT16) Xtoi (Param2);
+
+ return (EFI_DEVICE_PATH_PROTOCOL *) Sata;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE DevPathFromTextTable[] = {
+ {L"Pci", DevPathFromTextPci},
+ {L"PcCard", DevPathFromTextPcCard},
+ {L"MemoryMapped", DevPathFromTextMemoryMapped},
+ {L"VenHw", DevPathFromTextVenHw},
+ {L"Ctrl", DevPathFromTextCtrl},
+ {L"Acpi", DevPathFromTextAcpi},
+ {L"PciRoot", DevPathFromTextPciRoot},
+ {L"PcieRoot", DevPathFromTextPcieRoot},
+ {L"Floppy", DevPathFromTextFloppy},
+ {L"Keyboard", DevPathFromTextKeyboard},
+ {L"Serial", DevPathFromTextSerial},
+ {L"ParallelPort", DevPathFromTextParallelPort},
+ {L"AcpiEx", DevPathFromTextAcpiEx},
+ {L"AcpiExp", DevPathFromTextAcpiExp},
+ {L"AcpiAdr", DevPathFromTextAcpiAdr},
+ {L"Ata", DevPathFromTextAta},
+ {L"Scsi", DevPathFromTextScsi},
+ {L"Fibre", DevPathFromTextFibre},
+ {L"FibreEx", DevPathFromTextFibreEx},
+ {L"I1394", DevPathFromText1394},
+ {L"USB", DevPathFromTextUsb},
+ {L"I2O", DevPathFromTextI2O},
+ {L"Infiniband", DevPathFromTextInfiniband},
+ {L"VenMsg", DevPathFromTextVenMsg},
+ {L"VenPcAnsi", DevPathFromTextVenPcAnsi},
+ {L"VenVt100", DevPathFromTextVenVt100},
+ {L"VenVt100Plus", DevPathFromTextVenVt100Plus},
+ {L"VenUtf8", DevPathFromTextVenUtf8},
+ {L"UartFlowCtrl", DevPathFromTextUartFlowCtrl},
+ {L"SAS", DevPathFromTextSAS},
+ {L"SasEx", DevPathFromTextSasEx},
+ {L"DebugPort", DevPathFromTextDebugPort},
+ {L"MAC", DevPathFromTextMAC},
+ {L"IPv4", DevPathFromTextIPv4},
+ {L"IPv6", DevPathFromTextIPv6},
+ {L"Uart", DevPathFromTextUart},
+ {L"UsbClass", DevPathFromTextUsbClass},
+ {L"UsbAudio", DevPathFromTextUsbAudio},
+ {L"UsbCDCControl", DevPathFromTextUsbCDCControl},
+ {L"UsbHID", DevPathFromTextUsbHID},
+ {L"UsbImage", DevPathFromTextUsbImage},
+ {L"UsbPrinter", DevPathFromTextUsbPrinter},
+ {L"UsbMassStorage", DevPathFromTextUsbMassStorage},
+ {L"UsbHub", DevPathFromTextUsbHub},
+ {L"UsbCDCData", DevPathFromTextUsbCDCData},
+ {L"UsbSmartCard", DevPathFromTextUsbSmartCard},
+ {L"UsbVideo", DevPathFromTextUsbVideo},
+ {L"UsbDiagnostic", DevPathFromTextUsbDiagnostic},
+ {L"UsbWireless", DevPathFromTextUsbWireless},
+ {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate},
+ {L"UsbIrdaBridge", DevPathFromTextUsbIrdaBridge},
+ {L"UsbTestAndMeasurement", DevPathFromTextUsbTestAndMeasurement},
+ {L"UsbWwid", DevPathFromTextUsbWwid},
+ {L"Unit", DevPathFromTextUnit},
+ {L"iSCSI", DevPathFromTextiSCSI},
+ {L"Vlan", DevPathFromTextVlan},
+ {L"HD", DevPathFromTextHD},
+ {L"CDROM", DevPathFromTextCDROM},
+ {L"VenMEDIA", DevPathFromTextVenMEDIA},
+ {L"Media", DevPathFromTextMedia},
+ {L"Fv", DevPathFromTextFv},
+ {L"FvFile", DevPathFromTextFvFile},
+ {L"Offset", DevPathFromTextRelativeOffsetRange},
+ {L"BBS", DevPathFromTextBBS},
+ {L"Sata", DevPathFromTextSata},
+ {NULL, NULL}
+};
+
+/**
+ Convert text to the binary representation of a device node.
+
+ @param TextDeviceNode TextDeviceNode points to the text representation of a device
+ node. Conversion starts with the first character and continues
+ until the first non-device node character.
+
+ @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
+ insufficient memory or text unsupported.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+ConvertTextToDeviceNode (
+ IN CONST CHAR16 *TextDeviceNode
+ )
+{
+ DUMP_NODE DumpNode;
+ CHAR16 *ParamStr;
+ EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
+ CHAR16 *DeviceNodeStr;
+ UINTN Index;
+
+ if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) {
+ return NULL;
+ }
+
+ ParamStr = NULL;
+ DumpNode = NULL;
+ DeviceNodeStr = StrDuplicate (TextDeviceNode);
+ ASSERT (DeviceNodeStr != NULL);
+
+ for (Index = 0; DevPathFromTextTable[Index].Function != NULL; Index++) {
+ ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText);
+ if (ParamStr != NULL) {
+ DumpNode = DevPathFromTextTable[Index].Function;
+ break;
+ }
+ }
+
+ if (DumpNode == NULL) {
+ //
+ // A file path
+ //
+ DumpNode = DevPathFromTextFilePath;
+ DeviceNode = DumpNode (DeviceNodeStr);
+ } else {
+ DeviceNode = DumpNode (ParamStr);
+ FreePool (ParamStr);
+ }
+
+ FreePool (DeviceNodeStr);
+
+ return DeviceNode;
+}
+
+/**
+ Convert text to the binary representation of a device path.
+
+
+ @param TextDevicePath TextDevicePath points to the text representation of a device
+ path. Conversion starts with the first character and continues
+ until the first non-device node character.
+
+ @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
+ there was insufficient memory.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+ConvertTextToDevicePath (
+ IN CONST CHAR16 *TextDevicePath
+ )
+{
+ DUMP_NODE DumpNode;
+ CHAR16 *ParamStr;
+ EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ CHAR16 *DevicePathStr;
+ CHAR16 *Str;
+ CHAR16 *DeviceNodeStr;
+ UINT8 IsInstanceEnd;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) {
+ return NULL;
+ }
+
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+ ASSERT (DevicePath != NULL);
+ SetDevicePathEndNode (DevicePath);
+
+ ParamStr = NULL;
+ DeviceNodeStr = NULL;
+ DevicePathStr = StrDuplicate (TextDevicePath);
+
+ Str = DevicePathStr;
+ while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) {
+ DumpNode = NULL;
+ for (Index = 0; DevPathFromTextTable[Index].Function != NULL; Index++) {
+ ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText);
+ if (ParamStr != NULL) {
+ DumpNode = DevPathFromTextTable[Index].Function;
+ break;
+ }
+ }
+
+ if (DumpNode == NULL) {
+ //
+ // A file path
+ //
+ DumpNode = DevPathFromTextFilePath;
+ DeviceNode = DumpNode (DeviceNodeStr);
+ } else {
+ DeviceNode = DumpNode (ParamStr);
+ FreePool (ParamStr);
+ }
+
+ NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode);
+ FreePool (DevicePath);
+ FreePool (DeviceNode);
+ DevicePath = NewDevicePath;
+
+ if (IsInstanceEnd != 0) {
+ DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
+ ASSERT (DeviceNode != NULL);
+ SET_DEVICE_PATH_INSTANCE_END_NODE (DeviceNode);
+
+ NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode);
+ FreePool (DevicePath);
+ FreePool (DeviceNode);
+ DevicePath = NewDevicePath;
+ }
+ }
+
+ FreePool (DevicePathStr);
+ return DevicePath;
+}
+
+EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL EfiDevicePathFromTextProtocol = {
+ ConvertTextToDeviceNode,
+ ConvertTextToDevicePath
+};
diff --git a/Core/CORE_DXE/DevicePathToText.c b/Core/CORE_DXE/DevicePathToText.c
new file mode 100644
index 0000000..48642c9
--- /dev/null
+++ b/Core/CORE_DXE/DevicePathToText.c
@@ -0,0 +1,2083 @@
+/** @file
+ DevicePathToText protocol as defined in the UEFI 2.0 specification.
+
+Copyright (c) 2006 - 2010, Intel Corporation. <BR>
+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.
+
+**/
+
+
+#include "DevicePath.h"
+#include "EdkIICommon.h"
+
+/**
+ Concatenates a formatted unicode string to allocated pool. The caller must
+ free the resulting buffer.
+
+ @param Str Tracks the allocated pool, size in use, and
+ amount of pool allocated.
+ @param Fmt The format string
+ @param ... Variable arguments based on the format string.
+
+ @return Allocated buffer with the formatted string printed in it.
+ The caller must free the allocated buffer. The buffer
+ allocation is not packed.
+
+**/
+CHAR16 *
+CatPrint (
+ IN OUT POOL_PRINT *Str,
+ IN CHAR16 *Fmt,
+ ...
+ )
+{
+ UINT16 *AppendStr;
+ VA_LIST Args;
+ UINTN Size;
+
+ AppendStr = AllocateZeroPool (0x1000);
+ if (AppendStr == NULL) {
+ return Str->Str;
+ }
+
+ VA_START (Args, Fmt);
+ UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
+ VA_END (Args);
+ if (NULL == Str->Str) {
+ Size = StrSize (AppendStr);
+ Str->Str = AllocateZeroPool (Size);
+ ASSERT (Str->Str != NULL);
+ } else {
+ Size = StrSize (AppendStr) - sizeof (UINT16);
+ Size = Size + StrSize (Str->Str);
+ Str->Str = ReallocatePool (
+ StrSize (Str->Str),
+ Size,
+ Str->Str
+ );
+ ASSERT (Str->Str != NULL);
+ }
+
+ Str->MaxLen = MAX_CHAR * sizeof (UINT16);
+ if (Size < Str->MaxLen) {
+ StrCat (Str->Str, AppendStr);
+ Str->Len = Size - sizeof (UINT16);
+ }
+
+ FreePool (AppendStr);
+ return Str->Str;
+}
+
+/**
+ Converts a PCI device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextPci (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ PCI_DEVICE_PATH *Pci;
+
+ Pci = DevPath;
+ CatPrint (Str, L"Pci(0x%x,0x%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);
+}
+
+/**
+ Converts a PC Card device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextPccard (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ PCCARD_DEVICE_PATH *Pccard;
+
+ Pccard = DevPath;
+ CatPrint (Str, L"PcCard(0x%x)", (UINTN) Pccard->Function);
+}
+
+/**
+ Converts a Memory Map device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextMemMap (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ MEMMAP_DEVICE_PATH *MemMap;
+
+ MemMap = DevPath;
+ CatPrint (
+ Str,
+ L"MemoryMapped(0x%x,0x%lx,0x%lx)",
+ (UINTN) MemMap->MemoryType,
+ MemMap->StartingAddress,
+ MemMap->EndingAddress
+ );
+}
+
+/**
+ Converts a Vendor device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextVendor (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+ CHAR16 *Type;
+ UINTN Index;
+ UINTN DataLength;
+ UINT32 FlowControlMap;
+ UINT16 Info;
+
+ Vendor = (VENDOR_DEVICE_PATH *) DevPath;
+ switch (DevicePathType (&Vendor->Header)) {
+ case HARDWARE_DEVICE_PATH:
+ Type = L"Hw";
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+ Type = L"Msg";
+ if (AllowShortcuts) {
+ if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
+ CatPrint (Str, L"VenPcAnsi()");
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
+ CatPrint (Str, L"VenVt100()");
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
+ CatPrint (Str, L"VenVt100Plus()");
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
+ CatPrint (Str, L"VenUft8()");
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid)) {
+ FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
+ switch (FlowControlMap & 0x00000003) {
+ case 0:
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
+ break;
+
+ case 1:
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
+ break;
+
+ case 2:
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
+ break;
+
+ default:
+ break;
+ }
+
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {
+ CatPrint (
+ Str,
+ L"SAS(0x%lx,0x%lx,0x%x,",
+ ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
+ ((SAS_DEVICE_PATH *) Vendor)->Lun,
+ (UINTN) ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
+ );
+ Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
+ if ((Info & 0x0f) == 0) {
+ CatPrint (Str, L"NoTopology,0,0,0,");
+ } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
+ CatPrint (
+ Str,
+ L"%s,%s,%s,",
+ ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",
+ ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",
+ ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"
+ );
+ if ((Info & 0x0f) == 1) {
+ CatPrint (Str, L"0,");
+ } else {
+ CatPrint (Str, L"0x%x,",(UINTN) (Info >> 8) & 0xff);
+ }
+ } else {
+ CatPrint (Str, L"0,0,0,0,");
+ }
+
+ CatPrint (Str, L"0x%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);
+ return ;
+ } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
+ CatPrint (Str, L"DebugPort()");
+ return ;
+ }
+ }
+ break;
+
+ case MEDIA_DEVICE_PATH:
+ Type = L"Media";
+ break;
+
+ default:
+ Type = L"?";
+ break;
+ }
+
+ DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
+ CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
+ if (DataLength != 0) {
+ CatPrint (Str, L",");
+ for (Index = 0; Index < DataLength; Index++) {
+ CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
+ }
+ }
+
+ CatPrint (Str, L")");
+}
+
+/**
+ Converts a Controller device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextController (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ CONTROLLER_DEVICE_PATH *Controller;
+
+ Controller = DevPath;
+ CatPrint (
+ Str,
+ L"Ctrl(0x%x)",
+ (UINTN) Controller->Controller
+ );
+}
+
+/**
+ Converts a ACPI device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextAcpi (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ Acpi = DevPath;
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM (Acpi->HID)) {
+ case 0x0a03:
+ CatPrint (Str, L"PciRoot(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ case 0x0a08:
+ CatPrint (Str, L"PcieRoot(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ case 0x0604:
+ CatPrint (Str, L"Floppy(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ case 0x0301:
+ CatPrint (Str, L"Keyboard(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ case 0x0501:
+ CatPrint (Str, L"Serial(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ case 0x0401:
+ CatPrint (Str, L"ParallelPort(0x%x)", (UINTN) Acpi->UID);
+ break;
+
+ default:
+ CatPrint (Str, L"Acpi(PNP%04x,0x%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);
+ break;
+ }
+ } else {
+ CatPrint (Str, L"Acpi(0x%08x,0x%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);
+ }
+}
+
+/**
+ Converts EISA identification to string.
+
+ @param EisaId The input EISA identification.
+ @param Text A pointer to the output string.
+
+**/
+VOID
+EisaIdToText (
+ IN UINT32 EisaId,
+ IN OUT CHAR16 *Text
+ )
+{
+ CHAR16 PnpIdStr[17];
+
+ //
+ //UnicodeSPrint ("%X", 0x0a03) => "0000000000000A03"
+ //
+ UnicodeSPrint (PnpIdStr, 17 * 2, L"%16X", EisaId >> 16);
+
+ UnicodeSPrint (
+ Text,
+ sizeof (CHAR16) + sizeof (CHAR16) + sizeof (CHAR16) + sizeof (PnpIdStr),
+ L"%c%c%c%s",
+ '@' + ((EisaId >> 10) & 0x1f),
+ '@' + ((EisaId >> 5) & 0x1f),
+ '@' + ((EisaId >> 0) & 0x1f),
+ PnpIdStr + (16 - 4)
+ );
+}
+
+/**
+ Converts a ACPI extended HID device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextAcpiEx (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
+ CHAR8 *HIDStr;
+ CHAR8 *UIDStr;
+ CHAR8 *CIDStr;
+ CHAR16 HIDText[11];
+ CHAR16 CIDText[11];
+
+ AcpiEx = DevPath;
+ HIDStr = (CHAR8 *) (((UINT8 *) AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
+ UIDStr = HIDStr + AsciiStrLen (HIDStr) + 1;
+ CIDStr = UIDStr + AsciiStrLen (UIDStr) + 1;
+
+ EisaIdToText (AcpiEx->HID, HIDText);
+ EisaIdToText (AcpiEx->CID, CIDText);
+
+ if ((*HIDStr == '\0') && (*CIDStr == '\0') && (AcpiEx->UID == 0)) {
+ //
+ // use AcpiExp()
+ //
+ CatPrint (
+ Str,
+ L"AcpiExp(%s,%s,%a)",
+ HIDText,
+ CIDText,
+ UIDStr
+ );
+ } else {
+ if (AllowShortcuts) {
+ //
+ // display only
+ //
+ if (AcpiEx->HID == 0) {
+ CatPrint (Str, L"AcpiEx(%a,", HIDStr);
+ } else {
+ CatPrint (Str, L"AcpiEx(%s,", HIDText);
+ }
+
+ if (AcpiEx->UID == 0) {
+ CatPrint (Str, L"%a,", UIDStr);
+ } else {
+ CatPrint (Str, L"0x%x,", (UINTN) AcpiEx->UID);
+ }
+
+ if (AcpiEx->CID == 0) {
+ CatPrint (Str, L"%a)", CIDStr);
+ } else {
+ CatPrint (Str, L"%s)", CIDText);
+ }
+ } else {
+ CatPrint (
+ Str,
+ L"AcpiEx(%s,%s,0x%x,%a,%a,%a)",
+ HIDText,
+ CIDText,
+ (UINTN) AcpiEx->UID,
+ HIDStr,
+ CIDStr,
+ UIDStr
+ );
+ }
+ }
+}
+
+/**
+ Converts a ACPI address device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextAcpiAdr (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ ACPI_ADR_DEVICE_PATH *AcpiAdr;
+ UINT16 Index;
+ UINT16 Length;
+ UINT16 AdditionalAdrCount;
+
+ AcpiAdr = DevPath;
+ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
+ AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
+
+ CatPrint (Str, L"AcpiAdr(0x%x", (UINTN) AcpiAdr->ADR);
+ for (Index = 0; Index < AdditionalAdrCount; Index++) {
+ CatPrint (Str, L",0x%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
+ }
+ CatPrint (Str, L")");
+}
+
+/**
+ Converts a ATAPI device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextAtapi (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ ATAPI_DEVICE_PATH *Atapi;
+
+ Atapi = DevPath;
+
+ if (DisplayOnly) {
+ CatPrint (Str, L"Ata(0x%x)", (UINTN) Atapi->Lun);
+ } else {
+ CatPrint (
+ Str,
+ L"Ata(%s,%s,0x%x)",
+ (Atapi->PrimarySecondary == 1) ? L"Secondary" : L"Primary",
+ (Atapi->SlaveMaster == 1) ? L"Slave" : L"Master",
+ (UINTN) Atapi->Lun
+ );
+ }
+}
+
+/**
+ Converts a SCSI device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextScsi (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ SCSI_DEVICE_PATH *Scsi;
+
+ Scsi = DevPath;
+ CatPrint (Str, L"Scsi(0x%x,0x%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);
+}
+
+/**
+ Converts a Fibre device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextFibre (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ FIBRECHANNEL_DEVICE_PATH *Fibre;
+
+ Fibre = DevPath;
+ CatPrint (Str, L"Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun);
+}
+
+/**
+ Converts a FibreEx device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextFibreEx (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ FIBRECHANNELEX_DEVICE_PATH *FibreEx;
+ UINTN Index;
+
+ FibreEx = DevPath;
+ CatPrint (Str, L"FibreEx(0x");
+ for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) {
+ CatPrint (Str, L"%02x", FibreEx->WWN[Index]);
+ }
+ CatPrint (Str, L",0x");
+ for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) {
+ CatPrint (Str, L"%02x", FibreEx->Lun[Index]);
+ }
+ CatPrint (Str, L")");
+}
+
+/**
+ Converts a Sas Ex device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextSasEx (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ SASEX_DEVICE_PATH *SasEx;
+ UINTN Index;
+
+ SasEx = DevPath;
+ CatPrint (Str, L"SasEx(0x");
+
+ for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) {
+ CatPrint (Str, L"%02x", SasEx->SasAddress[Index]);
+ }
+ CatPrint (Str, L",0x");
+ for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) {
+ CatPrint (Str, L"%02x", SasEx->Lun[Index]);
+ }
+ CatPrint (Str, L",0x%x,", SasEx->RelativeTargetPort);
+
+ if ((SasEx->DeviceTopology & 0x0f) == 0) {
+ CatPrint (Str, L"NoTopology,0,0,0");
+ } else if (((SasEx->DeviceTopology & 0x0f) == 1) || ((SasEx->DeviceTopology & 0x0f) == 2)) {
+ CatPrint (
+ Str,
+ L"%s,%s,%s,",
+ ((SasEx->DeviceTopology & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",
+ ((SasEx->DeviceTopology & (0x1 << 5)) != 0) ? L"External" : L"Internal",
+ ((SasEx->DeviceTopology & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"
+ );
+ if ((SasEx->DeviceTopology & 0x0f) == 1) {
+ CatPrint (Str, L"0");
+ } else {
+ CatPrint (Str, L"0x%x", (SasEx->DeviceTopology >> 8) & 0xff);
+ }
+ } else {
+ CatPrint (Str, L"0,0,0,0");
+ }
+
+ CatPrint (Str, L")");
+ return ;
+
+}
+
+/**
+ Converts a 1394 device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToText1394 (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ F1394_DEVICE_PATH *F1394DevPath;
+
+ F1394DevPath = DevPath;
+ //
+ // Guid has format of IEEE-EUI64
+ //
+ CatPrint (Str, L"I1394(%016lx)", F1394DevPath->Guid);
+}
+
+/**
+ Converts a USB device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextUsb (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ USB_DEVICE_PATH *Usb;
+
+ Usb = DevPath;
+ CatPrint (Str, L"USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
+}
+
+/**
+ Converts a USB WWID device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextUsbWWID (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ USB_WWID_DEVICE_PATH *UsbWWId;
+ CHAR16 *SerialNumberStr;
+ CHAR16 *NewStr;
+ UINT16 Length;
+
+ UsbWWId = DevPath;
+
+ SerialNumberStr = (CHAR16 *) ((UINT8 *) UsbWWId + sizeof (USB_WWID_DEVICE_PATH));
+ Length = (UINT16) ((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16));
+ if (SerialNumberStr [Length - 1] != 0) {
+ //
+ // In case no NULL terminator in SerialNumber, create a new one with NULL terminator
+ //
+ NewStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), SerialNumberStr);
+ ASSERT (NewStr != NULL);
+ NewStr [Length] = 0;
+ SerialNumberStr = NewStr;
+ }
+
+ CatPrint (
+ Str,
+ L"UsbWwid(0x%x,0x%x,0x%x,\"%s\")",
+ (UINTN) UsbWWId->VendorId,
+ (UINTN) UsbWWId->ProductId,
+ (UINTN) UsbWWId->InterfaceNumber,
+ SerialNumberStr
+ );
+}
+
+/**
+ Converts a Logic Unit device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextLogicalUnit (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
+
+ LogicalUnit = DevPath;
+ CatPrint (Str, L"Unit(0x%x)", (UINTN) LogicalUnit->Lun);
+}
+
+/**
+ Converts a USB class device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextUsbClass (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ USB_CLASS_DEVICE_PATH *UsbClass;
+ BOOLEAN IsKnownSubClass;
+
+
+ UsbClass = DevPath;
+
+ IsKnownSubClass = TRUE;
+ switch (UsbClass->DeviceClass) {
+ case USB_CLASS_AUDIO:
+ CatPrint (Str, L"UsbAudio");
+ break;
+
+ case USB_CLASS_CDCCONTROL:
+ CatPrint (Str, L"UsbCDCControl");
+ break;
+
+ case USB_CLASS_HID:
+ CatPrint (Str, L"UsbHID");
+ break;
+
+ case USB_CLASS_IMAGE:
+ CatPrint (Str, L"UsbImage");
+ break;
+
+ case USB_CLASS_PRINTER:
+ CatPrint (Str, L"UsbPrinter");
+ break;
+
+ case USB_CLASS_MASS_STORAGE:
+ CatPrint (Str, L"UsbMassStorage");
+ break;
+
+ case USB_CLASS_HUB:
+ CatPrint (Str, L"UsbHub");
+ break;
+
+ case USB_CLASS_CDCDATA:
+ CatPrint (Str, L"UsbCDCData");
+ break;
+
+ case USB_CLASS_SMART_CARD:
+ CatPrint (Str, L"UsbSmartCard");
+ break;
+
+ case USB_CLASS_VIDEO:
+ CatPrint (Str, L"UsbVideo");
+ break;
+
+ case USB_CLASS_DIAGNOSTIC:
+ CatPrint (Str, L"UsbDiagnostic");
+ break;
+
+ case USB_CLASS_WIRELESS:
+ CatPrint (Str, L"UsbWireless");
+ break;
+
+ default:
+ IsKnownSubClass = FALSE;
+ break;
+ }
+
+ if (IsKnownSubClass) {
+ CatPrint (
+ Str,
+ L"(0x%x,0x%x,0x%x,0x%x)",
+ (UINTN) UsbClass->VendorId,
+ (UINTN) UsbClass->ProductId,
+ (UINTN) UsbClass->DeviceSubClass,
+ (UINTN) UsbClass->DeviceProtocol
+ );
+ return;
+ }
+
+ if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
+ if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
+ CatPrint (
+ Str,
+ L"UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
+ (UINTN) UsbClass->VendorId,
+ (UINTN) UsbClass->ProductId,
+ (UINTN) UsbClass->DeviceProtocol
+ );
+ return;
+ } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
+ CatPrint (
+ Str,
+ L"UsbIrdaBridge(0x%x,0x%x,0x%x)",
+ (UINTN) UsbClass->VendorId,
+ (UINTN) UsbClass->ProductId,
+ (UINTN) UsbClass->DeviceProtocol
+ );
+ return;
+ } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
+ CatPrint (
+ Str,
+ L"UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
+ (UINTN) UsbClass->VendorId,
+ (UINTN) UsbClass->ProductId,
+ (UINTN) UsbClass->DeviceProtocol
+ );
+ return;
+ }
+ }
+
+ CatPrint (
+ Str,
+ L"UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
+ (UINTN) UsbClass->VendorId,
+ (UINTN) UsbClass->ProductId,
+ (UINTN) UsbClass->DeviceClass,
+ (UINTN) UsbClass->DeviceSubClass,
+ (UINTN) UsbClass->DeviceProtocol
+ );
+}
+
+/**
+ Converts a SATA device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextSata (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ SATA_DEVICE_PATH *Sata;
+
+ Sata = DevPath;
+ if ((Sata->MultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) {
+ CatPrint (
+ Str,
+ L"Sata(0x%x,0x%x)",
+ (UINTN) Sata->PortNumber,
+ (UINTN) Sata->LogicalUnitNumber
+ );
+ } else {
+ CatPrint (
+ Str,
+ L"Sata(0x%x,0x%x,0x%x)",
+ (UINTN) Sata->PortNumber,
+ (UINTN) Sata->MultiplierPortNumber,
+ (UINTN) Sata->LogicalUnitNumber
+ );
+ }
+}
+
+/**
+ Converts a I20 device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextI2O (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ I20_DEVICE_PATH *I2ODevPath;
+
+ I2ODevPath = DevPath;
+ CatPrint (Str, L"I2O(0x%x)", (UINTN) I2ODevPath->Tid);
+}
+
+/**
+ Converts a MAC address device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextMacAddr (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ MAC_ADDRESS_DEVICE_PATH *MacDevPath;
+ UINTN HwAddressSize;
+ UINTN Index;
+
+ MacDevPath = DevPath;
+
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+ if (MacDevPath->IfType == 0x01 || MacDevPath->IfType == 0x00) {
+ HwAddressSize = 6;
+ }
+
+ CatPrint (Str, L"MAC(");
+
+ for (Index = 0; Index < HwAddressSize; Index++) {
+ CatPrint (Str, L"%02x", (UINTN) MacDevPath->MacAddr.mac[Index]);
+ }
+
+ CatPrint (Str, L",0x%x)", (UINTN) MacDevPath->IfType);
+}
+
+/**
+ Converts network protocol string to its text representation.
+
+ @param Str The string representative of input device.
+ @param Protocol The network protocol ID.
+
+**/
+VOID
+CatNetworkProtocol (
+ IN OUT POOL_PRINT *Str,
+ IN UINT16 Protocol
+ )
+{
+ if (Protocol == RFC_1700_TCP_PROTOCOL) {
+ CatPrint (Str, L"TCP");
+ } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
+ CatPrint (Str, L"UDP");
+ } else {
+ CatPrint (Str, L"0x%x", Protocol);
+ }
+}
+
+/**
+ Converts a IPv4 device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextIPv4 (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ IPV4_DEVICE_PATH *IPDevPath;
+
+ IPDevPath = DevPath;
+ if (DisplayOnly) {
+ CatPrint (
+ Str,
+ L"IPv4(%d.%d.%d.%d)",
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[0],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[1],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[2],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[3]
+ );
+ return ;
+ }
+
+ CatPrint (
+ Str,
+ L"IPv4(%d.%d.%d.%d,",
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[0],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[1],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[2],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[3]
+ );
+
+ CatNetworkProtocol (
+ Str,
+ IPDevPath->Protocol
+ );
+
+ CatPrint (
+ Str,
+ L",%s,%d.%d.%d.%d",
+ IPDevPath->StaticIpAddress ? L"Static" : L"DHCP",
+ (UINTN) IPDevPath->LocalIpAddress.Addr[0],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[1],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[2],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[3]
+ );
+ if (DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)IPDevPath) == sizeof (IPV4_DEVICE_PATH)) {
+ CatPrint (
+ Str,
+ L",%d.%d.%d.%d,%d.%d.%d.%d",
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[0],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[1],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[2],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[3],
+ (UINTN) IPDevPath->SubnetMask.Addr[0],
+ (UINTN) IPDevPath->SubnetMask.Addr[1],
+ (UINTN) IPDevPath->SubnetMask.Addr[2],
+ (UINTN) IPDevPath->SubnetMask.Addr[3]
+ );
+ }
+ CatPrint (Str, L")");
+}
+
+/**
+ Converts a IPv6 device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextIPv6 (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ IPV6_DEVICE_PATH *IPDevPath;
+
+ IPDevPath = DevPath;
+ if (DisplayOnly) {
+ CatPrint (
+ Str,
+ L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[0],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[1],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[2],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[3],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[4],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[5],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[6],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[7],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[8],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[9],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[10],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[11],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[12],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[13],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[14],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[15]
+ );
+ return ;
+ }
+
+ CatPrint (
+ Str,
+ L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x,",
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[0],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[1],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[2],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[3],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[4],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[5],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[6],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[7],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[8],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[9],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[10],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[11],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[12],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[13],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[14],
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[15]
+ );
+
+ CatNetworkProtocol (
+ Str,
+ IPDevPath->Protocol
+ );
+
+ switch (IPDevPath->IpAddressOrigin) {
+ case 0:
+ CatPrint (Str, L",Static");
+ break;
+ case 1:
+ CatPrint (Str, L",StatelessAutoConfigure");
+ break;
+ default:
+ CatPrint (Str, L",StatefulAutoConfigure");
+ break;
+ }
+
+ CatPrint (
+ Str,
+ L",%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ (UINTN) IPDevPath->LocalIpAddress.Addr[0],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[1],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[2],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[3],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[4],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[5],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[6],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[7],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[8],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[9],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[10],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[11],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[12],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[13],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[14],
+ (UINTN) IPDevPath->LocalIpAddress.Addr[15]
+ );
+
+ if (DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *)IPDevPath) == sizeof (IPV6_DEVICE_PATH)) {
+ CatPrint (
+ Str,
+ L",0x%x,%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ IPDevPath->PrefixLength,
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[0],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[1],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[2],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[3],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[4],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[5],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[6],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[7],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[8],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[9],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[10],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[11],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[12],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[13],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[14],
+ (UINTN) IPDevPath->GatewayIpAddress.Addr[15]
+ );
+ }
+ CatPrint (Str, L")");
+}
+
+/**
+ Converts an Infini Band device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextInfiniBand (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ INFINIBAND_DEVICE_PATH *InfiniBand;
+
+ InfiniBand = DevPath;
+ CatPrint (
+ Str,
+ L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)",
+ (UINTN) InfiniBand->ResourceFlags,
+ InfiniBand->PortGid,
+ InfiniBand->ServiceId,
+ InfiniBand->TargetPortId,
+ InfiniBand->DeviceId
+ );
+}
+
+/**
+ Converts a UART device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextUart (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ UART_DEVICE_PATH *Uart;
+ CHAR8 Parity;
+
+ Uart = DevPath;
+ switch (Uart->Parity) {
+ case 0:
+ Parity = 'D';
+ break;
+
+ case 1:
+ Parity = 'N';
+ break;
+
+ case 2:
+ Parity = 'E';
+ break;
+
+ case 3:
+ Parity = 'O';
+ break;
+
+ case 4:
+ Parity = 'M';
+ break;
+
+ case 5:
+ Parity = 'S';
+ break;
+
+ default:
+ Parity = 'x';
+ break;
+ }
+
+ if (Uart->BaudRate == 0) {
+ CatPrint (Str, L"Uart(DEFAULT,");
+ } else {
+ CatPrint (Str, L"Uart(%ld,", Uart->BaudRate);
+ }
+
+ if (Uart->DataBits == 0) {
+ CatPrint (Str, L"DEFAULT,");
+ } else {
+ CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);
+ }
+
+ CatPrint (Str, L"%c,", Parity);
+
+ switch (Uart->StopBits) {
+ case 0:
+ CatPrint (Str, L"D)");
+ break;
+
+ case 1:
+ CatPrint (Str, L"1)");
+ break;
+
+ case 2:
+ CatPrint (Str, L"1.5)");
+ break;
+
+ case 3:
+ CatPrint (Str, L"2)");
+ break;
+
+ default:
+ CatPrint (Str, L"x)");
+ break;
+ }
+}
+
+/**
+ Converts an iSCSI device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextiSCSI (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
+ UINT16 Options;
+
+ ISCSIDevPath = DevPath;
+ CatPrint (
+ Str,
+ L"iSCSI(%a,0x%x,0x%lx,",
+ ISCSIDevPath->TargetName,
+ (UINTN) ISCSIDevPath->TargetPortalGroupTag,
+ ISCSIDevPath->Lun
+ );
+
+ Options = ISCSIDevPath->LoginOption;
+ CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");
+ CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");
+ if (((Options >> 11) & 0x0001) != 0) {
+ CatPrint (Str, L"%s,", L"None");
+ } else if (((Options >> 12) & 0x0001) != 0) {
+ CatPrint (Str, L"%s,", L"CHAP_UNI");
+ } else {
+ CatPrint (Str, L"%s,", L"CHAP_BI");
+
+ }
+
+ CatPrint (Str, L"%s)", (ISCSIDevPath->NetworkProtocol == 0) ? L"TCP" : L"reserved");
+}
+
+/**
+ Converts a VLAN device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextVlan (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ VLAN_DEVICE_PATH *Vlan;
+
+ Vlan = DevPath;
+ CatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId);
+}
+
+/**
+ Converts a Hard drive device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextHardDrive (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ HARDDRIVE_DEVICE_PATH *Hd;
+
+ Hd = DevPath;
+ switch (Hd->SignatureType) {
+ case SIGNATURE_TYPE_MBR:
+ CatPrint (
+ Str,
+ L"HD(%d,%s,0x%08x,",
+ (UINTN) Hd->PartitionNumber,
+ L"MBR",
+ (UINTN) *((UINT32 *) (&(Hd->Signature[0])))
+ );
+ break;
+
+ case SIGNATURE_TYPE_GUID:
+ CatPrint (
+ Str,
+ L"HD(%d,%s,%g,",
+ (UINTN) Hd->PartitionNumber,
+ L"GPT",
+ (EFI_GUID *) &(Hd->Signature[0])
+ );
+ break;
+
+ default:
+ CatPrint (
+ Str,
+ L"HD(%d,%d,0,",
+ (UINTN) Hd->PartitionNumber,
+ (UINTN) Hd->SignatureType
+ );
+ break;
+ }
+
+ CatPrint (Str, L"0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
+}
+
+/**
+ Converts a CDROM device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextCDROM (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ CDROM_DEVICE_PATH *Cd;
+
+ Cd = DevPath;
+ if (DisplayOnly) {
+ CatPrint (Str, L"CDROM(0x%x)", (UINTN) Cd->BootEntry);
+ return ;
+ }
+
+ CatPrint (Str, L"CDROM(0x%x,0x%lx,0x%lx)", (UINTN) Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
+}
+
+/**
+ Converts a File device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextFilePath (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ FILEPATH_DEVICE_PATH *Fp;
+
+ Fp = DevPath;
+ CatPrint (Str, L"%s", Fp->PathName);
+}
+
+/**
+ Converts a Media protocol device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextMediaProtocol (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ PROTOCOL_DEVICE_PATH *MediaProt;
+
+ MediaProt = DevPath;
+ CatPrint (Str, L"Media(%g)", &MediaProt->ProtocolGuid);
+}
+
+/**
+ Converts a Firmware Volume device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextFv (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *Fv;
+
+ Fv = DevPath;
+ CatPrint (Str, L"Fv(%g)", &Fv->NameGuid);
+}
+
+/**
+ Converts a Firmware Volume File device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextFvFile (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile;
+
+ FvFile = DevPath;
+ CatPrint (Str, L"FvFile(%g)", &FvFile->NameGuid);
+}
+
+/**
+ Converts a Relative Offset device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathRelativeOffsetRange (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
+
+ Offset = DevPath;
+ CatPrint (
+ Str,
+ L"Offset(0x%lx,0x%lx)",
+ Offset->StartingOffset,
+ Offset->EndingOffset
+ );
+}
+
+/**
+ Converts a BIOS Boot Specification device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextBBS (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ BBS_BBS_DEVICE_PATH *Bbs;
+ CHAR16 *Type;
+
+ Bbs = DevPath;
+ switch (Bbs->DeviceType) {
+ case BBS_TYPE_FLOPPY:
+ Type = L"Floppy";
+ break;
+
+ case BBS_TYPE_HARDDRIVE:
+ Type = L"HD";
+ break;
+
+ case BBS_TYPE_CDROM:
+ Type = L"CDROM";
+ break;
+
+ case BBS_TYPE_PCMCIA:
+ Type = L"PCMCIA";
+ break;
+
+ case BBS_TYPE_USB:
+ Type = L"USB";
+ break;
+
+ case BBS_TYPE_EMBEDDED_NETWORK:
+ Type = L"Network";
+ break;
+
+ default:
+ Type = NULL;
+ break;
+ }
+
+ if (Type != NULL) {
+ CatPrint (Str, L"BBS(%s,%a", Type, Bbs->String);
+ } else {
+ CatPrint (Str, L"BBS(0x%x,%a", (UINTN) Bbs->DeviceType, Bbs->String);
+ }
+
+ if (DisplayOnly) {
+ CatPrint (Str, L")");
+ return ;
+ }
+
+ CatPrint (Str, L",0x%x)", (UINTN) Bbs->StatusFlag);
+}
+
+/**
+ Converts an End-of-Device-Path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextEndInstance (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ CatPrint (Str, L",");
+}
+
+/**
+ Converts an unknown device path structure to its string representative.
+
+ @param Str The string representative of input device.
+ @param DevPath The input device path structure.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+**/
+VOID
+DevPathToTextNodeUnknown (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ CatPrint (Str, L"?");
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_TABLE DevPathToTextTable[] = {
+ {HARDWARE_DEVICE_PATH, HW_PCI_DP, DevPathToTextPci},
+ {HARDWARE_DEVICE_PATH, HW_PCCARD_DP, DevPathToTextPccard},
+ {HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, DevPathToTextMemMap},
+ {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DevPathToTextVendor},
+ {HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, DevPathToTextController},
+ {ACPI_DEVICE_PATH, ACPI_DP, DevPathToTextAcpi},
+ {ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, DevPathToTextAcpiEx},
+ {ACPI_DEVICE_PATH, ACPI_ADR_DP, DevPathToTextAcpiAdr},
+ {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, DevPathToTextAtapi},
+ {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, DevPathToTextScsi},
+ {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, DevPathToTextFibre},
+ {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP, DevPathToTextFibreEx},
+ {MESSAGING_DEVICE_PATH, MSG_SASEX_DP, DevPathToTextSasEx},
+ {MESSAGING_DEVICE_PATH, MSG_1394_DP, DevPathToText1394},
+ {MESSAGING_DEVICE_PATH, MSG_USB_DP, DevPathToTextUsb},
+ {MESSAGING_DEVICE_PATH, MSG_USB_WWID_CLASS_DP, DevPathToTextUsbWWID},
+ {MESSAGING_DEVICE_PATH, MSG_USB_LOGICAL_UNIT_CLASS_DP, DevPathToTextLogicalUnit},
+ {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, DevPathToTextUsbClass},
+ {MESSAGING_DEVICE_PATH, MSG_SATA_DP, DevPathToTextSata},
+ {MESSAGING_DEVICE_PATH, MSG_I2O_DP, DevPathToTextI2O},
+ {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, DevPathToTextMacAddr},
+ {MESSAGING_DEVICE_PATH, MSG_IPv4_DP, DevPathToTextIPv4},
+ {MESSAGING_DEVICE_PATH, MSG_IPv6_DP, DevPathToTextIPv6},
+ {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, DevPathToTextInfiniBand},
+ {MESSAGING_DEVICE_PATH, MSG_UART_DP, DevPathToTextUart},
+ {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, DevPathToTextVendor},
+ {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP, DevPathToTextiSCSI},
+ {MESSAGING_DEVICE_PATH, MSG_VLAN_DP, DevPathToTextVlan},
+ {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, DevPathToTextHardDrive},
+ {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, DevPathToTextCDROM},
+ {MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, DevPathToTextVendor},
+ {MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, DevPathToTextMediaProtocol},
+ {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath},
+ {MEDIA_DEVICE_PATH, MEDIA_FV_DP, DevPathToTextFv},
+ {MEDIA_DEVICE_PATH, MEDIA_FV_FILEPATH_DP, DevPathToTextFvFile},
+ {MEDIA_DEVICE_PATH, MEDIA_RELATIVE_OFFSET_RANGE_DP, DevPathRelativeOffsetRange},
+ {BBS_DEVICE_PATH, BBS_BBS_DP, DevPathToTextBBS},
+ {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance},
+ {0, 0, NULL}
+};
+
+/**
+ Converts a device node to its string representation.
+
+ @param DeviceNode A Pointer to the device node to be converted.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+ @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
+ is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+ConvertDeviceNodeToText (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ POOL_PRINT Str;
+ UINTN Index;
+ UINTN NewSize;
+ VOID (*DumpNode)(POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
+
+ if (DeviceNode == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (&Str, sizeof (Str));
+
+ //
+ // Process the device path node
+ //
+ DumpNode = NULL;
+ for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index++) {
+ if (DevicePathType (DeviceNode) == DevPathToTextTable[Index].Type &&
+ DevicePathSubType (DeviceNode) == DevPathToTextTable[Index].SubType
+ ) {
+ DumpNode = DevPathToTextTable[Index].Function;
+ break;
+ }
+ }
+ //
+ // If not found, use a generic function
+ //
+ if (DumpNode == NULL) {
+ DumpNode = DevPathToTextNodeUnknown;
+ }
+
+ //
+ // Print this node
+ //
+ DumpNode (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts);
+
+ //
+ // Shrink pool used for string allocation
+ //
+ NewSize = (Str.Len + 1) * sizeof (CHAR16);
+ Str.Str = ReallocatePool (NewSize, NewSize, Str.Str);
+ ASSERT (Str.Str != NULL);
+ Str.Str[Str.Len] = 0;
+ return Str.Str;
+}
+
+/**
+ Converts a device path to its text representation.
+
+ @param DevicePath A Pointer to the device to be converted.
+ @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
+ of the display node is used, where applicable. If DisplayOnly
+ is FALSE, then the longer text representation of the display node
+ is used.
+ @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
+ representation for a device node can be used, where applicable.
+
+ @return A pointer to the allocated text representation of the device path or
+ NULL if DeviceNode is NULL or there was insufficient memory.
+
+**/
+CHAR16 *
+EFIAPI
+ConvertDevicePathToText (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN BOOLEAN DisplayOnly,
+ IN BOOLEAN AllowShortcuts
+ )
+{
+ POOL_PRINT Str;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *AlignedDevPathNode;
+ UINTN Index;
+ UINTN NewSize;
+ VOID (*DumpNode) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
+
+ if (DevicePath == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (&Str, sizeof (Str));
+
+ //
+ // Process each device path node
+ //
+ DevPathNode = (EFI_DEVICE_PATH_PROTOCOL *) DevicePath;
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Find the handler to dump this device path node
+ //
+ DumpNode = NULL;
+ for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index += 1) {
+
+ if (DevicePathType (DevPathNode) == DevPathToTextTable[Index].Type &&
+ DevicePathSubType (DevPathNode) == DevPathToTextTable[Index].SubType
+ ) {
+ DumpNode = DevPathToTextTable[Index].Function;
+ break;
+ }
+ }
+ //
+ // If not found, use a generic function
+ //
+ if (!DumpNode) {
+ DumpNode = DevPathToTextNodeUnknown;
+ }
+ //
+ // Put a path separator in if needed
+ //
+ if ((Str.Len != 0) && DumpNode != DevPathToTextEndInstance) {
+ if (*(Str.Str + Str.Len / sizeof (CHAR16) - 1) != L',') {
+ CatPrint (&Str, L"/");
+ }
+ }
+
+ AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (DevPathNode), DevPathNode);
+ //
+ // Print this node of the device path
+ //
+ DumpNode (&Str, AlignedDevPathNode, DisplayOnly, AllowShortcuts);
+ FreePool (AlignedDevPathNode);
+
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+
+ NewSize = (Str.Len + 1) * sizeof (CHAR16);
+ Str.Str = ReallocatePool (NewSize, NewSize, Str.Str);
+ ASSERT (Str.Str != NULL);
+ Str.Str[Str.Len] = 0;
+ return Str.Str;
+}
+
+EFI_DEVICE_PATH_TO_TEXT_PROTOCOL EfiDevicePathToTextProtocol = {
+ ConvertDeviceNodeToText,
+ ConvertDevicePathToText
+}; \ No newline at end of file
diff --git a/Core/CORE_DXE/DiskIo.c b/Core/CORE_DXE/DiskIo.c
new file mode 100644
index 0000000..a9476cd
--- /dev/null
+++ b/Core/CORE_DXE/DiskIo.c
@@ -0,0 +1,978 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*****************************************************************************
+// $Header: /Alaska/SOURCE/Core/EDK/DxeMain/DiskIo.c 27 8/12/11 12:23p Artems $
+//
+// $Revision: 27 $
+//
+// $Date: 8/12/11 12:23p $
+//*****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/EDK/DxeMain/DiskIo.c $
+//
+// 27 8/12/11 12:23p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 26 2/05/11 4:10p Artems
+// Removed previous check-in changes
+//
+// 25 1/06/11 5:52p Oleksiyy
+// [TAG] EIP28607
+// [Category] Improvement
+// [Description] System was hanging for some time if Floppy Media
+// removed while writing in meda in progress.
+// EFI_TPL_CALLBACK priority level rised during media related calls.
+// [Files] DiskIo.c, Info.c, MediaAccess.c, Open.c, Partition.c
+//
+// 24 8/27/09 5:21p Felixp
+//
+// 23 8/27/09 4:40p Felixp
+//
+// 20 8/21/09 4:29p Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 19 7/08/09 5:54p Vyacheslava
+// Updated according to the coding standards.
+//
+// 18 4/24/07 4:10p Robert
+// Updated headers to be compliant with the CHM Help Builder
+//
+// 17 4/19/07 12:57p Felixp
+// Minor bug fix in handling of media not present in ReadDiskIo (along
+// with IdeBus.c changes resolves SCT failure)
+//
+// 15 4/16/07 6:29p Felixp
+// Fix: proper handling of media not present in ReadDiskIo
+//
+// 14 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 11 10/28/05 9:03p Felixp
+// bug fix in CalcAlignmentValues
+//
+// 10 10/28/05 2:03p Felixp
+// bug fix in WriteDiskIo for the case when AboveAlign is not zero.
+//
+
+// 5 2/14/05 4:10p Felixp
+// Small bug fix in ReadDiskIo (success returned in case of error)
+//
+// 4 2/11/05 6:09p Felixp
+// - optimizations (both code size and speed)
+// - SCT failure fixed
+//
+// 2 2/07/05 6:05p Felixp
+// Small bug fix in ReadDiskIo and WriteDiskIo
+//
+//*****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Disko.c
+//
+// Description: EFI Disk Io Generic Driver.
+//
+//<AMI_FHDR_END>
+//*****************************************************************************
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <AmiDxeLib.h>
+
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+//----------------------------------------------------------------------------
+// Function Prototypes
+EFI_STATUS EFIAPI DiskIoSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+);
+
+EFI_STATUS EFIAPI DiskIoStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+);
+
+EFI_STATUS EFIAPI DiskIoStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+);
+
+EFI_STATUS ReadDiskIo (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+);
+
+EFI_STATUS WriteDiskIo (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+);
+
+//----------------------------------------------------------------------------
+// Data types
+typedef struct _DISK_IO_DATA {
+ EFI_DISK_IO_PROTOCOL DiskIo;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+} DISK_IO_DATA;
+
+//----------------------------------------------------------------------------
+// GUID Definitions
+static EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+static EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID;
+static EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+
+//----------------------------------------------------------------------------
+// Module Scope Glo=bal Variables
+
+EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBindingProtocol = {
+ DiskIoSupported,
+ DiskIoStart,
+ DiskIoStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+DISK_IO_DATA gDiskIoData = {
+ {
+ EFI_DISK_IO_PROTOCOL_REVISION,
+ ReadDiskIo,
+ WriteDiskIo
+ },
+ NULL
+};
+
+static EFI_BOOT_SERVICES *gBS = NULL;
+
+//----------------------------------------------------------------------------
+//Driver Name
+
+#ifdef EFI_DEBUG
+static UINT16 *gDriverName = L"AMI Disk I/O Driver";
+
+//----------------------------------------------------------------------------
+// Function Definitions
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+//
+// Procedure: ComponentNameGetControllerName
+//
+// DESCRIPTION: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// Input:
+// 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 Supported Languages. The number of languages supported by a
+// driver is up to the driver writer.
+//
+// Output:
+// 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 thedriver 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.
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: ComponentNameGetDriverName
+//
+// Description: Returns the Driver Name if the language is supported
+//
+// Input:
+// This - Pointer to the instance of this driver
+// Language - Current operating language
+// DriverName - return parameter that will contain the Driver's Name
+//
+// Output: DriverName - return parameter that will contain the Driver's Name
+//
+// Returns:
+// EFI_SUCCESS - Driver loaded
+// EFI_INVALID_PARAMETER - If the Language or DriverName variable is
+// not defined
+// EFI_UNSUPPORTED - If the current laungage is not supported
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS ComponentNameGetDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName )
+{
+ //Supports only English
+ if (!Language || !DriverName)
+ return EFI_INVALID_PARAMETER;
+
+ if ( !LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH) )
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName = gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+//Component Name Protocol
+static EFI_COMPONENT_NAME2_PROTOCOL gComponentName = {
+ ComponentNameGetDriverName,
+ ComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DiskIoEntryPoint
+//
+// Description: Installs the Driver Binding Protocol for the Disk
+// I/O Driver
+//
+// Input:
+// ImageHandle - Identification Handle for the Disk I/O driver
+// *SystemTable - Pointer to the EFI System Handle
+//
+// Output:
+// EFI_SUCCESS - if the Binding Protocol is installed
+//
+//
+// Modified:
+//
+// Referrals: InstallMultipleProtocolInterfaces
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Initialize Ami Lib.
+// 2. Install Driver Binding Protocol
+// 3. Return EFI_SUCCESS.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DiskIoEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ // Initialize global variable for use in this driver
+ gBS = SystemTable->BootServices;
+
+ // initiaize the ImageHandle and DriverBindingHandle
+ gDiskIoDriverBindingProtocol.DriverBindingHandle = NULL;
+ gDiskIoDriverBindingProtocol.ImageHandle = ImageHandle;
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &gDiskIoDriverBindingProtocol.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDiskIoDriverBindingProtocol,
+#ifdef EFI_DEBUG
+ &gEfiComponentName2ProtocolGuid,
+ &gComponentName,
+#endif
+ NULL
+ );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DiskIoSupported
+//
+// Description: Checks whether Block I/O protocol is installed on the
+// Controller
+//
+// Input:
+// *This - pointer to the Briver Binding instance of the
+// Disk I/O Protocol
+// Controller - The Controller that is looking for drivers that
+// operate on it
+// *RemainingDevicePath -
+//
+// Output:
+// EFI_SUCCESS - Driver supports the Controller that is passed in
+// EFI_UNSUPPORTED - The Driver Does not support the Controller
+// that is passed in
+//
+// Referrals: OpenProtocol CloseProtocol
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Check whether Block I/O driver is installed and not being used
+// by another driver
+// 2. Return EFI_SUCCESS or EFI_UNSUPPORTED
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI DiskIoSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+
+ // Check to see if the BlockIo Protocol in installed on the ControllerHandle
+ // if so, CloseProtocol and return success, otherwise exit with an error
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**)&BlockIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR(Status))
+ return Status;
+
+ return gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DiskIoStart
+//
+// Description: Installs DiskIo Protocol on the Controller
+//
+// Input:
+// *This - Pointer to an instance of the Disk I/O protocol
+// Controller - The controller being operated on
+// *RemainingDevicePath -
+//
+// Output:
+// EFI_SUCCESS - if Driver was installed properly
+// Errors - Returns any error that would cause the protocol not
+// to be installed
+//
+// Referrals: OpenProtocol CloseProtocol InstallProtocolInterface
+// AllocatePool CopyMem FreePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Open the Block I/O protocol BY_DRIVER
+// 2. Allocate memory for the new instance of the Disk I/O Data Structure
+// 3. Copy the Default Data into the newly allocated memory
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI DiskIoStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_STATUS Status;
+ DISK_IO_DATA *DiskIo;
+
+ // make sure that the controller handle has the BlockIo Protocol installed on it
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID**)&gDiskIoData.BlockIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ // If not error out
+ if (EFI_ERROR (Status))
+ return Status;
+
+ // Allocate memory for the private data structure for the instance of the driver
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(DISK_IO_DATA),
+ &DiskIo
+ );
+
+ // if no memory is available, exit with error
+ if (EFI_ERROR(Status))
+ return Status;
+
+ // copy the corrct data into it
+ gBS->CopyMem(
+ DiskIo,
+ &gDiskIoData,
+ sizeof(DISK_IO_DATA)
+ );
+
+ // Install the Protocol on the handle if it has a BlockIo Protocol alread installed
+ Status = gBS->InstallProtocolInterface(
+ &ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &DiskIo->DiskIo
+ );
+
+ // If there is an error when installing the protocol, reverse everything that was done
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool(DiskIo);
+ gBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DiskIoStop
+//
+// Description: Uninstalls DiskIo Protocol on the Controller
+//
+// Input:
+// *This - Pointer to an instance of the Disk I/O protocol
+// Controller - The controller being operated on
+// *RemainingDevicePath -
+//
+// Output:
+// EFI_SUCCESS - if Driver was Uninstalled properly
+// EFI_UNSUPPORTED - Disk I/O was not installed on the Controller
+// Errors - Returns any error that would cause the protocol not
+// to be installed
+//
+// Referrals: OpenProtocol CloseProtocol UnInstallProtocolInterface
+// FreePool
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Open the Disk I/O protocol by GET_DERIVER
+// 2. Uninstall the protocol
+// 3. Free the allocated Memory
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS EFIAPI DiskIoStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+)
+{
+ EFI_STATUS Status;
+ EFI_DISK_IO_PROTOCOL *DiskIoProtocol;
+ DISK_IO_DATA *DiskIo;
+
+ // Unistall all protocols installed installed in DriverBindingStart
+ // open the disk Io protocol
+ Status = gBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID**)&DiskIoProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status))
+ return EFI_UNSUPPORTED;
+
+ // Find the pointer to the parent structure
+ // in this case, DiskIo is the first element in the data structure
+ DiskIo = (DISK_IO_DATA*)DiskIoProtocol;
+
+ // Uninstall the protocol interface
+ Status = gBS->UninstallProtocolInterface(
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid,
+ &DiskIo->DiskIo
+ );
+
+ // if the interface is uninstalled then close the protocol
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ }
+
+ // if the protocol is closed, then free the data structure
+ if (!EFI_ERROR (Status))
+ Status = gBS->FreePool(DiskIo);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: CalcAlignmentValues
+//
+// Description: Calculates FirstBlock, Numblocks, and the amount
+// of data above and below an alignment value
+//
+// Input:
+// *Media - pointer to the media data structure that is being
+// operated on
+// Offset - byte value that is the offset into the media that
+// indicates where the buffer starts
+// BufferSize - Size of the entire buffer to read
+//
+// Output:
+// *BelowAlign - Number of bytes below an aligned value where
+// the Buffer starts
+// *AboveAlign - Number of bytes above an aligned value where
+// the Buffer ends
+// *FirstBlock - First block that needs to be read to get the
+// entire buffer
+// *NumBlocks - number of blocks to be read
+//
+// Return: VOID
+//
+// Referrals: Div64
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Calculate the first block of the media to read
+// 2. calculate the number of blocks to read
+// 3. Check for any data area that is ablove the final aligned block
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID CalcAlignmentValues(
+ IN EFI_BLOCK_IO_MEDIA *Media,
+ IN UINT64 Offset,
+ IN UINT64 BufferSize,
+ OUT UINTN *BelowAlign,
+ OUT UINTN *AboveAlign,
+ OUT UINT64 *FirstBlock,
+ OUT UINT64 *NumBlocks
+)
+{
+ UINT64 Temp;
+
+ // Find out if the Offset is aligned and the remainder if it is not
+ // use 64 bit division function
+ *FirstBlock = Div64(
+ Offset,
+ Media->BlockSize,
+ BelowAlign
+ );
+
+ // Find out if the ending point is aligned and the remainder if it is not
+ // use 64 bit division function
+ Temp = Div64(
+ Offset + BufferSize,
+ Media->BlockSize,
+ AboveAlign
+ );
+
+ // Calculate the total number of blocks to be read/written
+ *NumBlocks = Temp - *FirstBlock;
+
+ if (*AboveAlign)
+ (*NumBlocks)++;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadDiskIo
+//
+// Description: Reads the data from the media specified by the parameters
+// that are passed in
+//
+// Input:
+// *This - Pointer to the Disk I/O protocol instance
+// MediaId - media ID of the device to read from
+// Offset - byte offset where to start reading
+// BufferSize - amount of data to read
+//
+// Output:
+// *Buffer - location to store the data read from the media
+//
+// Return:
+// EFI_SUCCESS - Function Read the Buffer properly or BufferSize = 0
+// EFI_MEDIA_CHANGED - Media changed since last operation
+// EFI_INVALID_PARAMETER - Buffer does not fit within the Media
+//
+// Referrals: Mul64 AllocatePool CalcAlignmentValues CopyMem
+// FreePool BlockIo->ReadBlock
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS ReadDiskIo (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+)
+{
+ DISK_IO_DATA *Container;
+ UINT64 StartBlock = 0;
+ UINT64 NumBlocks = 0;
+ UINTN BelowAlign = 0;
+ UINTN AboveAlign = 0;
+ UINT32 IoAlign;
+ UINTN Temp;
+ UINT8 *DataBuffer, *AlignDataBuffer;
+ UINT32 BlockSize;
+ EFI_STATUS Status;
+
+ // Get the pointer to the Container Structure
+ // DiskIo is the first element of the Data Structure
+ // also define some variables for easier access
+ Container = (DISK_IO_DATA*)This;
+ BlockSize = Container->BlockIo->Media->BlockSize;
+ IoAlign = Container->BlockIo->Media->IoAlign;
+
+ // Error Check values here
+ if (Container->BlockIo->Media->MediaPresent) {
+ if (Container->BlockIo->Media->MediaId != MediaId)
+ return EFI_MEDIA_CHANGED;
+
+ if ( Offset + BufferSize > Mul64(Container->BlockIo->Media->LastBlock + 1, BlockSize) )
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!BufferSize)
+ return EFI_SUCCESS;
+
+ if (!BlockSize)
+ return EFI_INVALID_PARAMETER;
+
+ // find the needed data
+ CalcAlignmentValues(
+ Container->BlockIo->Media,
+ Offset,
+ BufferSize,
+ &BelowAlign,
+ &AboveAlign,
+ &StartBlock,
+ &NumBlocks
+ );
+
+ // Allocate a buffer for use in pulling data out of selected blocks
+ // Size is generated by total number of blocks to be read plus the IoAlignment
+ // value so that the buffer will have plenty of space in it if needed
+ Temp = BlockSize * (UINTN)NumBlocks;
+
+ if ( Temp>BufferSize || IoAlign && ( (UINTN)Buffer & (IoAlign - 1) ) ) {
+ if (IoAlign > 1)
+ Temp += IoAlign;
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ Temp,
+ &DataBuffer
+ );
+
+ // No buffer allocated: exit, no need to free the memory
+ if (Status != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ AlignDataBuffer = (IoAlign <= 1) ?
+ DataBuffer : DataBuffer + IoAlign - ( (UINTN)DataBuffer & (IoAlign - 1) );
+
+ } else
+ AlignDataBuffer = Buffer;
+
+ Status = Container->BlockIo->ReadBlocks(
+ Container->BlockIo,
+ MediaId,
+ StartBlock,
+ BlockSize * (UINTN)NumBlocks,
+ AlignDataBuffer
+ );
+
+ if (AlignDataBuffer != Buffer) {
+ gBS->CopyMem(
+ Buffer,
+ AlignDataBuffer + BelowAlign,
+ BufferSize
+ );
+ gBS->FreePool(DataBuffer);
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: WriteDiskIo
+//
+// Description: Writes the data to the media specified by the parameters
+// that are passed in
+//
+// Input:
+// *This - Pointer to the Disk I/O protocol instance
+// MediaId - media ID of the device to write to
+// Offset - byte offset where to start wrtiing
+// BufferSize - amount of data to write
+//
+// Output:
+// *Buffer - location of data that should be written to the media
+//
+// Return:
+// EFI_SUCCESS - Function wrote the Buffer properly or BufferSize = 0
+// EFI_MEDIA_CHANGED - Media changed since last operation
+// EFI_INVALID_PARAMETER - Buffer does not fit within the Media
+//
+// Referrals: Mul64 AllocatePool CalcAlignmentValues CopyMem
+// FreePool BlockIo->ReadBlocks BlockIo->WriteBlocks
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS WriteDiskIo (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+)
+{
+ DISK_IO_DATA *Container;
+ UINT64 StartBlock = 0;
+ UINT64 NumBlocks = 0;
+ UINTN BelowAlign = 0;
+ UINTN AboveAlign = 0;
+ UINTN IoAlign;
+ UINT8 *DataBuffer, *AlignDataBuffer;
+ UINT32 BlockSize;
+ EFI_STATUS Status;
+ UINTN Temp;
+
+ // Get the pointer to the Container Structure
+ // DiskIo is the first element of the Data Structure
+ // also define some variables for easier access
+ Container = (DISK_IO_DATA*)This;
+ BlockSize = Container->BlockIo->Media->BlockSize;
+ IoAlign = Container->BlockIo->Media->IoAlign;
+
+ // Error Check values here
+ if (Container->BlockIo->Media->MediaId != MediaId)
+ return EFI_MEDIA_CHANGED;
+
+ if ( Offset + BufferSize > Mul64(Container->BlockIo->Media->LastBlock + 1, BlockSize) )
+ return EFI_INVALID_PARAMETER;
+
+ if (!BufferSize)
+ return EFI_SUCCESS;
+
+ // find the needed data
+ CalcAlignmentValues(
+ Container->BlockIo->Media,
+ Offset,
+ BufferSize,
+ &BelowAlign,
+ &AboveAlign,
+ &StartBlock,
+ &NumBlocks
+ );
+
+ // Allocate a buffer for use in pulling data out of selected blocks
+ // Size is generated by total number of blocks to be read plus the IoAlignment
+ // value so that the buffer will have plenty of space in it if needed
+ Temp = BlockSize * (UINTN)NumBlocks;
+
+ if ( Temp>BufferSize || IoAlign && ( (UINTN)Buffer & (IoAlign - 1) ) ) {
+ if (IoAlign > 1)
+ Temp += IoAlign;
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ Temp,
+ &DataBuffer
+ );
+
+ // No buffer allocated: exit, no need to free the memory
+ if (Status != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ AlignDataBuffer = (IoAlign <= 1) ?
+ DataBuffer : DataBuffer + IoAlign - ( (UINTN)DataBuffer & (IoAlign - 1) );
+
+ } else {
+
+ Status = Container->BlockIo->WriteBlocks(
+ Container->BlockIo,
+ MediaId,
+ StartBlock,
+ BufferSize,
+ Buffer
+ );
+ return Status;
+ }
+
+ if ( AboveAlign && (NumBlocks > 1 || !BelowAlign) ) {
+ // Read the block that contains the data at the beginning of the block
+ Status = Container->BlockIo->ReadBlocks(
+ Container->BlockIo,
+ MediaId,
+ StartBlock + NumBlocks - 1,
+ BlockSize,
+ AlignDataBuffer
+ );
+
+ // Check to see if the BlockIo protocol reported an error
+ if (Status != EFI_SUCCESS) {
+ gBS->FreePool(DataBuffer);
+ return Status;
+ }
+
+ // just copy the data above the alignment address, not the complete block
+ gBS->CopyMem(
+ AlignDataBuffer + (UINTN)(NumBlocks - 1) * BlockSize + AboveAlign,
+ AlignDataBuffer + AboveAlign,
+ BlockSize - AboveAlign
+ );
+ }
+
+ // see if we need to only pull the data from the end of a block
+ if (BelowAlign) {
+ // read the block that contains the data at the end of the block
+ // Advance StartBlock to the next block after reading the current block
+ Status = Container->BlockIo->ReadBlocks(
+ Container->BlockIo,
+ MediaId,
+ StartBlock,
+ BlockSize,
+ AlignDataBuffer
+ );
+
+
+ // Check to see if the BlockIo protocol reported an error
+ if (Status != EFI_SUCCESS) {
+ gBS->FreePool(DataBuffer);
+ return Status;
+ }
+ }
+
+ // Copy that data to allocated memory
+ gBS->CopyMem(
+ AlignDataBuffer + BelowAlign,
+ Buffer,
+ BufferSize
+ );
+
+ // Write full blocks of data from the block I/O driver
+ Status = Container->BlockIo->WriteBlocks(
+ Container->BlockIo,
+ MediaId,
+ StartBlock,
+ (UINTN)NumBlocks * BlockSize,
+ AlignDataBuffer
+ );
+
+ // Free allocated memory
+ gBS->FreePool(DataBuffer);
+ return Status;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/CORE_DXE/Dispatcher.c b/Core/CORE_DXE/Dispatcher.c
new file mode 100644
index 0000000..751a9dd
--- /dev/null
+++ b/Core/CORE_DXE/Dispatcher.c
@@ -0,0 +1,1351 @@
+/*++
+
+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:
+
+ Dispatcher.c
+
+Abstract:
+
+ Tiano DXE Dispatcher.
+
+ Step #1 - When a FV protocol is added to the system every driver in the FV
+ is added to the mDiscoveredList. The SOR, Before, and After Depex are
+ pre-processed as drivers are added to the mDiscoveredList. If an Apriori
+ file exists in the FV those drivers are addeded to the
+ mScheduledQueue. The mFvHandleList is used to make sure a
+ FV is only processed once.
+
+ Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and
+ start it. After mScheduledQueue is drained check the
+ mDiscoveredList to see if any item has a Depex that is ready to
+ be placed on the mScheduledQueue.
+
+ Step #3 - Adding to the mScheduledQueue requires that you process Before
+ and After dependencies. This is done recursively as the call to add
+ to the mScheduledQueue checks for Before and recursively adds
+ all Befores. It then addes the item that was passed in and then
+ processess the After dependecies by recursively calling the routine.
+
+ Dispatcher Rules:
+ The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3
+ is the state diagram for the DXE dispatcher
+
+ Depex - Dependency Expresion.
+ SOR - Schedule On Request - Don't schedule if this bit is set.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "FwVolBlock.h"
+#include EFI_GUID_DEFINITION (Apriori)
+
+//
+// The Driver List contains one copy of every driver that has been discovered.
+// Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY
+//
+EFI_LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList);
+
+//
+// Queue of drivers that are ready to dispatch. This queue is a subset of the
+// mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY.
+//
+EFI_LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
+
+//
+// List of handles who's Fv's have been parsed and added to the mFwDriverList.
+//
+EFI_LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE
+
+//
+// Lock for mDiscoveredList, mScheduledQueue, mDispatcherRunning.
+//
+EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+
+
+//
+// Flag for the DXE Dispacher. TRUE if dispatcher is execuing.
+//
+BOOLEAN mDispatcherRunning = FALSE;
+
+//
+// Module globals to manage the FwVol registration notification event
+//
+EFI_EVENT mFwVolEvent;
+VOID *mFwVolEventRegistration;
+
+//
+// List of file types supported by dispatcher
+//
+static EFI_FV_FILETYPE mDxeFileTypes[] = {
+ EFI_FV_FILETYPE_DRIVER,
+ EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
+ EFI_FV_FILETYPE_DXE_CORE,
+ EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
+//*** AMI PORTING BEGIN ***//
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+ ,EFI_FV_FILETYPE_COMBINED_SMM_DXE
+#endif
+//*** AMI PORTING END *****//
+};
+
+typedef struct {
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FV_FILEPATH_DEVICE_PATH;
+
+FV_FILEPATH_DEVICE_PATH mFvDevicePath;
+//
+// Function Prototypes
+//
+VOID
+CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
+ IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
+ );
+
+VOID
+EFIAPI
+CoreFwVolEventProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreFvToDevicePath (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+STATIC
+EFI_STATUS
+CoreAddToDriverList (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+STATIC
+EFI_STATUS
+CoreProcessFvImageFile (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ );
+
+
+VOID
+CoreAcquireDispatcherLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on mDispatcherLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+{
+ CoreAcquireLock (&mDispatcherLock);
+}
+
+VOID
+CoreReleaseDispatcherLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on mDispatcherLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&mDispatcherLock);
+}
+
+
+EFI_STATUS
+CoreGetDepexSectionAndPreProccess (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Read Depex and pre-process the Depex for Before and After. If Section Extraction
+ protocol returns an error via ReadSection defer the reading of the Depex.
+
+Arguments:
+
+ DriverEntry - Driver to work on.
+
+Returns:
+
+ EFI_SUCCESS - Depex read and preprossesed
+
+ EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and
+ Depex reading needs to be retried.
+
+ Other Error - DEPEX not found.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+
+ Fv = DriverEntry->Fv;
+
+ //
+ // Grab Depex info, it will never be free'ed.
+ //
+ SectionType = EFI_SECTION_DXE_DEPEX;
+ Status = Fv->ReadSection (
+ DriverEntry->Fv,
+ &DriverEntry->FileName,
+ SectionType,
+ 0,
+ &DriverEntry->Depex,
+ (UINTN *)&DriverEntry->DepexSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_PROTOCOL_ERROR) {
+ //
+ // The section extraction protocol failed so set protocol error flag
+ //
+ DriverEntry->DepexProtocolError = TRUE;
+ } else {
+ //
+ // If no Depex assume EFI 1.1 driver model
+ //
+ DriverEntry->Depex = NULL;
+ DriverEntry->Dependent = TRUE;
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+ } else {
+ //
+ // Set Before, After, and Unrequested state information based on Depex
+ // Driver will be put in Dependent or Unrequested state
+ //
+ CorePreProcessDepex (DriverEntry);
+ DriverEntry->DepexProtocolError = FALSE;
+ }
+
+ return Status;
+}
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreSchedule (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Check every driver and locate a matching one. If the driver is found, the Unrequested
+ state flag is cleared.
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Dependent state.
+
+Returns:
+
+ EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
+
+ EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Check every driver
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
+ DriverEntry->Unrequested &&
+ EfiCompareGuid (DriverName, &DriverEntry->FileName)) {
+ //
+ // Move the driver from the Unrequested to the Dependent state
+ //
+ CoreAcquireDispatcherLock ();
+ DriverEntry->Unrequested = FALSE;
+ DriverEntry->Dependent = TRUE;
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreTrust (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert a driver from the Untrused back to the Scheduled state
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Scheduled state
+
+Returns:
+
+ EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
+ to the trusted state.
+
+ EFI_NOT_FOUND - The file was not found in the untrusted state.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Check every driver
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->FvHandle == FirmwareVolumeHandle &&
+ DriverEntry->Untrusted &&
+ EfiCompareGuid (DriverName, &DriverEntry->FileName)) {
+ //
+ // Transition driver from Untrusted to Scheduled state.
+ //
+ CoreAcquireDispatcherLock ();
+ DriverEntry->Untrusted = FALSE;
+ DriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+/**
+ An empty function to pass error checking of CreateEventEx ().
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+EmptyFuntion (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ return;
+}
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This is the main Dispatcher for DXE and it exits when there are no more
+ drivers to run. Drain the mScheduledQueue and load and start a PE
+ image for each driver. Search the mDiscoveredList to see if any driver can
+ be placed on the mScheduledQueue. If no drivers are placed on the
+ mScheduledQueue exit the function. On exit it is assumed the Bds()
+ will be called, and when the Bds() exits the Dispatcher will be called
+ again.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ EFI_ALREADY_STARTED - The DXE Dispatcher is already running
+
+ EFI_NOT_FOUND - No DXE Drivers were dispatched
+
+ EFI_SUCCESS - One or more DXE Drivers were dispatched
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+ BOOLEAN ReadyToRun;
+ UINT8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+ EFI_STATUS_CODE_DATA *StatusCodeData;
+ EFI_DEVICE_HANDLE_EXTENDED_DATA *DeviceHandleExtData;
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+ EFI_EVENT DxeDispatchEvent;
+//---------------------------------------
+
+ Status = CoreCreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ EmptyFuntion,
+ NULL,
+ &gEfiEventDxeDispatchGuid,
+ &DxeDispatchEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+
+ DeviceHandleExtData = (EFI_DEVICE_HANDLE_EXTENDED_DATA *) Buffer;
+ StatusCodeData = (EFI_STATUS_CODE_DATA *) Buffer;
+ DeviceHandleExtData->DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
+ DeviceHandleExtData->DataHeader.Size =
+ sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) -
+ sizeof (EFI_STATUS_CODE_DATA);
+
+ EfiCommonLibCopyMem (
+ &DeviceHandleExtData->DataHeader.Type,
+ &gEfiStatusCodeSpecificDataGuid,
+ sizeof (EFI_GUID)
+ );
+
+ if (mDispatcherRunning) {
+ //
+ // If the dispatcher is running don't let it be restarted.
+ //
+ return EFI_ALREADY_STARTED;
+ }
+
+ mDispatcherRunning = TRUE;
+
+
+ ReturnStatus = EFI_NOT_FOUND;
+ do {
+ //
+ // Drain the Scheduled Queue
+ //
+ while (!IsListEmpty (&mScheduledQueue)) {
+ DriverEntry = CR (
+ mScheduledQueue.ForwardLink,
+ EFI_CORE_DRIVER_ENTRY,
+ ScheduledLink,
+ EFI_CORE_DRIVER_ENTRY_SIGNATURE
+ );
+
+ //
+ // Load the DXE Driver image into memory. If the Driver was transitioned from
+ // Untrused to Scheduled it would have already been loaded so we may need to
+ // skip the LoadImage
+ //
+ if (DriverEntry->ImageHandle == NULL) {
+ Status = CoreLoadImage (
+ FALSE,
+ gDxeCoreImageHandle,
+ DriverEntry->FvFileDevicePath,
+ NULL,
+ 0,
+ &DriverEntry->ImageHandle
+ );
+
+ //
+ // Update the driver state to reflect that it's been loaded
+ //
+ if (EFI_ERROR (Status)) {
+ CoreAcquireDispatcherLock ();
+
+ if (Status == EFI_SECURITY_VIOLATION) {
+ //
+ // Take driver from Scheduled to Untrused state
+ //
+ DriverEntry->Untrusted = TRUE;
+ } else {
+ //
+ // The DXE Driver could not be loaded, and do not attempt to load or start it again.
+ // Take driver from Scheduled to Initialized.
+ //
+ // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
+ //
+ DriverEntry->Initialized = TRUE;
+ }
+
+ DriverEntry->Scheduled = FALSE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // If it's an error don't try the StartImage
+ //
+ continue;
+ }
+ }
+
+ CoreAcquireDispatcherLock ();
+
+ DriverEntry->Scheduled = FALSE;
+ DriverEntry->Initialized = TRUE;
+ RemoveEntryList (&DriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // Report Status Code here to notify drivers has
+ // been initialized (INIT_BEGIN)
+ //
+ EfiCommonLibCopyMem (
+ &DeviceHandleExtData->Handle,
+ &DriverEntry->ImageHandle,
+ sizeof (EFI_HANDLE)
+ );
+
+ CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle);
+
+ Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);
+
+ CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle);
+
+ ReturnStatus = EFI_SUCCESS;
+ }
+
+ //
+ // Search DriverList for items to place on Scheduled Queue
+ //
+ ReadyToRun = FALSE;
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+
+ if (DriverEntry->DepexProtocolError){
+ //
+ // If Section Extraction Protocol did not let the Depex be read before retry the read
+ //
+ Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
+ }
+
+ if (DriverEntry->Dependent) {
+ if (CoreIsSchedulable (DriverEntry)) {
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ ReadyToRun = TRUE;
+ }
+ }
+ }
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+ //
+ // Now DXE Dispatcher finished one round of dispatch, signal an event group
+ // so that SMM Dispatcher get chance to dispatch SMM Drivers which depend
+ // on UEFI protocols
+ //
+ if (!EFI_ERROR (ReturnStatus)) {
+ CoreSignalEvent (DxeDispatchEvent);
+ }
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+ } while (ReadyToRun);
+
+ mDispatcherRunning = FALSE;
+
+ return ReturnStatus;
+}
+
+
+VOID
+CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
+ IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
+ must add any driver with a before dependency on InsertedDriverEntry first.
+ You do this by recursively calling this routine. After all the Befores are
+ processed you can add InsertedDriverEntry to the mScheduledQueue.
+ Then you can add any driver with an After dependency on InsertedDriverEntry
+ by recursively calling this routine.
+
+Arguments:
+
+ InsertedDriverEntry - The driver to insert on the ScheduledLink Queue
+
+Returns:
+
+ NONE
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ //
+ // Process Before Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Before && DriverEntry->Dependent) {
+ if (EfiCompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process BEFORE
+ //
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+
+ //
+ // Convert driver from Dependent to Scheduled state
+ //
+ CoreAcquireDispatcherLock ();
+
+ InsertedDriverEntry->Dependent = FALSE;
+ InsertedDriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // Process After Dependency
+ //
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->After && DriverEntry->Dependent) {
+ if (EfiCompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
+ //
+ // Recursively process AFTER
+ //
+ CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
+ }
+ }
+ }
+}
+
+#if (PI_SPECIFICATION_VERSION >= 0x00010000)
+EFI_STATUS
+FileHasBeenProcessed (
+ IN EFI_GUID *FileNameGuid
+ )
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_STATUS HobStatus;
+ EFI_GUID FileName;
+ //
+ // First walk hobs and create appropriate FVs.
+ //
+ Status = CoreGetConfigTable (&gEfiHobListGuid, &HobList);
+ //
+ // Core Needs Firmware Volumes to function
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ BaseAddress = 0;
+ Length = 0;
+ HobStatus = GetNextFirmwareVolume2Hob (
+ &HobList,
+ &BaseAddress,
+ &Length,
+ &FileName
+ );
+ while (!EFI_ERROR (HobStatus)) {
+ //
+ // Check if the file has been processed.
+ //
+ if (EfiCompareGuid (FileNameGuid, &FileName)) {
+ return EFI_SUCCESS;
+ }
+ HobStatus = GetNextFirmwareVolume2Hob (
+ &HobList,
+ &BaseAddress,
+ &Length,
+ &FileName
+ );
+ }
+
+ return EFI_NOT_FOUND;
+
+}
+
+#endif
+
+BOOLEAN
+FvHasBeenProcessed (
+ IN EFI_HANDLE FvHandle
+ )
+/*++
+
+Routine Description:
+
+ Return TRUE if the Fv has been processed, FALSE if not.
+
+Arguments:
+
+ FvHandle - The handle of a FV that's being tested
+
+Returns:
+
+ TRUE - Fv protocol on FvHandle has been processed
+
+ FALSE - Fv protocol on FvHandle has not yet been processed
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ KNOWN_HANDLE *KnownHandle;
+
+ for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
+ KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
+ if (KnownHandle->Handle == FvHandle) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+VOID
+FvIsBeingProcesssed (
+ IN EFI_HANDLE FvHandle
+ )
+/*++
+
+Routine Description:
+
+ Remember that Fv protocol on FvHandle has had it's drivers placed on the
+ mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
+ never removed/freed from the mFvHandleList.
+
+Arguments:
+
+ FvHandle - The handle of a FV that has been processed
+
+Returns:
+
+ None
+
+--*/
+{
+ KNOWN_HANDLE *KnownHandle;
+
+ KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE));
+ ASSERT (KnownHandle != NULL);
+
+ KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
+ KnownHandle->Handle = FvHandle;
+ InsertTailList (&mFvHandleList, &KnownHandle->Link);
+}
+
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreFvToDevicePath (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert FvHandle and DriverName into an EFI device path
+
+Arguments:
+
+ Fv - Fv protocol, needed to read Depex info out of FLASH.
+
+ FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
+ PE image can be read out of the FV at a later time.
+
+ DriverName - Name of driver to add to mDiscoveredList.
+
+Returns:
+
+ Pointer to device path constructed from FvHandle and DriverName
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath;
+
+ //
+ // Remember the device path of the FV
+ //
+ Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, &FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ FileNameDevicePath = NULL;
+ } else {
+ //
+ // Build a device path to the file in the FV to pass into gBS->LoadImage
+ //
+ CoreInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
+ mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
+ mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ FileNameDevicePath = CoreAppendDevicePath (
+ FvDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
+ );
+ }
+
+ return FileNameDevicePath;
+}
+
+
+
+EFI_STATUS
+CoreAddToDriverList (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
+ and initilize any state variables. Read the Depex from the FV and store it
+ in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
+ The Discovered list is never free'ed and contains booleans that represent the
+ other possible DXE driver states.
+
+Arguments:
+
+ Fv - Fv protocol, needed to read Depex info out of FLASH.
+
+ FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
+ PE image can be read out of the FV at a later time.
+
+ DriverName - Name of driver to add to mDiscoveredList.
+
+Returns:
+
+ EFI_SUCCESS - If driver was added to the mDiscoveredList.
+
+ EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName
+ may be active in the system at any one time.
+
+--*/
+{
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+
+ //
+ // Create the Driver Entry for the list. ZeroPool initializes lots of variables to
+ // NULL or FALSE.
+ //
+ DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY));
+ ASSERT (DriverEntry != NULL);
+
+ DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
+ EfiCommonLibCopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID));
+ DriverEntry->FvHandle = FvHandle;
+ DriverEntry->Fv = Fv;
+ DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);
+
+ CoreGetDepexSectionAndPreProccess (DriverEntry);
+
+ CoreAcquireDispatcherLock ();
+
+ InsertTailList (&mDiscoveredList, &DriverEntry->Link);
+
+ CoreReleaseDispatcherLock ();
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+CoreProcessFvImageFile (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv,
+#else
+ IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv,
+#endif
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.
+
+Arguments:
+
+ Fv - The FIRMWARE_VOLUME protocol installed on the FV.
+ FvHandle - The handle which FVB protocol installed on.
+ DriverName - The driver guid specified.
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough memory or other resource.
+
+ EFI_VOLUME_CORRUPTED - Corrupted volume.
+
+ EFI_SUCCESS - Function successfully returned.
+
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ VOID *Buffer;
+ UINTN BufferSize;
+
+ //
+ // Read the first (and only the first) firmware volume section
+ //
+ SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
+ Buffer = NULL;
+ BufferSize = 0;
+ Status = Fv->ReadSection (
+ Fv,
+ DriverName,
+ SectionType,
+ 0,
+ &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Produce a FVB protocol for the file
+ //
+ Status = ProduceFVBProtocolOnBuffer (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,
+ (UINT64)BufferSize,
+ FvHandle,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status) && (Buffer != NULL)) {
+ //
+ // ReadSection or Produce FVB failed, Free data buffer
+ //
+ gBS->FreePool (Buffer);
+
+ }
+
+ return Status;
+}
+
+
+VOID
+EFIAPI
+CoreFwVolEventProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Event notification that is fired every time a FV dispatch protocol is added.
+ More than one protocol may have been added when this event is fired, so you
+ must loop on CoreLocateHandle () to see how many protocols were added and
+ do the following to each FV:
+
+ If the Fv has already been processed, skip it. If the Fv has not been
+ processed then mark it as being processed, as we are about to process it.
+
+ Read the Fv and add any driver in the Fv to the mDiscoveredList.The
+ mDiscoveredList is never free'ed and contains variables that define
+ the other states the DXE driver transitions to..
+
+ While you are at it read the A Priori file into memory.
+ Place drivers in the A Priori list onto the mScheduledQueue.
+
+Arguments:
+
+ Event - The Event that is being processed, not used.
+
+ Context - Event Context, not used.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS GetNextFileStatus;
+ EFI_STATUS SecurityStatus;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_HANDLE FvHandle;
+ UINTN BufferSize;
+ EFI_GUID NameGuid;
+ UINTN Key;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+ EFI_GUID *AprioriFile;
+ UINTN AprioriEntryCount;
+ UINTN Index;
+ EFI_LIST_ENTRY *Link;
+ UINT32 AuthenticationStatus;
+ UINTN SizeOfBuffer;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = CoreLocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mFwVolEventRegistration,
+ &BufferSize,
+ &FvHandle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no more notification events exit
+ //
+ return;
+ }
+
+ if (FvHasBeenProcessed (FvHandle)) {
+ //
+ // This Fv has already been processed so lets skip it!
+ //
+ continue;
+ }
+
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, &Fv);
+ if (EFI_ERROR (Status)) {
+ //
+ // If no dispatch protocol then skip, but do not marked as being processed as it
+ // may show up later.
+ //
+ continue;
+ }
+
+ //
+ // Since we are about to process this Fv mark it as processed.
+ //
+ FvIsBeingProcesssed (FvHandle);
+
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, &Fv);
+ #else
+ Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ #endif
+ if (EFI_ERROR (Status)) {
+ //
+ // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
+ // a FirmwareVolume protocol thus we should never get here.
+ //
+ ASSERT (FALSE);
+ continue;
+ }
+
+ Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, &FvDevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // The Firmware volume doesn't have device path, can't be dispatched.
+ //
+ continue;
+ }
+
+ //
+ // Evaluate the authentication status of the Firmware Volume through
+ // Security Architectural Protocol
+ //
+ if (gSecurity != NULL) {
+ SecurityStatus = gSecurity->FileAuthenticationState (
+ gSecurity,
+ 0,
+ FvDevicePath
+ );
+ if (SecurityStatus != EFI_SUCCESS) {
+ //
+ // Security check failed. The firmware volume should not be used for any purpose.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Discover Drivers in FV and add them to the Discovered Driver List.
+ // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
+ // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
+ // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
+ //
+ for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
+ //
+ // Initialize the search key
+ //
+ Key = 0;
+ do {
+ Type = mDxeFileTypes[Index];
+ GetNextFileStatus = Fv->GetNextFile (
+ Fv,
+ &Key,
+ &Type,
+ &NameGuid,
+ &Attributes,
+ &Size
+ );
+ if (!EFI_ERROR (GetNextFileStatus)) {
+ if (Type == EFI_FV_FILETYPE_DXE_CORE) {
+ //
+ // If this is the DXE core fill in it's DevicePath & DeviceHandle
+ //
+ if (gDxeCoreLoadedImage->FilePath == NULL) {
+ if (EfiCompareGuid (&NameGuid, gDxeCoreFileName)) {
+ CoreInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
+ mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
+ mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (
+ (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
+ );
+ gDxeCoreLoadedImage->DeviceHandle = FvHandle;
+ }
+ }
+ } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+
+ #if (PI_SPECIFICATION_VERSION >= 0x00010000)
+ if (FileHasBeenProcessed (&NameGuid) == EFI_SUCCESS) {
+ //
+ // Skip over the file which has been processed.
+ //
+ continue;
+ }
+
+ #endif
+ //
+ // Found a firmware volume image. Produce a firmware volume block
+ // protocol for it so it gets dispatched from. This is usually a
+ // capsule.
+ //
+ CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
+ } else {
+ //
+ // Transition driver from Undiscovered to Discovered state
+ //
+ CoreAddToDriverList (Fv, FvHandle, &NameGuid);
+ }
+ }
+ } while (!EFI_ERROR (GetNextFileStatus));
+ }
+
+ //
+ // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
+ //
+ AprioriFile = NULL;
+ Status = Fv->ReadSection (
+ Fv,
+ &gAprioriGuid,
+ EFI_SECTION_RAW,
+ 0,
+ &AprioriFile,
+ &SizeOfBuffer,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
+ } else {
+ AprioriEntryCount = 0;
+ }
+
+ //
+ // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
+ // drivers not in the current FV and these must be skipped since the a priori list
+ // is only valid for the FV that it resided in.
+ //
+ CoreAcquireDispatcherLock ();
+
+ for (Index = 0; Index < AprioriEntryCount; Index++) {
+ for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (EfiCompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
+ (FvHandle == DriverEntry->FvHandle)) {
+ DriverEntry->Dependent = FALSE;
+ DriverEntry->Scheduled = TRUE;
+ InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
+ break;
+ }
+ }
+ }
+
+ CoreReleaseDispatcherLock ();
+
+ //
+ // Free data allocated by Fv->ReadSection ()
+ //
+ gBS->FreePool (AprioriFile);
+ }
+}
+
+
+VOID
+CoreInitializeDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the dispatcher. Initialize the notification function that runs when
+ a FV protocol is added to the system.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ mFwVolEvent = CoreCreateProtocolNotifyEvent (
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+ #else
+ &gEfiFirmwareVolume2ProtocolGuid,
+ #endif
+ EFI_TPL_CALLBACK,
+ CoreFwVolEventProtocolNotify,
+ NULL,
+ &mFwVolEventRegistration,
+ TRUE
+ );
+}
+
+//
+// Function only used in debug buils
+//
+DEBUG_CODE (
+VOID
+CoreDisplayDiscoveredNotDispatched (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Traverse the discovered list for any drivers that were discovered but not loaded
+ because the dependency experessions evaluated to false
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_CORE_DRIVER_ENTRY *DriverEntry;
+
+ for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
+ DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
+ if (DriverEntry->Dependent) {
+ DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
+ }
+ }
+}
+)
diff --git a/Core/CORE_DXE/DriverSupport.c b/Core/CORE_DXE/DriverSupport.c
new file mode 100644
index 0000000..029bf5d
--- /dev/null
+++ b/Core/CORE_DXE/DriverSupport.c
@@ -0,0 +1,931 @@
+/*++
+
+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:
+
+ DriverSupport.c
+
+Abstract:
+
+ EFI Driver Support Protocol
+
+Revision History
+
+--*/
+
+#include "Tiano.h"
+#include "hand.h"
+#include "EfiPerf.h"
+
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION(DriverBinding)
+#include EFI_PROTOCOL_DEFINITION(PlatformDriverOverride)
+#include EFI_PROTOCOL_DEFINITION(BusSpecificDriverOverride)
+//*** AMI PORTING BEGIN ***//
+//Print Name of the driver to be started
+#ifdef EFI_DEBUG
+#include <Token.h>
+CHAR8* GetDriverName(EFI_DRIVER_BINDING_PROTOCOL *pDriver);
+VOID Trace(UINTN /* Level*/, CHAR8 * /*sFormat*/,...);
+#endif
+//*** AMI PORTING END *****//
+
+
+//
+// Driver Support Function Prototypes
+//
+STATIC
+EFI_STATUS
+CoreConnectSingleController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+//
+// Driver Support Functions
+//
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreConnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN BOOLEAN Recursive
+ )
+/*++
+
+Routine Description:
+
+ Connects one or more drivers to a controller.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+
+ DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
+
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
+ controller specified by ControllerHandle.
+
+ Recursive - Whether the function would be called recursively or not.
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY *ProtLink;
+ OPEN_PROTOCOL_DATA *OpenData;
+ EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;
+ EFI_HANDLE *ChildHandleBuffer;
+ UINTN ChildHandleCount;
+ UINTN Index;
+
+ //
+ // Make sure ControllerHandle is valid
+ //
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = ControllerHandle;
+
+ //
+ // Make a copy of RemainingDevicePath to guanatee it is aligned
+ //
+ AlignedRemainingDevicePath = NULL;
+ if (RemainingDevicePath != NULL) {
+ AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
+ }
+
+ //
+ // Connect all drivers to ControllerHandle
+ // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
+ // Driver Binding Protocols in the handle database has increased during the call
+ // so the connect operation must be restarted
+ //
+ do {
+ ReturnStatus = CoreConnectSingleController (
+ ControllerHandle,
+ DriverImageHandle,
+ AlignedRemainingDevicePath
+ );
+ } while (ReturnStatus == EFI_NOT_READY);
+
+ //
+ // Free the aligned copy of RemainingDevicePath
+ //
+ if (AlignedRemainingDevicePath != NULL) {
+ CoreFreePool (AlignedRemainingDevicePath);
+ }
+
+ //
+ // If recursive, then connect all drivers to all of ControllerHandle's children
+ //
+ if (Recursive) {
+ //
+ // Acquire the protocol lock on the handle database so the child handles can be collected
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Make sure the DriverBindingHandle is valid
+ //
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Release the protocol lock on the handle database
+ //
+ CoreReleaseProtocolLock ();
+
+ return ReturnStatus;
+ }
+
+
+ //
+ // Count ControllerHandle's children
+ //
+ for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ ChildHandleCount++;
+ }
+ }
+ }
+
+ //
+ // Allocate a handle buffer for ControllerHandle's children
+ //
+ ChildHandleBuffer = CoreAllocateBootServicesPool (ChildHandleCount * sizeof(EFI_HANDLE));
+
+ //
+ // Fill in a handle buffer with ControllerHandle's children
+ //
+ for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
+ ChildHandleCount++;
+ }
+ }
+ }
+
+ //
+ // Release the protocol lock on the handle database
+ //
+ CoreReleaseProtocolLock ();
+
+ //
+ // Recursively connect each child handle
+ //
+ for (Index = 0; Index < ChildHandleCount; Index++) {
+ CoreConnectController (
+ ChildHandleBuffer[Index],
+ NULL,
+ NULL,
+ TRUE
+ );
+ }
+
+ //
+ // Free the handle buffer of ControllerHandle's children
+ //
+ CoreFreePool (ChildHandleBuffer);
+ }
+
+ return ReturnStatus;
+}
+
+VOID
+AddSortedDriverBindingProtocol (
+ IN EFI_HANDLE DriverBindingHandle,
+ IN OUT UINTN *NumberOfSortedDriverBindingProtocols,
+ IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols,
+ IN UINTN DriverBindingHandleCount,
+ IN OUT EFI_HANDLE *DriverBindingHandleBuffer,
+ IN BOOLEAN IsImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Add Driver Binding Protocols from Context Driver Image Handles to sorted
+ Driver Binding Protocol list.
+
+Arguments:
+
+ DriverBindingHandle - Handle of the driver binding protocol.
+
+ NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
+
+ SortedDriverBindingProtocols - The sorted protocol list.
+
+ DriverBindingHandleCount - Driver Binding Handle Count.
+
+ DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
+
+ IsImageHandle - Indicate whether DriverBindingHandle is an image handle
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN Index;
+
+ //
+ // Make sure the DriverBindingHandle is valid
+ //
+ Status = CoreValidateHandle (DriverBindingHandle);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
+ // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
+ //
+ if (IsImageHandle) {
+ //
+ // Loop through all the Driver Binding Handles
+ //
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ //
+ // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
+ //
+ Status = CoreHandleProtocol (
+ DriverBindingHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ &DriverBinding
+ );
+ if (EFI_ERROR(Status) || DriverBinding == NULL) {
+ continue;
+ }
+ //
+ // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
+ // then add the DriverBindingProtocol[Index] to the sorted list
+ //
+ if (DriverBinding->ImageHandle == DriverBindingHandle) {
+ AddSortedDriverBindingProtocol (
+ DriverBindingHandleBuffer[Index],
+ NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer,
+ FALSE
+ );
+ }
+ }
+ return;
+ }
+
+ //
+ // Retrieve the Driver Binding Protocol from DriverBindingHandle
+ //
+ Status = CoreHandleProtocol(
+ DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &DriverBinding
+ );
+ //
+ // If DriverBindingHandle does not support the Driver Binding Protocol then return
+ //
+ if (EFI_ERROR (Status) || DriverBinding == NULL) {
+ return;
+ }
+
+ //
+ // See if DriverBinding is already in the sorted list
+ //
+ for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
+ if (DriverBinding == SortedDriverBindingProtocols[Index]) {
+ return;
+ }
+ }
+
+ //
+ // Add DriverBinding to the end of the list
+ //
+ if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
+ SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
+ }
+ *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
+
+ //
+ // Mark the cooresponding handle in DriverBindingHandleBuffer as used
+ //
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
+ DriverBindingHandleBuffer[Index] = NULL;
+ }
+ }
+}
+
+STATIC
+EFI_STATUS
+CoreConnectSingleController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Connects a controller to a driver.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+ ContextDriverImageHandles - DriverImageHandle A pointer to an ordered list of driver image handles.
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child
+ of the controller specified by ControllerHandle.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were connected to ControllerHandle.
+ EFI_OUT_OF_RESOURCES - No enough system resources to complete the request.
+ EFI_NOT_FOUND - No drivers were connected to ControllerHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE DriverImageHandle;
+ EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ UINTN NewDriverBindingHandleCount;
+ EFI_HANDLE *NewDriverBindingHandleBuffer;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN NumberOfSortedDriverBindingProtocols;
+ EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols;
+ UINT32 HighestVersion;
+ UINTN HighestIndex;
+ UINTN SortIndex;
+ BOOLEAN OneStarted;
+ BOOLEAN DriverFound;
+
+ //
+ // Initialize local variables
+ //
+ DriverBindingHandleCount = 0;
+ DriverBindingHandleBuffer = NULL;
+ NumberOfSortedDriverBindingProtocols = 0;
+ SortedDriverBindingProtocols = NULL;
+
+ //
+ // Get list of all Driver Binding Protocol Instances
+ //
+ Status = CoreLocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
+ //
+ SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
+ if (SortedDriverBindingProtocols == NULL) {
+ CoreFreePool (DriverBindingHandleBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Add Driver Binding Protocols from Context Driver Image Handles first
+ //
+ if (ContextDriverImageHandles != NULL) {
+ for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
+ AddSortedDriverBindingProtocol (
+ ContextDriverImageHandles[Index],
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer,
+ FALSE
+ );
+ }
+ }
+
+ //
+ // Add the Platform Driver Override Protocol drivers for ControllerHandle next
+ //
+ Status = CoreLocateProtocol (
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ NULL,
+ &PlatformDriverOverride
+ );
+ if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
+ DriverImageHandle = NULL;
+ do {
+ Status = PlatformDriverOverride->GetDriver (
+ PlatformDriverOverride,
+ ControllerHandle,
+ &DriverImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ AddSortedDriverBindingProtocol (
+ DriverImageHandle,
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer,
+ TRUE
+ );
+ }
+ } while (!EFI_ERROR (Status));
+ }
+
+ //
+ // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
+ //
+ Status = CoreHandleProtocol(
+ ControllerHandle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ &BusSpecificDriverOverride
+ );
+ if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
+ DriverImageHandle = NULL;
+ do {
+ Status = BusSpecificDriverOverride->GetDriver (
+ BusSpecificDriverOverride,
+ &DriverImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ AddSortedDriverBindingProtocol (
+ DriverImageHandle,
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer,
+ TRUE
+ );
+ }
+ } while (!EFI_ERROR (Status));
+ }
+
+ //
+ // Then add all the remaining Driver Binding Protocols
+ //
+ SortIndex = NumberOfSortedDriverBindingProtocols;
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ AddSortedDriverBindingProtocol (
+ DriverBindingHandleBuffer[Index],
+ &NumberOfSortedDriverBindingProtocols,
+ SortedDriverBindingProtocols,
+ DriverBindingHandleCount,
+ DriverBindingHandleBuffer,
+ FALSE
+ );
+ }
+
+ //
+ // Free the Driver Binding Handle Buffer
+ //
+ CoreFreePool (DriverBindingHandleBuffer);
+
+ //
+ // If the number of Driver Binding Protocols has increased since this function started, then return
+ // EFI_NOT_READY, so it will be restarted
+ //
+ Status = CoreLocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &NewDriverBindingHandleCount,
+ &NewDriverBindingHandleBuffer
+ );
+ CoreFreePool (NewDriverBindingHandleBuffer);
+ if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
+ //
+ // Free any buffers that were allocated with AllocatePool()
+ //
+ CoreFreePool (SortedDriverBindingProtocols);
+
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Sort the remaining DriverBinding Protocol based on their Version field from
+ // highest to lowest.
+ //
+ for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
+ HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
+ HighestIndex = SortIndex;
+ for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
+ if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
+ HighestVersion = SortedDriverBindingProtocols[Index]->Version;
+ HighestIndex = Index;
+ }
+ }
+ if (SortIndex != HighestIndex) {
+ DriverBinding = SortedDriverBindingProtocols[SortIndex];
+ SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
+ SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
+ }
+ }
+
+ //
+ // Loop until no more drivers can be started on ControllerHandle
+ //
+ OneStarted = FALSE;
+ do {
+
+ //
+ // Loop through the sorted Driver Binding Protocol Instances in order, and see if
+ // any of the Driver Binding Protocols support the controller specified by
+ // ControllerHandle.
+ //
+ DriverBinding = NULL;
+ DriverFound = FALSE;
+ for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
+ if (SortedDriverBindingProtocols[Index] != NULL) {
+ DriverBinding = SortedDriverBindingProtocols[Index];
+ Status = DriverBinding->Supported(
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ if (!EFI_ERROR (Status)) {
+ SortedDriverBindingProtocols[Index] = NULL;
+ DriverFound = TRUE;
+
+//*** AMI PORTING BEGIN ***//
+//Print Name of the driver to be started
+#if defined(EFI_DEBUG) && defined(TRACE_START) && TRACE_START==1
+ Trace(-1, "%s.Start(%X)=", GetDriverName(DriverBinding), DriverBinding->Start);
+#endif
+//*** AMI PORTING END *****//
+ //
+ // A driver was found that supports ControllerHandle, so attempt to start the driver
+ // on ControllerHandle.
+ //
+ PERF_START (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
+ Status = DriverBinding->Start (
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ PERF_END (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
+//*** AMI PORTING BEGIN ***//
+//Print Name of the driver to be started
+#if defined(EFI_DEBUG) && defined(TRACE_START) && TRACE_START==1
+ Trace(-1, "%r\n", Status);
+#endif
+//*** AMI PORTING END *****//
+ if (!EFI_ERROR (Status)) {
+ //
+ // The driver was successfully started on ControllerHandle, so set a flag
+ //
+ OneStarted = TRUE;
+ }
+ }
+ }
+ }
+ } while (DriverFound);
+
+ //
+ // Free any buffers that were allocated with AllocatePool()
+ //
+ CoreFreePool (SortedDriverBindingProtocols);
+
+ //
+ // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
+ //
+ if (OneStarted) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
+ //
+ if (RemainingDevicePath != NULL) {
+ if (IsDevicePathEnd (RemainingDevicePath)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
+ //
+ return EFI_NOT_FOUND;
+}
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreDisconnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE DriverImageHandle OPTIONAL,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Disonnects a controller from a driver
+
+Arguments:
+
+ ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
+ are to be disconnected.
+ DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
+ ChildHandle - ChildHandle The handle of the child to destroy.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were disconnected from the controller.
+ EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
+ EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
+ EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ EFI_HANDLE *DriverImageHandleBuffer;
+ EFI_HANDLE *ChildBuffer;
+ UINTN Index;
+ UINTN HandleIndex;
+ UINTN DriverImageHandleCount;
+ UINTN ChildrenToStop;
+ UINTN ChildBufferCount;
+ UINTN StopCount;
+ BOOLEAN Duplicate;
+ BOOLEAN ChildHandleValid;
+ BOOLEAN DriverImageHandleValid;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY *ProtLink;
+ OPEN_PROTOCOL_DATA *OpenData;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+ //
+ // Make sure ControllerHandle is valid
+ //
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Make sure ChildHandle is valid if it is not NULL
+ //
+ if (ChildHandle != NULL) {
+ Status = CoreValidateHandle (ChildHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Handle = ControllerHandle;
+
+ //
+ // Get list of drivers that are currently managing ControllerHandle
+ //
+ DriverImageHandleBuffer = NULL;
+ DriverImageHandleCount = 1;
+
+ if (DriverImageHandle == NULL) {
+ //
+ // Look at each protocol interface for a match
+ //
+ DriverImageHandleCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ DriverImageHandleCount++;
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+
+ //
+ // If there are no drivers managing this controller, then return EFI_SUCCESS
+ //
+ if (DriverImageHandleCount == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
+ if (DriverImageHandleBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ DriverImageHandleCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ Duplicate = FALSE;
+ for (Index = 0; Index< DriverImageHandleCount; Index++) {
+ if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
+ Duplicate = TRUE;
+ break;
+ }
+ }
+ if (!Duplicate) {
+ DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
+ DriverImageHandleCount++;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+ }
+
+ StopCount = 0;
+ for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
+
+ if (DriverImageHandleBuffer != NULL) {
+ DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
+ }
+
+ //
+ // Get the Driver Binding Protocol of the driver that is managing this controller
+ //
+ Status = CoreHandleProtocol (
+ DriverImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &DriverBinding
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ DriverImageHandleValid = FALSE;
+ ChildBufferCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->AgentHandle == DriverImageHandle) {
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ ChildBufferCount++;
+ }
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ DriverImageHandleValid = TRUE;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+
+ if (DriverImageHandleValid) {
+ ChildHandleValid = FALSE;
+ ChildBuffer = NULL;
+ if (ChildBufferCount != 0) {
+ ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
+ if (ChildBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ChildBufferCount = 0;
+
+ CoreAcquireProtocolLock ();
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ for (ProtLink = Prot->OpenList.ForwardLink;
+ ProtLink != &Prot->OpenList;
+ ProtLink = ProtLink->ForwardLink) {
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->AgentHandle == DriverImageHandle) &&
+ ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
+ Duplicate = FALSE;
+ for (Index = 0; Index < ChildBufferCount; Index++) {
+ if (ChildBuffer[Index] == OpenData->ControllerHandle) {
+ Duplicate = TRUE;
+ break;
+ }
+ }
+ if (!Duplicate) {
+ ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
+ if (ChildHandle == ChildBuffer[ChildBufferCount]) {
+ ChildHandleValid = TRUE;
+ }
+ ChildBufferCount++;
+ }
+ }
+ }
+ }
+ CoreReleaseProtocolLock ();
+ }
+
+ if (ChildHandle == NULL || ChildHandleValid) {
+ ChildrenToStop = 0;
+ Status = EFI_SUCCESS;
+//*** AMI PORTING BEGIN ***//
+//Print Name of the driver to be stopped
+#if defined(EFI_DEBUG) && defined(TRACE_STOP) && TRACE_STOP==1
+ Trace(-1, "%s.Stop=", GetDriverName(DriverBinding));
+#endif
+//*** AMI PORTING END *****//
+ if (ChildBufferCount > 0) {
+ if (ChildHandle != NULL) {
+ ChildrenToStop = 1;
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
+ } else {
+ ChildrenToStop = ChildBufferCount;
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
+ }
+ }
+ if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
+ Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
+ }
+//*** AMI PORTING BEGIN ***//
+//Print Name of the driver to be stopped
+#if defined(EFI_DEBUG) && defined(TRACE_STOP) && TRACE_STOP==1
+ Trace(-1, "%r\n", Status);
+#endif
+//*** AMI PORTING END *****//
+
+ if (!EFI_ERROR (Status)) {
+ StopCount++;
+ }
+ }
+
+ if (ChildBuffer != NULL) {
+ CoreFreePool (ChildBuffer);
+ }
+ }
+ }
+
+ if (StopCount > 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+
+Done:
+
+ if (DriverImageHandleBuffer != NULL) {
+ CoreFreePool (DriverImageHandleBuffer);
+ }
+
+ return Status;
+}
diff --git a/Core/CORE_DXE/DxeCore.h b/Core/CORE_DXE/DxeCore.h
new file mode 100644
index 0000000..0fb2611
--- /dev/null
+++ b/Core/CORE_DXE/DxeCore.h
@@ -0,0 +1,2542 @@
+/*++
+
+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:
+
+ DxeCore.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXECORE_H_
+#define _DXECORE_H_
+
+#include EFI_GUID_DEFINITION (PeiFlushInstructionCache)
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)
+#include EFI_GUID_DEFINITION (PeiTransferControl)
+#include EFI_GUID_DEFINITION (Hob)
+#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+#include EFI_GUID_DEFINITION (DxeServices)
+#include EFI_GUID_DEFINITION (MemoryTypeInformation)
+#include EFI_GUID_DEFINITION (StatusCodeCallerId)
+#include EFI_GUID_DEFINITION (EventGroup)
+#include EFI_GUID_DEFINITION (EventLegacyBios)
+#include EFI_GUID_DEFINITION (FrameworkDevicePath)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_ARCH_PROTOCOL_DEFINITION (MonotonicCounter)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Timer)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Bds)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Reset)
+#include EFI_ARCH_PROTOCOL_DEFINITION (RealTimeClock)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
+#include EFI_ARCH_PROTOCOL_DEFINITION (VariableWrite)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Capsule)
+#include EFI_ARCH_PROTOCOL_DEFINITION (WatchdogTimer)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Runtime)
+#include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Security)
+//*** AMI PORTING BEGIN ***//
+#include EFI_ARCH_PROTOCOL_DEFINITION (Security2)
+//*** AMI PORTING END ***//
+#include EFI_PROTOCOL_DEFINITION (Decompress)
+#include EFI_PROTOCOL_DEFINITION (TianoDecompress)
+#include EFI_PROTOCOL_DEFINITION (CustomizedDecompress)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume2)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeDispatch)
+#include EFI_PROTOCOL_DEFINITION (LoadedImage)
+#include EFI_PROTOCOL_DEFINITION (TcgService)
+#include "LinkedList.h"
+#include "DebugImageInfo.h"
+#include "EfiCommonLib.h"
+#include "Library.h"
+#include "Peihob.h"
+#include "EfiHobLib.h"
+#include "DebugMask.h"
+
+
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ VOID **Protocol;
+ EFI_EVENT Event;
+ VOID *Registration;
+ BOOLEAN Present;
+} ARCHITECTURAL_PROTOCOL_ENTRY;
+
+
+//
+// DXE Dispatcher Data structures
+//
+
+#define KNOWN_HANDLE_SIGNATURE EFI_SIGNATURE_32('k','n','o','w')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link; // mFvHandleList
+ EFI_HANDLE Handle;
+} KNOWN_HANDLE;
+
+
+#define EFI_CORE_DRIVER_ENTRY_SIGNATURE EFI_SIGNATURE_32('d','r','v','r')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link; // mDriverList
+
+ EFI_LIST_ENTRY ScheduledLink; // mScheduledQueue
+
+ EFI_HANDLE FvHandle;
+ EFI_GUID FileName;
+ EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+ VOID *Depex;
+ UINTN DepexSize;
+
+ BOOLEAN Before;
+ BOOLEAN After;
+ EFI_GUID BeforeAfterGuid;
+
+ BOOLEAN Dependent;
+ BOOLEAN Unrequested;
+ BOOLEAN Scheduled;
+ BOOLEAN Untrusted;
+ BOOLEAN Initialized;
+ BOOLEAN DepexProtocolError;
+
+ EFI_HANDLE ImageHandle;
+
+} EFI_CORE_DRIVER_ENTRY;
+
+//
+//The data structure of GCD memory map entry
+//
+#define EFI_GCD_MAP_SIGNATURE EFI_SIGNATURE_32('g','c','d','m')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 EndAddress;
+ UINT64 Capabilities;
+ UINT64 Attributes;
+ EFI_GCD_MEMORY_TYPE GcdMemoryType;
+ EFI_GCD_IO_TYPE GcdIoType;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE DeviceHandle;
+} EFI_GCD_MAP_ENTRY;
+
+//
+// DXE Core Global Variables
+//
+extern EFI_SYSTEM_TABLE *gST;
+extern EFI_BOOT_SERVICES *gBS;
+extern EFI_RUNTIME_SERVICES *gRT;
+extern EFI_DXE_SERVICES *gDS;
+extern EFI_HANDLE gDxeCoreImageHandle;
+
+extern EFI_DECOMPRESS_PROTOCOL *gEfiDecompress;
+extern EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *gEfiPeiFlushInstructionCache;
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader;
+extern EFI_PEI_TRANSFER_CONTROL_PROTOCOL *gEfiPeiTransferControl;
+
+extern EFI_RUNTIME_ARCH_PROTOCOL *gRuntime;
+extern EFI_CPU_ARCH_PROTOCOL *gCpu;
+extern EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer;
+extern EFI_METRONOME_ARCH_PROTOCOL *gMetronome;
+extern EFI_TIMER_ARCH_PROTOCOL *gTimer;
+extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity;
+//*** AMI PORTING BEGIN ***//
+extern EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2;
+//*** AMI PORTING END ***//
+extern EFI_BDS_ARCH_PROTOCOL *gBds;
+extern EFI_STATUS_CODE_PROTOCOL *gStatusCode;
+
+extern EFI_TPL gEfiCurrentTpl;
+
+extern EFI_GUID *gDxeCoreFileName;
+extern EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage;
+
+extern EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1];
+
+extern EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate;
+
+//
+// Service Initialization Functions
+//
+
+
+VOID
+CoreInitializePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the pool.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreAddMemoryDescriptor (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 NumberOfPages,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the memory map and add descriptors to
+ the current descriptor list.
+
+ N.B. The first descriptor that is added must be general usable
+ memory as the addition allocates heap.
+
+Arguments:
+
+ Type - The type of memory to add
+
+ Start - The starting address in the memory range
+ Must be page aligned
+
+ NumberOfPages - The number of pages in the range
+
+ Attribute - Attributes of the memory to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+;
+
+VOID
+CoreReleaseGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+;
+
+VOID
+CoreAcquireGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeMemoryServices (
+ IN VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
+ IN UINT64 *MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB.
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+Returns:
+
+ EFI_SUCCESS - Memory services successfully initialized.
+
+--*/
+;
+
+
+EFI_STATUS
+CoreInitializeGcdServices (
+ IN OUT VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map. The HobStart will be relocated to a pool
+ buffer.
+
+Arguments:
+
+ HobStart - The start address of the HOB
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+
+Returns:
+
+ EFI_SUCCESS - GCD services successfully initialized.
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes "event" support and populates parts of the System and Runtime Table.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success
+
+--*/
+;
+
+EFI_STATUS
+CoreInitializeImageServices (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Add the Image Services to EFI Boot Services Table and install the protocol
+ interfaces for this image.
+
+Arguments:
+
+ HobStart - The HOB to initialize
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+VOID
+CoreNotifyOnArchProtocolInstallation (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Creates an event that is fired everytime a Protocol of a specific type is installed
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+;
+
+EFI_STATUS
+CoreAllEfiServicesAvailable (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE if all AP services are availible.
+
+Arguments:
+ NONE
+
+Returns:
+ EFI_SUCCESS - All AP services are available
+ EFI_NOT_FOUND - At least one AP service is not available
+
+--*/
+;
+
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+Arguments:
+
+ Hdr - Pointer to an EFI standard header
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreTimerTick (
+ IN UINT64 Duration
+ )
+/*++
+
+Routine Description:
+
+ Called by the platform code to process a tick.
+
+Arguments:
+
+ Duration - The number of 100ns elasped since the last call to TimerTick
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreInitializeDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the dispatcher. Initialize the notification function that runs when
+ a FV protocol is added to the system.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+;
+
+BOOLEAN
+CoreIsSchedulable (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. This code does
+ not need to handle Before or After, as it is not valid to call this
+ routine in this case. The SOR is just ignored and is a nop in the grammer.
+
+ POSTFIX means all the math is done on top of the stack.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ TRUE - If driver is ready to run.
+
+ FALSE - If driver is not ready to run or some fatal error was found.
+
+--*/
+;
+
+EFI_STATUS
+CorePreProcessDepex (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Preprocess dependency expression and update DriverEntry to reflect the
+ state of Before, After, and SOR dependencies. If DriverEntry->Before
+ or DriverEntry->After is set it will never be cleared. If SOR is set
+ it will be cleared by CoreSchedule(), and then the driver can be
+ dispatched.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ EFI_SUCCESS - It always works.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreExitBootServices (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ EFI 1.0 API to terminate Boot Services
+
+Arguments:
+
+ ImageHandle - Handle that represents the identity of the calling image
+
+ MapKey -Key to the latest memory map.
+
+Returns:
+
+ EFI_SUCCESS - Boot Services terminated
+ EFI_INVALID_PARAMETER - MapKey is incorrect.
+
+--*/
+;
+
+EFI_STATUS
+CoreTerminateMemoryMap (
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Make sure the memory map is following all the construction rules,
+ it is the last time to check memory map error before exit boot services.
+
+Arguments:
+
+ MapKey - Memory map key
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Memory map not consistent with construction rules.
+
+ EFI_SUCCESS - Valid memory map.
+
+--*/
+;
+
+VOID
+CoreNotifySignalList (
+ IN EFI_GUID *EventGroup
+ )
+/*++
+
+Routine Description:
+
+ Signals all events on the requested list
+
+Arguments:
+
+ SignalType - The list to signal
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreInstallConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+/*++
+
+Routine Description:
+
+ Boot Service called to add, modify, or remove a system configuration table from
+ the EFI System Table.
+
+Arguments:
+
+ Guid: Pointer to the GUID for the entry to add, update, or remove
+ Table: Pointer to the configuration table for the entry to add, update, or
+ remove, may be NULL.
+
+Returns:
+
+ EFI_SUCCESS Guid, Table pair added, updated, or removed.
+ EFI_INVALID_PARAMETER Input GUID not valid.
+ EFI_NOT_FOUND Attempted to delete non-existant entry
+ EFI_OUT_OF_RESOURCES Not enough memory available
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_TPL
+EFIAPI
+CoreRaiseTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Raise the task priority level to the new level.
+ High level is implemented by disabling processor interrupts.
+
+Arguments:
+
+ NewTpl - New task priority level
+
+Returns:
+
+ The previous task priority level
+
+--*/
+;
+
+EFI_BOOTSERVICE
+VOID
+EFIAPI
+CoreRestoreTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Lowers the task priority to the previous value. If the new
+ priority unmasks events at a higher priority, they are dispatched.
+
+Arguments:
+
+ NewTpl - New, lower, task priority
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Introduces a fine-grained stall.
+
+Arguments:
+
+ Microseconds The number of microseconds to stall execution
+
+Returns:
+
+ EFI_SUCCESS - Execution was stalled for at least the requested amount
+ of microseconds.
+
+ EFI_NOT_AVAILABLE_YET - gMetronome is not available yet
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSetWatchdogTimer (
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Sets the system's watchdog timer.
+
+Arguments:
+
+ Timeout The number of seconds. Zero disables the timer.
+
+ ///////following three parameters are left for platform specific using
+
+ WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware
+ DataSize Size of the optional data
+ WatchdogData Optional Null terminated unicode string followed by binary
+ data.
+
+Returns:
+
+ EFI_SUCCESS Timeout has been set
+ EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
+ EFI_UNSUPPORTED System does not have a timer (currently not used)
+ EFI_DEVICE_ERROR Could not complete due to hardware error
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
+ Calls the private one which contains a BOOLEAN parameter for notifications
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+Returns:
+
+ Status code
+
+--*/
+;
+
+EFI_STATUS
+CoreInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ )
+/*++
+
+Routine Description:
+
+ Installs a protocol interface into the boot services environment.
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+ Notify - Whether to notify the notification list for this protocol
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Protocol interface successfully installed
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreInstallMultipleProtocolInterfaces (
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Installs a list of protocol interface into the boot services environment.
+ This function calls InstallProtocolInterface() in a loop. If any error
+ occures all the protocols added by this function are removed. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to install the protocol handlers on,
+ or NULL if a new handle is to be allocated
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to InstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Handle is NULL.
+
+ EFI_SUCCESS - Protocol interfaces successfully installed.
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreUninstallMultipleProtocolInterfaces (
+ IN EFI_HANDLE Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls a list of protocol interface in the boot services environment.
+ This function calls UnisatllProtocolInterface() in a loop. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to uninstall the protocol
+
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to UninstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ Status code
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreReinstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+/*++
+
+Routine Description:
+
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
+
+Arguments:
+
+ UserHandle - Handle on which the interface is to be reinstalled
+ Protocol - The numeric ID of the interface
+ OldInterface - A pointer to the old interface
+ NewInterface - A pointer to the new interface
+
+
+Returns:
+
+ Status code.
+
+ On EFI_SUCCESS The protocol interface was installed
+ On EFI_NOT_FOUND The OldInterface on the handle was not found
+ On EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls all instances of a protocol:interfacer from a handle.
+ If the last protocol interface is remove from the handle, the
+ handle is freed.
+
+Arguments:
+
+ UserHandle - The handle to remove the protocol handler from
+
+ Protocol - The protocol, of protocol:interface, to remove
+
+ Interface - The interface, of protocol:interface, to remove
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Protocol interface successfully uninstalled.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Queries a handle to determine if it supports a specified protocol.
+
+Arguments:
+
+ UserHandle - The handle being queried.
+
+ Protocol - The published unique identifier of the protocol.
+
+ Interface - Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreOpenProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface OPTIONAL,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Locates the installed protocol handler for the handle, and
+ invokes it to obtain the protocol interface. Usage information
+ is registered in the protocol data base.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ Interface - The location to return the protocol interface
+
+ ImageHandle - The handle of the Image that is opening the protocol interface
+ specified by Protocol and Interface.
+
+ ControllerHandle - The controller handle that is requiring this interface.
+
+ Attributes - The open mode of the protocol interface specified by Handle
+ and Protocol.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Get the protocol interface.
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreOpenProtocolInformation (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ )
+/*++
+
+Routine Description:
+
+ Return information about Opened protocols in the system
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ EntryBuffer - A pointer to a buffer of open protocol information in the form of
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+
+ EntryCount - Number of EntryBuffer entries
+
+Returns:
+
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreCloseProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle
+ )
+/*++
+
+Routine Description:
+
+ Close Protocol
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ ImageHandle - The user of the protocol to close
+
+ ControllerHandle - The user of the protocol to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreProtocolsPerHandle (
+ IN EFI_HANDLE UserHandle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+Arguments:
+
+ UserHandle - The handle from which to retrieve the list of protocol interface
+ GUIDs.
+
+ ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are
+ installed on Handle.
+
+ ProtocolBufferCount - A pointer to the number of GUID pointers present in
+ ProtocolBuffer.
+
+Returns:
+ EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in
+ ProtocolBuffer. The number of protocol interface GUIDs was
+ returned in ProtocolBufferCount.
+ EFI_INVALID_PARAMETER - Handle is NULL.
+ EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ProtocolBuffer is NULL.
+ EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreRegisterProtocolNotify (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ )
+/*++
+
+Routine Description:
+
+ Add a new protocol notification record for the request protocol.
+
+Arguments:
+
+ Protocol - The requested protocol to add the notify registration
+
+ Event - The event to signal
+
+ Registration - Returns the registration record
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully returned the registration record that has been added
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Locates the requested handle(s) and returns them in Buffer.
+
+Arguments:
+
+ SearchType - The type of search to perform to locate the handles
+
+ Protocol - The protocol to search for
+
+ SearchKey - Dependant on SearchType
+
+ BufferSize - On input the size of Buffer. On output the
+ size of data returned.
+
+ Buffer - The buffer to return the results in
+
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLocateDevicePath (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *Device
+ )
+/*++
+
+Routine Description:
+
+ Locates the handle to a device on the device path that supports the specified protocol.
+
+Arguments:
+
+ Protocol - The protocol to search for.
+ FilePath - On input, a pointer to a pointer to the device path. On output, the device
+ path pointer is modified to point to the remaining part of the devicepath.
+ Device - A pointer to the returned device handle.
+
+Returns:
+
+ EFI_SUCCESS - The resulting handle was returned.
+ EFI_NOT_FOUND - No handles matched the search.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreLocateHandleBuffer (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *NumberHandles,
+ OUT EFI_HANDLE **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Function returns an array of handles that support the requested protocol
+ in a buffer allocated from pool. This is a version of CoreLocateHandle()
+ that allocates a buffer for the caller.
+
+Arguments:
+
+ SearchType - Specifies which handle(s) are to be returned.
+ Protocol - Provides the protocol to search by.
+ This parameter is only valid for SearchType ByProtocol.
+ SearchKey - Supplies the search key depending on the SearchType.
+ NumberHandles - The number of handles returned in Buffer.
+ Buffer - A pointer to the buffer to return the requested array of
+ handles that support Protocol.
+
+Returns:
+
+ EFI_SUCCESS - The result array of handles was returned.
+ EFI_NOT_FOUND - No handles match the search.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Return the first Protocol Interface that matches the Protocol GUID. If
+ Registration is pasased in return a Protocol Instance that was just add
+ to the system. If Retistration is NULL return the first Protocol Interface
+ you find.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ Registration - Optional Registration Key returned from RegisterProtocolNotify()
+
+ Interface - Return the Protocol interface (instance).
+
+Returns:
+
+ EFI_SUCCESS - If a valid Interface is returned
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Protocol interface not found
+
+--*/
+;
+
+UINT64
+CoreGetHandleDatabaseKey (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ return handle database key.
+
+Arguments:
+
+ None
+
+Returns:
+
+ Handle database key.
+
+--*/
+;
+
+VOID
+CoreConnectHandlesByKey (
+ UINT64 Key
+ )
+/*++
+
+Routine Description:
+
+ Go connect any handles that were created or modified while a image executed.
+
+Arguments:
+
+ Key - The Key to show that the handle has been created/modified
+
+Returns:
+
+ None
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreConnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE *DriverImageHandle OPTIONAL,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN BOOLEAN Recursive
+ )
+/*++
+
+Routine Description:
+
+ Connects one or more drivers to a controller.
+
+Arguments:
+
+ ControllerHandle - Handle of the controller to be connected.
+
+ DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles.
+
+ RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the
+ controller specified by ControllerHandle.
+
+ Recursive - - Whether the function would be called recursively or not.
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreDisconnectController (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE DriverImageHandle OPTIONAL,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Disonnects a controller from a driver
+
+Arguments:
+
+ ControllerHandle - ControllerHandle The handle of the controller from which driver(s)
+ are to be disconnected.
+ DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
+ ChildHandle - ChildHandle The handle of the child to destroy.
+
+Returns:
+
+ EFI_SUCCESS - One or more drivers were disconnected from the controller.
+ EFI_SUCCESS - On entry, no drivers are managing ControllerHandle.
+ EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle.
+ EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreAllocatePages (
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages from the memory map.
+
+Arguments:
+
+ Type - The type of allocation to perform
+
+ MemoryType - The type of memory to turn the allocated pages into
+
+ NumberOfPages - The number of pages to allocate
+
+ Memory - A pointer to receive the base allocated memory address
+
+Returns:
+
+ Status. On success, Memory is filled in with the base address allocated
+
+ EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec.
+
+ EFI_NOT_FOUND - Could not allocate pages match the requirement.
+
+ EFI_OUT_OF_RESOURCES - No enough pages to allocate.
+
+ EFI_SUCCESS - Pages successfully allocated.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreFreePages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Frees previous allocated pages.
+
+Arguments:
+
+ Memory - Base address of memory being freed
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the entry that covers the range
+
+ EFI_INVALID_PARAMETER - Address not aligned
+
+ EFI_SUCCESS -Pages successfully freed.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMap (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *Desc,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ )
+/*++
+
+Routine Description:
+
+ Returns the current memory map.
+
+Arguments:
+
+ MemoryMapSize - On input the buffer size of MemoryMap allocated by caller
+ On output the required buffer size to contain the memory map
+
+ Desc - The buffer to return the current memory map
+
+ MapKey - The address to return the current map key
+
+ DescriptorSize - The size in bytes for an individual EFI_MEMORY_DESCRIPTOR
+
+ DescriptorVersion - The version number associated with the EFI_MEMORY_DESCRIPTOR
+
+Returns:
+
+ EFI_SUCCESS The current memory map was returned successfully
+
+ EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small
+
+ EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of a particular type.
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+ Buffer - The address to return a pointer to the allocated pool
+
+Returns:
+
+ EFI_INVALID_PARAMETER - PoolType not valid
+
+ EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed.
+
+ EFI_SUCCESS - Pool successfully allocated.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreFreePool (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Frees pool.
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is not a valid value.
+
+ EFI_SUCCESS - Pool successfully freed.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLoadImage (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreStartImage (
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Transfer control to a loaded image's entry point.
+
+Arguments:
+
+ ImageHandle - Handle of image to be started.
+
+ ExitDataSize - Pointer of the size to ExitData
+
+ ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
+ Unicode string, optionally followed by additional binary data. The string
+ is a description that the caller may use to further indicate the reason for
+ the image's exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully transfer control to the image's entry point.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_STATUS Status,
+ IN UINTN ExitDataSize,
+ IN CHAR16 *ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Terminates the currently loaded EFI image and returns control to boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image. This parameter is passed to the image
+ on entry.
+ Status - The image's exit code.
+ ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
+ EFI_SUCCESS.
+ ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
+ optionally followed by additional binary data. The string is a
+ description that the caller may use to further indicate the reason for
+ the image's exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
+
+ EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
+
+ EFI_ACCESS_DENIED - Should never reach there.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEvent (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT EFI_EVENT *pEvent
+ )
+/*++
+
+Routine Description:
+
+ Creates a general-purpose event structure
+
+Arguments:
+
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the event's notification function
+ NotifyContext - Pointer to the notification function's context; corresponds to
+ parameter "Context" in the notification function
+ pEvent - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ IN CONST EFI_GUID *EventGroup, OPTIONAL
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+ Creates a general-purpose event structure
+
+Arguments:
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSetTimer (
+ IN EFI_EVENT Event,
+ IN EFI_TIMER_DELAY Type,
+ IN UINT64 TriggerTime
+ )
+/*++
+
+Routine Description:
+
+ Sets the type of timer and the trigger time for a timer event.
+
+Arguments:
+
+ UserEvent - The timer event that is to be signaled at the specified time
+ Type - The type of time that is specified in TriggerTime
+ TriggerTime - The number of 100ns units until the timer expires
+
+Returns:
+
+ EFI_SUCCESS - The event has been set to be signaled at the requested time
+ EFI_INVALID_PARAMETER - Event or Type is not valid
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSignalEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Signals the event. Queues the event to be notified if needed
+
+Arguments:
+
+ Event - The event to signal
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event was signaled.
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreWaitForEvent (
+ IN UINTN NumberOfEvents,
+ IN EFI_EVENT *UserEvents,
+ OUT UINTN *UserIndex
+ )
+/*++
+
+Routine Description:
+
+ Stops execution until an event is signaled.
+
+Arguments:
+
+ NumberOfEvents - The number of events in the UserEvents array
+ UserEvents - An array of EFI_EVENT
+ UserIndex - Pointer to the index of the event which satisfied the wait condition
+
+Returns:
+
+ EFI_SUCCESS - The event indicated by Index was signaled.
+ EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
+ Event was not a valid type
+ EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCloseEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Closes an event and frees the event structure.
+
+Arguments:
+
+ UserEvent - Event to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event has been closed
+
+--*/
+;
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCheckEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Check the status of an event
+
+Arguments:
+
+ UserEvent - The event to check
+
+Returns:
+
+ EFI_SUCCESS - The event is in the signaled state
+ EFI_NOT_READY - The event is not in the signaled state
+ EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
+
+--*/
+;
+
+EFI_STATUS
+CoreAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of memory space to GCD map and add all available pages in this segment
+ as memory descriptors.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+ Capabilities - alterable attributes of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAllocateMemorySpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate memory space on GCD map.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdMemoryType - The desired memory type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - Memory space successfully allocated.
+
+--*/
+;
+
+EFI_STATUS
+CoreFreeMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Free a segment of memory space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+;
+
+EFI_STATUS
+CoreRemoveMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Remove a segment of memory space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully a segment of memory space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetMemorySpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Search all entries in GCD map which contains specified segment and build it to a descriptor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully get memory space descriptor.
+
+--*/
+;
+
+EFI_STATUS
+CoreSetMemorySpaceAttributes (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Set memory space with specified attributes.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Length - Specified length
+
+ Attributes - Specified attributes
+
+Returns:
+
+ EFI_SUCCESS - Successfully set attribute of a segment of memory space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetMemorySpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Transer all entries of GCD memory map into memory descriptors and pass to caller.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ MemorySpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get memory space map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAddIoSpace (
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of IO space to GCD map.
+
+Arguments:
+
+ GcdIoType - IO type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+
+--*/
+;
+
+EFI_STATUS
+CoreAllocateIoSpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate IO space on GCD map.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdIoType - The desired IO type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - IO space successfully allocated.
+
+--*/
+;
+
+EFI_STATUS
+CoreFreeIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Free a segment of IO space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+;
+
+EFI_STATUS
+CoreRemoveIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:Routine Description:
+
+ Remove a segment of IO space in GCD map.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully removed a segment of IO space.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetIoSpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Search all entries in GCD map which contains specified segment and build it to a descriptor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Descriptor is NULL.
+
+ EFI_SUCCESS - Successfully get the IO space descriptor.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetIoSpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Transer all entries of GCD IO map into IO descriptors and pass to caller.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ IoSpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get IO space map.
+
+--*/
+;
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreDispatcher (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This is the main Dispatcher for DXE and it exits when there are no more
+ drivers to run. Drain the mScheduledQueue and load and start a PE
+ image for each driver. Search the mDiscoveredList to see if any driver can
+ be placed on the mScheduledQueue. If no drivers are placed on the
+ mScheduledQueue exit the function. On exit it is assumed the Bds()
+ will be called, and when the Bds() exits the Dispatcher will be called
+ again.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ EFI_ALREADY_STARTED - The DXE Dispatcher is already running
+
+ EFI_NOT_FOUND - No DXE Drivers were dispatched
+
+ EFI_SUCCESS - One or more DXE Drivers were dispatched
+
+--*/
+;
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreSchedule (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Check every driver and locate a matching one. If the driver is found, the Unrequested
+ state flag is cleared.
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Dependent state.
+
+Returns:
+
+ EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared
+
+ EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set.
+
+--*/
+;
+
+EFI_DXESERVICE
+EFI_STATUS
+EFIAPI
+CoreTrust (
+ IN EFI_HANDLE FirmwareVolumeHandle,
+ IN EFI_GUID *DriverName
+ )
+/*++
+
+Routine Description:
+
+ Convert a driver from the Untrused back to the Scheduled state
+
+Arguments:
+
+ FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware
+ file specified by DriverName.
+
+ DriverName - The Driver name to put in the Scheduled state
+
+Returns:
+
+ EFI_SUCCESS - The file was found in the untrusted state, and it was promoted
+ to the trusted state.
+
+ EFI_NOT_FOUND - The file was not found in the untrusted state.
+
+--*/
+;
+
+BOOLEAN
+CoreGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+Arguments:
+
+ Status - Current status
+
+ Buffer - Current allocated buffer, or NULL
+
+ BufferSize - Current buffer size needed
+
+Returns:
+
+ TRUE - if the buffer was reallocated and the caller
+ should try the API again.
+
+ FALSE - buffer could not be allocated and the caller
+ should not try the API again.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FwVolDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, and registers two notification functions. These notification
+ functions are responsible for building the FV stack dynamically.
+
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+
+Returns:
+ EFI_SUCCESS - Function successfully returned.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+InitializeSectionExtraction (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Entry point of the section extraction code. Initializes an instance of the
+ section extraction interface and installs it on a new handle.
+
+Arguments:
+ ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver
+ SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table
+
+Returns:
+ EFI_SUCCESS: Driver initialized successfully
+ EFI_OUT_OF_RESOURCES: Could not allocate needed resources
+
+--*/
+;
+
+EFI_STATUS
+CoreProcessFirmwareVolume (
+ IN VOID *FvHeader,
+ IN UINTN Size,
+ OUT EFI_HANDLE *FVProtocolHandle
+ )
+/*++
+
+Routine Description:
+ This DXE service routine is used to process a firmware volume. In
+ particular, it can be called by BDS to process a single firmware
+ volume found in a capsule.
+
+Arguments:
+ FvHeader - pointer to a firmware volume header
+ Size - the size of the buffer pointed to by FvHeader
+ FVProtocolHandle - the handle on which a firmware volume protocol
+ was produced for the firmware volume passed in.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of
+ system resources
+ EFI_VOLUME_CORRUPTED - if the volume was corrupted
+ EFI_SUCCESS - a firmware volume protocol was produced for the
+ firmware volume
+
+--*/
+;
+
+//
+//Functions used during debug buils
+//
+DEBUG_CODE (
+ VOID
+ CoreDisplayMissingArchProtocols (
+ VOID
+ )
+ /*++
+
+ Routine Description:
+ Displays Architectural protocols that were not loaded and are required for DXE core to function
+ Only used in Debug Builds
+
+ Arguments:
+ NONE
+
+ Returns:
+ NONE
+
+ --*/;
+
+ VOID
+ CoreDisplayDiscoveredNotDispatched (
+ VOID
+ )
+ /*++
+
+ Routine Description:
+
+ Traverse the discovered list for any drivers that were discovered but not loaded
+ because the dependency experessions evaluated to false
+
+ Arguments:
+
+ NONE
+
+ Returns:
+
+ NONE
+
+ --*/;
+)
+#endif
diff --git a/Core/CORE_DXE/DxeMain.c b/Core/CORE_DXE/DxeMain.c
new file mode 100644
index 0000000..8c38168
--- /dev/null
+++ b/Core/CORE_DXE/DxeMain.c
@@ -0,0 +1,1065 @@
+/*++
+
+Copyright (c) 2004 - 2009, 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:
+
+ DxeMain.c
+
+Abstract:
+
+ DXE Core Main Entry Point
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiHobLib.h"
+#include "EfiPerf.h"
+#include "FwVolBlock.h"
+
+
+VOID
+EFIAPI
+DxeMain (
+ IN VOID *HobStart
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg0 (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg1 (
+ UINTN Arg1
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg2 (
+ UINTN Arg1,
+ UINTN Arg2
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg3 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg4 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4
+ );
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg5 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4,
+ UINTN Arg5
+ );
+
+EFI_STATUS
+CoreGetPeiProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ IN VOID **Interface
+ );
+
+PERF_CODE (
+ EFI_STATUS
+ GetTimerValue (
+ OUT UINT64 *TimerValue
+ );
+)
+
+//*** AMI PORTING BEGIN ***//
+VOID AmiDxeInit0();
+VOID AmiDxeInit1();
+VOID AmiDxeInit2();
+VOID checkpoint(UINT8);
+EFI_STATUS AmiResetNotAvailableYet(
+ IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize, IN CHAR16 *ResetData OPTIONAL
+);
+VOID AmiReportArhcProtocolMissingError();
+//*** AMI PORTING END *****//
+
+//
+// DXE Core Global Variables for Protocols from PEI
+//
+EFI_DECOMPRESS_PROTOCOL *gEfiDecompress = NULL;
+EFI_TIANO_DECOMPRESS_PROTOCOL *gEfiTianoDecompress = NULL;
+EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *gEfiCustomizedDecompress = NULL;
+EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *gEfiPeiFlushInstructionCache = NULL;
+EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader = NULL;
+EFI_PEI_TRANSFER_CONTROL_PROTOCOL *gEfiPeiTransferControl = NULL;
+
+//
+// DXE Core globals for Architecture Protocols
+//
+EFI_SECURITY_ARCH_PROTOCOL *gSecurity = NULL;
+//*** AMI PORTING BEGIN ***//
+EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2 = NULL;
+//*** AMI PORTING END ***//
+EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
+EFI_METRONOME_ARCH_PROTOCOL *gMetronome = NULL;
+EFI_TIMER_ARCH_PROTOCOL *gTimer = NULL;
+EFI_BDS_ARCH_PROTOCOL *gBds = NULL;
+EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer = NULL;
+
+//
+// DXE Core Global used to update core loaded image protocol handle
+//
+EFI_GUID *gDxeCoreFileName;
+EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage;
+
+//
+// BugBug: I'n not runtime, but is the PPI?
+//
+EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = {
+ NULL
+};
+
+EFI_STATUS_CODE_PROTOCOL *gStatusCode = &gStatusCodeInstance;
+
+//
+// DXE Core Module Variables
+//
+
+EFI_BOOT_SERVICES mBootServices = {
+ {
+ EFI_BOOT_SERVICES_SIGNATURE, // Signature
+ EFI_BOOT_SERVICES_REVISION, // Revision
+ sizeof (EFI_BOOT_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_RAISE_TPL) CoreRaiseTpl, // RaiseTPL
+ (EFI_RESTORE_TPL) CoreRestoreTpl, // RestoreTPL
+ (EFI_ALLOCATE_PAGES) CoreAllocatePages, // AllocatePages
+ (EFI_FREE_PAGES) CoreFreePages, // FreePages
+ (EFI_GET_MEMORY_MAP) CoreGetMemoryMap, // GetMemoryMap
+ (EFI_ALLOCATE_POOL) CoreAllocatePool, // AllocatePool
+ (EFI_FREE_POOL) CoreFreePool, // FreePool
+ (EFI_CREATE_EVENT) CoreCreateEvent, // CreateEvent
+ (EFI_SET_TIMER) CoreSetTimer, // SetTimer
+ (EFI_WAIT_FOR_EVENT) CoreWaitForEvent, // WaitForEvent
+ (EFI_SIGNAL_EVENT) CoreSignalEvent, // SignalEvent
+ (EFI_CLOSE_EVENT) CoreCloseEvent, // CloseEvent
+ (EFI_CHECK_EVENT) CoreCheckEvent, // CheckEvent
+ (EFI_INSTALL_PROTOCOL_INTERFACE) CoreInstallProtocolInterface, // InstallProtocolInterface
+ (EFI_REINSTALL_PROTOCOL_INTERFACE) CoreReinstallProtocolInterface, // ReinstallProtocolInterface
+ (EFI_UNINSTALL_PROTOCOL_INTERFACE) CoreUninstallProtocolInterface, // UninstallProtocolInterface
+ (EFI_HANDLE_PROTOCOL) CoreHandleProtocol, // HandleProtocol
+ (VOID *) NULL, // Reserved
+ (EFI_REGISTER_PROTOCOL_NOTIFY) CoreRegisterProtocolNotify, // RegisterProtocolNotify
+ (EFI_LOCATE_HANDLE) CoreLocateHandle, // LocateHandle
+ (EFI_LOCATE_DEVICE_PATH) CoreLocateDevicePath, // LocateDevicePath
+ (EFI_INSTALL_CONFIGURATION_TABLE) CoreInstallConfigurationTable, // InstallConfigurationTable
+ (EFI_IMAGE_LOAD) CoreLoadImage, // LoadImage
+ (EFI_IMAGE_START) CoreStartImage, // StartImage
+ (EFI_EXIT) CoreExit, // Exit
+ (EFI_IMAGE_UNLOAD) CoreUnloadImage, // UnloadImage
+ (EFI_EXIT_BOOT_SERVICES) CoreExitBootServices, // ExitBootServices
+ (EFI_GET_NEXT_MONOTONIC_COUNT) CoreEfiNotAvailableYetArg1, // GetNextMonotonicCount
+ (EFI_STALL) CoreStall, // Stall
+ (EFI_SET_WATCHDOG_TIMER) CoreSetWatchdogTimer, // SetWatchdogTimer
+ (EFI_CONNECT_CONTROLLER) CoreConnectController, // ConnectController
+ (EFI_DISCONNECT_CONTROLLER) CoreDisconnectController, // DisconnectController
+ (EFI_OPEN_PROTOCOL) CoreOpenProtocol, // OpenProtocol
+ (EFI_CLOSE_PROTOCOL) CoreCloseProtocol, // CloseProtocol
+ (EFI_OPEN_PROTOCOL_INFORMATION) CoreOpenProtocolInformation, // OpenProtocolInformation
+ (EFI_PROTOCOLS_PER_HANDLE) CoreProtocolsPerHandle, // ProtocolsPerHandle
+ (EFI_LOCATE_HANDLE_BUFFER) CoreLocateHandleBuffer, // LocateHandleBuffer
+ (EFI_LOCATE_PROTOCOL) CoreLocateProtocol, // LocateProtocol
+ (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreInstallMultipleProtocolInterfaces, // InstallMultipleProtocolInterfaces
+ (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreUninstallMultipleProtocolInterfaces, // UninstallMultipleProtocolInterfaces
+ (EFI_CALCULATE_CRC32) CoreEfiNotAvailableYetArg3, // CalculateCrc32
+ (EFI_COPY_MEM) EfiCommonLibCopyMem, // CopyMem
+ (EFI_SET_MEM) EfiCommonLibSetMem // SetMem
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ ,
+ //
+ // UEFI 2.0 Extension to the table
+ //
+ (EFI_CREATE_EVENT_EX) CoreCreateEventEx
+#endif
+};
+
+EFI_DXE_SERVICES mDxeServices = {
+ {
+ EFI_DXE_SERVICES_SIGNATURE, // Signature
+ EFI_DXE_SERVICES_REVISION, // Revision
+ sizeof (EFI_DXE_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_ADD_MEMORY_SPACE) CoreAddMemorySpace, // AddMemorySpace
+ (EFI_ALLOCATE_MEMORY_SPACE) CoreAllocateMemorySpace, // AllocateMemorySpace
+ (EFI_FREE_MEMORY_SPACE) CoreFreeMemorySpace, // FreeMemorySpace
+ (EFI_REMOVE_MEMORY_SPACE) CoreRemoveMemorySpace, // RemoveMemorySpace
+ (EFI_GET_MEMORY_SPACE_DESCRIPTOR) CoreGetMemorySpaceDescriptor, // GetMemorySpaceDescriptor
+ (EFI_SET_MEMORY_SPACE_ATTRIBUTES) CoreSetMemorySpaceAttributes, // SetMemorySpaceAttributes
+ (EFI_GET_MEMORY_SPACE_MAP) CoreGetMemorySpaceMap, // GetMemorySpaceMap
+ (EFI_ADD_IO_SPACE) CoreAddIoSpace, // AddIoSpace
+ (EFI_ALLOCATE_IO_SPACE) CoreAllocateIoSpace, // AllocateIoSpace
+ (EFI_FREE_IO_SPACE) CoreFreeIoSpace, // FreeIoSpace
+ (EFI_REMOVE_IO_SPACE) CoreRemoveIoSpace, // RemoveIoSpace
+ (EFI_GET_IO_SPACE_DESCRIPTOR) CoreGetIoSpaceDescriptor, // GetIoSpaceDescriptor
+ (EFI_GET_IO_SPACE_MAP) CoreGetIoSpaceMap, // GetIoSpaceMap
+ (EFI_DISPATCH) CoreDispatcher, // Dispatch
+ (EFI_SCHEDULE) CoreSchedule, // Schedule
+ (EFI_TRUST) CoreTrust, // Trust
+ (EFI_PROCESS_FIRMWARE_VOLUME) CoreProcessFirmwareVolume, // ProcessFirmwareVolume
+};
+
+EFI_SYSTEM_TABLE mEfiSystemTableTemplate = {
+ {
+ EFI_SYSTEM_TABLE_SIGNATURE, // Signature
+ EFI_SYSTEM_TABLE_REVISION, // Revision
+ sizeof (EFI_SYSTEM_TABLE), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ NULL, // FirmwareVendor
+ 0, // FirmwareRevision
+ NULL, // ConsoleInHandle
+ NULL, // ConIn
+ NULL, // ConsoleOutHandle
+ NULL, // ConOut
+ NULL, // StandardErrorHandle
+ NULL, // StdErr
+ NULL, // RuntimeServices
+ &mBootServices, // BootServices
+ 0, // NumberOfConfigurationTableEntries
+ NULL // ConfigurationTable
+};
+
+EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = {
+ {
+ EFI_RUNTIME_SERVICES_SIGNATURE, // Signature
+ EFI_RUNTIME_SERVICES_REVISION, // Revision
+ sizeof (EFI_RUNTIME_SERVICES), // HeaderSize
+ 0, // CRC32
+ 0 // Reserved
+ },
+ (EFI_GET_TIME) CoreEfiNotAvailableYetArg2, // GetTime
+ (EFI_SET_TIME) CoreEfiNotAvailableYetArg1, // SetTime
+ (EFI_GET_WAKEUP_TIME) CoreEfiNotAvailableYetArg3, // GetWakeupTime
+ (EFI_SET_WAKEUP_TIME) CoreEfiNotAvailableYetArg2, // SetWakeupTime
+ (EFI_SET_VIRTUAL_ADDRESS_MAP) CoreEfiNotAvailableYetArg4, // SetVirtualAddressMap
+ (EFI_CONVERT_POINTER) CoreEfiNotAvailableYetArg2, // ConvertPointer
+ (EFI_GET_VARIABLE) CoreEfiNotAvailableYetArg5, // GetVariable
+ (EFI_GET_NEXT_VARIABLE_NAME) CoreEfiNotAvailableYetArg3, // GetNextVariableName
+ (EFI_SET_VARIABLE) CoreEfiNotAvailableYetArg5, // SetVariable
+ (EFI_GET_NEXT_HIGH_MONO_COUNT) CoreEfiNotAvailableYetArg1, // GetNextHighMonotonicCount
+//*** AMI PORTING BEGIN ***//
+// Replace standard dummy routine with a customized one,
+// which reports error code when called
+// (EFI_RESET_SYSTEM) CoreEfiNotAvailableYetArg4, // ResetSystem
+ (EFI_RESET_SYSTEM) AmiResetNotAvailableYet, // ResetSystem
+//*** AMI PORTING END *****//
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule
+ (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities
+ (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo
+#elif (TIANO_RELEASE_VERSION != 0)
+ (EFI_REPORT_STATUS_CODE) CoreEfiNotAvailableYetArg5 // ReportStatusCode
+#endif
+};
+
+EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate = {
+ INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.ImageHead),
+ INITIALIZE_LIST_HEAD_VARIABLE (gRuntimeTemplate.EventHead),
+
+ //
+ // Make sure Size != sizeof (EFI_MEMORY_DESCRIPTOR). This will
+ // prevent people from having pointer math bugs in their code.
+ // now you have to use *DescriptorSize to make things work.
+ //
+ sizeof (EFI_MEMORY_DESCRIPTOR) + sizeof (UINT64) - (sizeof (EFI_MEMORY_DESCRIPTOR) % sizeof (UINT64)),
+ EFI_MEMORY_DESCRIPTOR_VERSION,
+ 0,
+ NULL,
+ NULL,
+ FALSE,
+ FALSE
+};
+
+EFI_RUNTIME_ARCH_PROTOCOL *gRuntime = &gRuntimeTemplate;
+
+//
+// DXE Core Global Variables for the EFI System Table, Boot Services Table,
+// DXE Services Table, and Runtime Services Table
+//
+EFI_BOOT_SERVICES *gBS = &mBootServices;
+EFI_DXE_SERVICES *gDS = &mDxeServices;
+EFI_SYSTEM_TABLE *gST = NULL;
+
+//
+// For debug initialize gRT to template. gRT must be allocated from RT memory
+// but gRT is used for ASSERT () and DEBUG () type macros so lets give it
+// a value that will not cause debug infrastructure to crash early on.
+//
+EFI_RUNTIME_SERVICES *gRT = &mEfiRuntimeServicesTableTemplate;
+EFI_HANDLE gDxeCoreImageHandle;
+
+VOID *mHobStart;
+
+//
+// Main entry point to the DXE Core
+//
+EFI_DXE_ENTRY_POINT (DxeMain)
+
+VOID
+EFIAPI
+DxeMain (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Main entry point to DXE Core.
+
+Arguments:
+
+ HobStart - Pointer to the beginning of the HOB List from PEI
+
+Returns:
+
+ This function should never return
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DecompressHandle;
+ EFI_PHYSICAL_ADDRESS MemoryBaseAddress;
+ UINT64 MemoryLength;
+
+#ifdef EFI_DXE_PERFORMANCE
+ UINT64 Tick;
+
+ GetTimerValue (&Tick);
+#endif
+
+
+ mHobStart = HobStart;
+//*** AMI PORTING BEGIN ***//
+ AmiDxeInit0();
+//*** AMI PORTING END *****//
+ //
+ // Initialize Memory Services
+ //
+ CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
+
+ //
+ // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
+ // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
+ //
+ gST = CoreAllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
+ ASSERT (gST != NULL);
+
+ gRT = CoreAllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
+ ASSERT (gRT != NULL);
+
+ gST->RuntimeServices = gRT;
+
+//*** AMI PORTING BEGIN ***//
+ AmiDxeInit1();
+//*** AMI PORTING END *****//
+
+ //
+ // Start the Image Services.
+ //
+ Status = CoreInitializeImageServices (HobStart);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the Global Coherency Domain Services
+ //
+ Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The HobStart is relocated in gcd service init. Sync mHobStart variable.
+ //
+ mHobStart = HobStart;
+
+ //
+ // Install the DXE Services Table into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDS);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the HOB List into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Memory Type Information Table into the EFI System Tables's Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the ReportStatusCode with PEI version, if availible
+ //
+ CoreGetPeiProtocol (&gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode->ReportStatusCode);
+#if ((TIANO_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000))
+ if (gStatusCode->ReportStatusCode != NULL) {
+ gRT->ReportStatusCode = gStatusCode->ReportStatusCode;
+ }
+#endif
+
+ //
+ // Report Status Code here for DXE_ENTRY_POINT once it is available
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT));
+
+ //
+ // Create the aligned system table pointer structure that is used by external
+ // debuggers to locate the system table... Also, install debug image info
+ // configuration table.
+ //
+ CoreInitializeDebugImageInfoTable ();
+ CoreNewDebugImageInfoEntry (
+ EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
+ gDxeCoreLoadedImage,
+ gDxeCoreImageHandle
+ );
+
+ DEBUG_CODE (
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "HOBLIST address in DXE = 0x%x\n", HobStart));
+ )
+ //
+ // Initialize the Event Services
+ //
+ Status = CoreInitializeEventServices ();
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs
+ //
+ // These Protocols are not architectural. This implementation is sharing code between
+ // PEI and DXE in order to save FLASH space. These Protocols could also be implemented
+ // as part of the DXE Core. However, that would also require the DXE Core to be ported
+ // each time a different CPU is used, a different Decompression algorithm is used, or a
+ // different Image type is used. By placing these Protocols in PEI, the DXE Core remains
+ // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform,
+ // and from CPU to CPU.
+ //
+
+ Status = CoreGetPeiProtocol (&gEfiDecompressProtocolGuid, &gEfiDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the EFI Decompress protocol for use by other DXE components
+ //
+
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = CoreGetPeiProtocol (&gEfiTianoDecompressProtocolGuid, &gEfiTianoDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the Tiano Decompress protocol for use by other DXE components
+ //
+
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiTianoDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiTianoDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = CoreGetPeiProtocol (&gEfiCustomizedDecompressProtocolGuid, &gEfiCustomizedDecompress);
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Publish the Tiano Decompress protocol for use by other DXE components
+ //
+ DecompressHandle = NULL;
+ Status = CoreInstallProtocolInterface (
+ &DecompressHandle,
+ &gEfiCustomizedDecompressProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gEfiCustomizedDecompress
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ CoreGetPeiProtocol (&gEfiPeiFlushInstructionCacheGuid, &gEfiPeiFlushInstructionCache);
+
+ CoreGetPeiProtocol (&gEfiPeiPeCoffLoaderGuid, &gEfiPeiPeCoffLoader);
+
+ CoreGetPeiProtocol (&gEfiPeiTransferControlGuid, &gEfiPeiTransferControl);
+
+
+ //
+ // Register for the GUIDs of the Architectural Protocols, so the rest of the
+ // EFI Boot Services and EFI Runtime Services tables can be filled in.
+ //
+ CoreNotifyOnArchProtocolInstallation ();
+
+ //
+ // Produce Firmware Volume Protocols, one for each FV in the HOB list.
+ //
+ Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FwVolDriverInit (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Produce the Section Extraction Protocol
+ //
+ Status = InitializeSectionExtraction (gDxeCoreImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Initialize Performance monitoring if enabled in build
+ //
+ PERF_ENABLE (0, gST, Tick);
+
+ PERF_START (0,DXE_TOK, NULL, Tick) ;
+
+//*** AMI PORTING BEGIN ***//
+ AmiDxeInit2();
+//*** AMI PORTING END *****//
+
+ //
+ // Initialize the DXE Dispatcher
+ //
+ PERF_START (0,L"CoreInitializeDispatcher", L"DxeMain", 0) ;
+ CoreInitializeDispatcher ();
+ PERF_END (0,L"CoreInitializeDispatcher", L"DxeMain", 0) ;
+
+ //
+ // Invoke the DXE Dispatcher
+ //
+ PERF_START (0, L"CoreDispatcher", L"DxeMain", 0);
+ CoreDispatcher ();
+ PERF_END (0, L"CoreDispatcher", L"DxeMain", 0);
+
+ //
+ // Display Architectural protocols that were not loaded if this is DEBUG build
+ //
+ DEBUG_CODE (
+ CoreDisplayMissingArchProtocols ();
+ )
+
+ //
+ // Assert if the Architectural Protocols are not present.
+ //
+//*** AMI PORTING BEGIN ***//
+//Report "Architectural Protocol Missing" error
+ //ASSERT_EFI_ERROR (CoreAllEfiServicesAvailable ());
+ Status = CoreAllEfiServicesAvailable ();
+ if (EFI_ERROR (Status)) AmiReportArhcProtocolMissingError();
+ ASSERT_EFI_ERROR (Status);
+//*** AMI PORTING END *****//
+
+
+ //
+ // Report Status code before transfer control to BDS
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT));
+
+ //
+ // Display any drivers that were not dispatched because dependency expression
+ // evaluated to false if this is a debug build
+ //
+ DEBUG_CODE (
+ CoreDisplayDiscoveredNotDispatched ();
+ )
+
+ //
+ // Transfer control to the BDS Architectural Protocol
+ //
+ gBds->Entry (gBds);
+
+ //
+ // BDS should never return
+ //
+ ASSERT (FALSE);
+ EFI_DEADLOOP ();
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg0 (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg1 (
+ UINTN Arg1
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg2 (
+ UINTN Arg1,
+ UINTN Arg2
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg3 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg4 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+ Arg4 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+EFI_STATUS
+EFIAPI
+CoreEfiNotAvailableYetArg5 (
+ UINTN Arg1,
+ UINTN Arg2,
+ UINTN Arg3,
+ UINTN Arg4,
+ UINTN Arg5
+ )
+/*++
+
+Routine Description:
+
+ Place holder function until all the Boot Services and Runtime Services are available
+
+Arguments:
+
+ Arg1 - Undefined
+
+ Arg2 - Undefined
+
+ Arg3 - Undefined
+
+ Arg4 - Undefined
+
+ Arg5 - Undefined
+
+Returns:
+
+ EFI_NOT_AVAILABLE_YET
+
+--*/
+{
+ //
+ // This function should never be executed. If it does, then the architectural protocols
+ // have not been designed correctly. The EFI_BREAKPOINT() is commented out for now until the
+ // DXE Core and all the Architectural Protocols are complete.
+ //
+
+ return EFI_NOT_AVAILABLE_YET;
+}
+
+
+EFI_STATUS
+CoreGetPeiProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ IN VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Searches for a Protocol Interface passed from PEI through a HOB
+
+Arguments:
+
+ ProtocolGuid - The Protocol GUID to search for in the HOB List
+
+ Interface - A pointer to the interface for the Protocol GUID
+
+Returns:
+
+ EFI_SUCCESS - The Protocol GUID was found and its interface is returned in Interface
+
+ EFI_NOT_FOUND - The Protocol GUID was not found in the HOB List
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ VOID *Buffer;
+
+ HobList = mHobStart;
+ Status = GetNextGuidHob (&HobList, ProtocolGuid, &Buffer, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ *Interface = (VOID *)(*(UINTN *)(Buffer));
+
+ return Status;
+}
+
+
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+/*++
+
+Routine Description:
+
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+Arguments:
+
+ Hdr - Pointer to an EFI standard header
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT32 Crc;
+
+ Hdr->CRC32 = 0;
+
+ //
+ // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
+ // Crc will come back as zero if we set it to zero here
+ //
+ Crc = 0;
+ gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);
+ Hdr->CRC32 = Crc;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreExitBootServices (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Terminates all boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the exiting image.
+ MapKey - Key to the latest memory map.
+
+Returns:
+
+ EFI_SUCCESS - Boot services have been terminated.
+ EFI_INVALID_PARAMETER - MapKey is incorrect.
+
+--*/
+{
+ EFI_STATUS Status, Status2;
+ EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;
+//*** AMI PORTING BEGIN ***//
+// EIP 58707: Updated to reflect changes introduced in UEFI spec v2.3.1 section 6.4.
+// 1. The callback functions are to be called once
+// (even if ExitBootServices is called more than once).
+// 2. The memory map must be validated after the execution of the callback functions
+// (CoreTerminateMemoryMap call).
+ static BOOLEAN FirstCall = TRUE;
+//*** AMI PORTING END ***//
+
+ //
+ // Measure invocation of ExitBootServices,
+ // which is defined by TCG_EFI_Platform_1_20_Final Specification
+ //
+ TcgPlatformProtocol = NULL;
+ Status = CoreLocateProtocol (
+ &gEfiTcgPlatformProtocolGuid,
+ NULL,
+ &TcgPlatformProtocol
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_INVOCATION);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+//*** AMI PORTING BEGIN ***//
+// See comments at the beginning of the function.
+ if (FirstCall) {
+
+ AmiFillFpdt (FillExitBootServicesEntry); // Fill ExitBootServicesEntry field in FPDT
+ //
+ // Disable Timer
+ //
+ gTimer->SetTimerPeriod (gTimer, 0);
+
+ //
+ // Notify other drivers that we are exiting boot services.
+ //
+ CoreNotifySignalList (&gEfiEventExitBootServicesGuid);
+
+ FirstCall = FALSE;
+ }
+//*** AMI PORTING END ***//
+
+ //
+ // Terminate memory services if the MapKey matches
+ //
+ Status = CoreTerminateMemoryMap (MapKey);
+ if (EFI_ERROR (Status)) {
+ //
+ // Measure failure of ExitBootServices
+ //
+ if (TcgPlatformProtocol != NULL) {
+ Status2 = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_FAILED);
+ ASSERT_EFI_ERROR (Status2);
+ }
+
+ return Status;
+ }
+//*** AMI PORTING BEGIN ***//
+// These two calls have been moved above.
+// See comments at the beginning of the function.
+ //
+ // Disable Timer
+ //
+// gTimer->SetTimerPeriod (gTimer, 0);
+
+
+ //
+ // Notify other drivers that we are exiting boot services.
+ //
+// CoreNotifySignalList (&gEfiEventExitBootServicesGuid);
+//*** AMI PORTING END ***//
+
+
+ //
+ // Disable CPU Interrupts
+ //
+ gCpu->DisableInterrupt (gCpu);
+
+ //
+ // Report that ExitBootServices() has been called
+ //
+ // We are using gEfiDxeServicesTableGuid as the caller ID for Dxe Core
+ //
+ CoreReportProgressCode ((EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES));
+
+ //
+ // Clear the non-runtime values of the EFI System Table
+ //
+ gST->BootServices = NULL;
+ gST->ConIn = NULL;
+ gST->ConsoleInHandle = NULL;
+ gST->ConOut = NULL;
+ gST->ConsoleOutHandle = NULL;
+ gST->StdErr = NULL;
+ gST->StandardErrorHandle = NULL;
+
+ //
+ // Recompute the 32-bit CRC of the EFI System Table
+ //
+ CalculateEfiHdrCrc (&gST->Hdr);
+
+ //
+ // Update the AtRuntime field in Runtiem AP.
+ //
+ gRuntime->AtRuntime = TRUE;
+
+ //
+ // Measure success of ExitBootServices
+ //
+ if (TcgPlatformProtocol != NULL) {
+ Status2 = TcgPlatformProtocol->MeasureAction (EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
+ ASSERT_EFI_ERROR (Status2);
+ }
+
+ //
+ // Zero out the Boot Service Table
+ //
+ EfiCommonLibSetMem (gBS, sizeof (EFI_BOOT_SERVICES), 0);
+ gBS = NULL;
+//*** AMI PORTING BEGIN ***//
+ AmiFillFpdt (FillExitBootServicesExit); // Fill ExitBootServicesExit field in FPDT
+//*** AMI PORTING END ***//
+
+ return Status;
+}
diff --git a/Core/CORE_DXE/DxePerf.c b/Core/CORE_DXE/DxePerf.c
new file mode 100644
index 0000000..6e744f4
--- /dev/null
+++ b/Core/CORE_DXE/DxePerf.c
@@ -0,0 +1,813 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ Perf.c
+
+Abstract:
+
+ Support for Performance primatives.
+
+--*/
+
+
+#include <Efi.h>
+#include <Tiano.h>
+#include <AmiLib.h>
+#include <AmiDxeLib.h>
+#include <Dxe.h>
+#include <Hob.h>
+#include <EfiHobLib.h>
+#include <EfiCommonLib.h>
+#include <EfiImage.h>
+#include <Protocol\LoadedImage.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\Cpu.h>
+#include <AmiHobs.h>
+#include "EfiPerf.h"
+#include "linkedlist.h"
+
+#define EFI_NULL_GUID \
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+
+EFI_STATUS
+GetTimerValue (
+ OUT UINT64 *TimerValue
+ )
+{
+ *TimerValue = GetCpuTimer();
+ return EFI_SUCCESS;
+}
+
+
+#define EFI_PERF_PEI_ENTRY_MAX_NUM 50
+
+typedef struct {
+ CHAR8 Token[EFI_PERF_PDBFILENAME_LENGTH];
+ UINT32 Duration;
+} EFI_PERF_DATA;
+
+typedef struct {
+ UINT64 BootToOs;
+ UINT64 S3Resume;
+ UINT32 S3EntryNum;
+ EFI_PERF_DATA S3Entry[EFI_PERF_PEI_ENTRY_MAX_NUM];
+ UINT64 CpuFreq;
+ UINT64 BDSRaw;
+ UINT32 Count;
+ UINT32 Signiture;
+} EFI_PERF_HEADER;
+
+EFI_STATUS
+GetPeiPerformance (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT64 Ticker
+ );
+
+#define EFI_PERFORMANCE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'D', 'A')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_LIST_ENTRY Link;
+ EFI_GAUGE_DATA GaugeData;
+} EFI_PERF_DATA_LIST;
+
+#define GAUGE_DATA_FROM_LINK(_link) \
+ CR(_link, EFI_PERF_DATA_LIST, Link, EFI_PERFORMANCE_DATA_SIGNATURE)
+
+#define GAUGE_DATA_FROM_GAUGE(_GaugeData) \
+ CR(_GaugeData, EFI_PERF_DATA_LIST, GaugeData, EFI_PERFORMANCE_DATA_SIGNATURE)
+
+#define EFI_PERFORMANCE_SIGNATURE EFI_SIGNATURE_32 ('P', 'E', 'R', 'F')
+
+//
+// Performance protocol instance data structure
+//
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_PERFORMANCE_PROTOCOL Perf;
+ UINT8 Phase;
+} EFI_PERFORMANCE_INSTANCE;
+
+//
+// Performace protocol instance containing record macro
+//
+
+#define EFI_PERFORMANCE_FROM_THIS(a) \
+ CR(a, EFI_PERFORMANCE_INSTANCE, Perf, EFI_PERFORMANCE_SIGNATURE)
+
+EFI_LIST_ENTRY mPerfDataHead = INITIALIZE_LIST_HEAD_VARIABLE(mPerfDataHead);
+
+BOOLEAN GetImageName(EFI_HANDLE ImageHandle, CHAR8 *sName);
+
+STATIC
+VOID
+GetShortPdbFileName (
+ CHAR8 *PdbFileName,
+ CHAR8 *GaugeString
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Index;
+ UINTN Index1;
+ UINTN StartIndex;
+ UINTN EndIndex;
+
+ if (PdbFileName == NULL) {
+ EfiAsciiStrCpy (GaugeString, " ");
+ } else {
+ StartIndex = 0;
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+ ;
+
+ for (Index = 0; PdbFileName[Index] != 0; Index++) {
+ if (PdbFileName[Index] == '\\') {
+ StartIndex = Index + 1;
+ }
+
+ if (PdbFileName[Index] == '.') {
+ EndIndex = Index;
+ }
+ }
+
+ Index1 = 0;
+ for (Index = StartIndex; Index < EndIndex; Index++) {
+ GaugeString[Index1] = PdbFileName[Index];
+ Index1++;
+ if (Index1 == EFI_PERF_PDBFILENAME_LENGTH - 1) {
+ break;
+ }
+ }
+
+ GaugeString[Index1] = 0;
+ }
+
+ return ;
+}
+
+STATIC
+CHAR8 *
+GetPdbPath (
+ VOID *ImageBase
+ )
+/*++
+
+Routine Description:
+
+ Located PDB path name in PE image
+
+Arguments:
+
+ ImageBase - base of PE to search
+
+Returns:
+
+ Pointer into image at offset of PDB file name if PDB file name is found,
+ Otherwise a pointer to an empty string.
+
+--*/
+{
+ CHAR8 *PdbPath;
+ UINT32 DirCount;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS *NtHdr;
+ EFI_IMAGE_OPTIONAL_HEADER *OptionalHdr;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ VOID *CodeViewEntryPointer;
+
+ CodeViewEntryPointer = NULL;
+ PdbPath = NULL;
+ DosHdr = ImageBase;
+
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ NtHdr = (EFI_IMAGE_NT_HEADERS *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
+ OptionalHdr = (VOID *) &NtHdr->OptionalHeader;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ if (DirectoryEntry->VirtualAddress != 0) {
+ for (DirCount = 0;
+ (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
+ DirCount++
+ ) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
+ switch (*(UINT32 *) CodeViewEntryPointer) {
+ case CODEVIEW_SIGNATURE_NB10:
+ PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+
+ case CODEVIEW_SIGNATURE_RSDS:
+ PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return PdbPath;
+}
+
+STATIC
+VOID
+GetNameFromHandle (
+ IN EFI_HANDLE Handle,
+ OUT CHAR8 *GaugeString
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ CHAR8 *PdbFileName;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+ EfiAsciiStrCpy (GaugeString, " ");
+
+ //
+ // Get handle name from image protocol
+ //
+ Status = pBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&Image
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = pBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ //
+ // Get handle name from image protocol
+ //
+ Status = pBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&Image
+ );
+ }
+
+ PdbFileName = GetPdbPath (Image->ImageBase);
+
+ if (PdbFileName != NULL) {
+ GetShortPdbFileName (PdbFileName, GaugeString);
+ }
+
+ return ;
+}
+
+EFI_PERF_DATA_LIST *
+CreateDataNode (
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host
+ )
+/*++
+
+Routine Description:
+
+ Create a EFI_PERF_DATA_LIST data node.
+
+Arguments:
+
+ Handle - Handle of gauge data
+ Token - Token of gauge data
+ Host - Host of gauge data
+
+Returns:
+
+ Pointer to a data node created.
+
+--*/
+{
+ EFI_PERF_DATA_LIST *Node;
+
+ //
+ // Al\ a new image structure
+ //
+
+ Node = MallocZ (sizeof (EFI_PERF_DATA_LIST));
+
+ if (Node != NULL) {
+
+ Node->Signature = EFI_PERFORMANCE_DATA_SIGNATURE;
+
+ Node->GaugeData.Handle = Handle;
+
+ if (Token != NULL) {
+ EfiStrCpy ((Node->GaugeData).Token, Token);
+ }
+
+ if (Host != NULL) {
+ EfiStrCpy ((Node->GaugeData).Host, Host);
+ }
+
+ if (Handle != NULL) {
+ GetImageName (Handle, Node->GaugeData.PdbFileName);
+ }
+ }
+
+ return Node;
+}
+
+
+EFI_PERF_DATA_LIST *
+GetDataNode (
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN EFI_GUID *GuidName,
+ IN EFI_GAUGE_DATA *PrevGauge
+ )
+/*++
+
+Routine Description:
+
+ Search gauge node list to find one node with matched handle, token, host and Guid name.
+
+Arguments:
+
+ Handle - Handle to match
+ Token - Token to match
+ Host - Host to match
+ GuidName - Guid name to match
+ PrevGauge - Start node, start from list head if NULL
+
+Returns:
+
+ Return pointer to the node found, NULL if not found.
+
+--*/
+{
+ EFI_PERF_DATA_LIST *Node;
+ EFI_PERF_DATA_LIST *Temp;
+ EFI_PERF_DATA_LIST *Temp2;
+ EFI_LIST_ENTRY *CurrentLink;
+ EFI_GUID NullGuid = EFI_NULL_GUID;
+
+ Node = NULL;
+ Temp = NULL;
+ Temp2 = NULL;
+
+ if (PrevGauge == NULL) {
+ CurrentLink = mPerfDataHead.ForwardLink;
+ } else {
+ Temp2 = GAUGE_DATA_FROM_GAUGE (PrevGauge);
+ CurrentLink = (Temp2->Link).ForwardLink;
+ }
+
+ while (CurrentLink && CurrentLink != &mPerfDataHead) {
+ Node = GAUGE_DATA_FROM_LINK (CurrentLink);
+
+ if (Handle == 0 && Token == NULL && Host == NULL && GuidName == NULL) {
+ return Node;
+ }
+
+ if (Handle != (Node->GaugeData).Handle) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (GuidName == NULL && !EfiCompareGuid (&((Node->GaugeData).GuidName), &NullGuid)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (GuidName && !EfiCompareGuid (&((Node->GaugeData).GuidName), GuidName)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (Token == NULL && EfiStrCmp (Node->GaugeData.Token, L"")) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (Token && EfiStrCmp (Node->GaugeData.Token, Token)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (Host == NULL && EfiStrCmp (Node->GaugeData.Host, L"")) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if (Host && EfiStrCmp (Node->GaugeData.Host, Host)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ Temp = Node;
+ break;
+ }
+
+ return Temp;
+}
+
+
+EFI_STATUS
+EFIAPI
+StartGauge (
+ IN EFI_PERFORMANCE_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Create a guage data node and initialized it.
+
+Arguments:
+
+ This - Calling context
+ Handle - Handle of gauge data
+ Token - Token of gauge data
+ Host - Host of gauge data
+ Ticker - Set gauge data's StartTick. If 0, StartTick is current timer.
+
+Returns:
+
+ EFI_SUCCESS - Successfully create and initialized a guage data node.
+ EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node.
+
+--*/
+{
+ EFI_PERFORMANCE_INSTANCE *PerfInstance;
+ EFI_PERF_DATA_LIST *Node;
+ UINT64 TimerValue;
+
+ TimerValue = 0;
+ PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
+
+ Node = CreateDataNode (Handle, Token, Host);
+ if (!Node) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Ticker != 0) {
+ TimerValue = Ticker;
+ } else {
+// GetTimerValue (&TimerValue);
+ TimerValue = GetCpuTimer();
+ }
+
+ Node->GaugeData.StartTick = TimerValue;
+
+ if (!EfiStrCmp (Token, DXE_TOK)) {
+ PerfInstance->Phase = DXE_PHASE;
+ }
+
+ if (!EfiStrCmp (Token, SHELL_TOK)) {
+ PerfInstance->Phase = SHELL_PHASE;
+ }
+
+ Node->GaugeData.Phase = PerfInstance->Phase;
+
+ InsertTailList (&mPerfDataHead, &(Node->Link));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+EndGauge (
+ IN EFI_PERFORMANCE_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ End all unfinished gauge data node that match specified handle, token and host.
+
+Arguments:
+
+ This - Calling context
+ Handle - Handle to stop
+ Token - Token to stop
+ Host - Host to stop
+ Ticker - End tick, if 0 then get current timer
+
+Returns:
+
+ EFI_NOT_FOUND - Node not found
+ EFI_SUCCESS - Gauge data node successfully ended.
+
+--*/
+{
+ EFI_PERFORMANCE_INSTANCE *PerfInstance;
+ EFI_PERF_DATA_LIST *Node;
+ UINT64 TimerValue;
+
+ TimerValue = 0;
+ PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
+
+ Node = GetDataNode (Handle, Token, Host, NULL, NULL);
+ if (!Node) {
+ return EFI_NOT_FOUND;
+ }
+
+ while (Node->GaugeData.EndTick != 0) {
+ Node = GetDataNode (Handle, Token, Host, NULL, &(Node->GaugeData));
+ if (!Node) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (Ticker != 0) {
+ TimerValue = Ticker;
+ } else {
+// GetTimerValue (&TimerValue);
+ TimerValue = GetCpuTimer();
+ }
+
+ Node->GaugeData.EndTick = TimerValue;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_GAUGE_DATA *
+EFIAPI
+GetGauge (
+ IN EFI_PERFORMANCE_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN EFI_GAUGE_DATA *PrevGauge
+ )
+/*++
+
+Routine Description:
+ Get gauge.
+
+Arguments:
+ This - A pointer to the EFI_PERFORMANCE_PROTOCOL.
+ Handle - A pointer of a efi handle.
+ Token - A pointer to the token.
+ Host - A pointer to the host.
+ PrevGauge - A pointer to the EFI_GAUGE_DATA structure.
+
+
+Returns:
+ Status code.
+
+--*/
+{
+ EFI_PERFORMANCE_INSTANCE *PerfInstance;
+ EFI_PERF_DATA_LIST *Node;
+
+ PerfInstance = EFI_PERFORMANCE_FROM_THIS (This);
+
+ Node = GetDataNode (Handle, Token, Host, NULL, PrevGauge);
+ if (Node != NULL) {
+ return &(Node->GaugeData);
+ } else {
+ return NULL;
+ }
+}
+
+//
+// Driver entry point
+//
+EFI_STATUS
+InitializePerformanceInfrastructure (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Install gEfiPerformanceProtocolGuid protocol and transfer PEI performance to gauge data nodes.
+
+Arguments:
+
+ ImageHandle - Standard driver entry point parameter
+ SystemTable - Standard driver entry point parameter
+ Ticker - End tick for PEI performance
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+ EFI_SUCCESS - Protocol installed.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PERFORMANCE_INSTANCE *PerfInstance;
+
+ //
+ // Allocate a new image structure
+ //
+ PerfInstance = MallocZ (sizeof (EFI_PERFORMANCE_INSTANCE));
+ if (PerfInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PerfInstance->Signature = EFI_PERFORMANCE_SIGNATURE;
+ PerfInstance->Perf.StartGauge = StartGauge;
+ PerfInstance->Perf.EndGauge = EndGauge;
+ PerfInstance->Perf.GetGauge = GetGauge;
+
+ //
+ // Install the protocol interfaces
+ //
+ Status = pBS->InstallProtocolInterface (
+ &PerfInstance->Handle,
+ &gEfiPerformanceProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &PerfInstance->Perf
+ );
+
+ if (!EFI_ERROR (Status)) {
+ GetPeiPerformance (ImageHandle, SystemTable, Ticker);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+EFI_STATUS
+GetPeiPerformance (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT64 Ticker
+ )
+/*++
+
+Routine Description:
+
+ Transfer PEI performance data to gauge data node.
+
+Arguments:
+
+ ImageHandle - Standard entry point parameter
+ SystemTable - Standard entry point parameter
+ Ticker - Start tick
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough resource to create data node.
+ EFI_SUCCESS - Transfer done successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ EFI_HOB_GUID_DATA_PERFORMANCE_LOG *LogHob;
+ PEI_PERFORMANCE_MEASURE_LOG_ENTRY *LogEntry;
+ UINT32 Index;
+ EFI_PERF_DATA_LIST *Node;
+ UINT64 TimerValue;
+ EFI_GUID HobListGuid = HOB_LIST_GUID;
+ EFI_GUID PerformanceHobGuid = EFI_PEI_PERFORMANCE_HOB_GUID;
+
+ Node = CreateDataNode (0, PEI_TOK, NULL);
+ if (!Node) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Ticker != 0) {
+ TimerValue = Ticker;
+ } else {
+// GetTimerValue (&TimerValue);
+ TimerValue = GetCpuTimer();
+ }
+ (Node->GaugeData).EndTick = TimerValue;
+
+ InsertTailList (&mPerfDataHead, &(Node->Link));
+
+// EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ HobList = GetEfiConfigurationTable(pST, &HobListGuid);
+ if(HobList == NULL)
+ return EFI_NOT_FOUND;
+
+ do {
+ Status = GetNextGuidHob (&HobList, &PerformanceHobGuid, (VOID **) &LogHob, NULL);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ for (Index = 0; Index < LogHob->NumberOfEntries; Index++) {
+ LogEntry = &(LogHob->Log[Index]);
+ Node = CreateDataNode (0, LogEntry->DescriptionString, NULL);
+ if (!Node) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ (Node->GaugeData).StartTick = LogEntry->StartTimeCount;
+
+ MemCpy (&(Node->GaugeData.GuidName), &LogEntry->Name, sizeof (EFI_GUID));
+
+ InsertTailList (&mPerfDataHead, &(Node->Link));
+
+ (Node->GaugeData).EndTick = LogEntry->StopTimeCount;
+ }
+ } while (!EFI_ERROR (Status));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+UpdateMeasure (
+ EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ EFI_HANDLE HandleNew,
+ IN UINT16 *TokenNew,
+ IN UINT16 *HostNew
+ )
+/*++
+
+Routine Description:
+ Update measure.
+
+Arguments:
+ Handle - A pointer of an efi handle.
+ Token - A pointer to the token.
+ Host - A pointer to the host.
+ HandleNew - A pointer of an new efi handle.
+ TokenNew - A pointer to the new token.
+ HostNew - A pointer to the new host.
+
+Returns:
+ Status code.
+
+ EFI_NOT_FOUND - The speicified gauge data node not found.
+
+ EFI_SUCCESS - Update successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GAUGE_DATA *GaugeData;
+ EFI_PERFORMANCE_PROTOCOL *Perf;
+
+ Status = pBS->LocateProtocol (&gEfiPerformanceProtocolGuid, NULL, (VOID **) &Perf);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GaugeData = Perf->GetGauge (Perf, Handle, Token, Host, NULL);
+ if (!GaugeData) {
+ return EFI_NOT_FOUND;
+ }
+
+ GaugeData->Handle = HandleNew;
+ if (HostNew != NULL) {
+ Wcscpy (GaugeData->Host, HostNew);
+ } else {
+ Wcscpy (GaugeData->Host, L"");
+ }
+
+ if (TokenNew != NULL) {
+ Wcscpy (GaugeData->Token, TokenNew);
+ } else {
+ Wcscpy (GaugeData->Token, L"");
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Core/CORE_DXE/DxeProtocolNotify.c b/Core/CORE_DXE/DxeProtocolNotify.c
new file mode 100644
index 0000000..5d9288d
--- /dev/null
+++ b/Core/CORE_DXE/DxeProtocolNotify.c
@@ -0,0 +1,334 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ DxeProtocolNotify.c
+
+Abstract:
+
+ This file deals with Architecture Protocol (AP) registration in
+ the Dxe Core. The mArchProtocols[] array represents a list of
+ events that represent the Architectural Protocols.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+
+//
+// DXE Core Global Variables for all of the Architectural Protocols.
+// If a protocol is installed mArchProtocols[].Present will be TRUE.
+//
+// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
+// and mArchProtocols[].Registration as it creates events for every array
+// entry.
+//
+
+ARCHITECTURAL_PROTOCOL_ENTRY mArchProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, &gSecurity, NULL, NULL, FALSE},
+ { &gEfiCpuArchProtocolGuid, &gCpu, NULL, NULL, FALSE},
+ { &gEfiMetronomeArchProtocolGuid, &gMetronome, NULL, NULL, FALSE},
+ { &gEfiTimerArchProtocolGuid, &gTimer, NULL, NULL, FALSE},
+ { &gEfiBdsArchProtocolGuid, &gBds, NULL, NULL, FALSE},
+ { &gEfiWatchdogTimerArchProtocolGuid, &gWatchdogTimer, NULL, NULL, FALSE},
+ { &gEfiRuntimeArchProtocolGuid, &gRuntime, NULL, NULL, FALSE},
+ { &gEfiVariableArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiVariableWriteArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+//*** AMI PORTING BEGIN ***//
+// Make Security support optional.
+// { &gEfiCapsuleArchProtocolGuid, NULL, NULL, NULL, FALSE},
+//*** AMI PORTING END *****//
+ #endif
+ { &gEfiMonotonicCounterArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiResetArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiStatusCodeRuntimeProtocolGuid, NULL, NULL, NULL, FALSE},
+ { &gEfiRealTimeClockArchProtocolGuid, NULL, NULL, NULL, FALSE},
+ NULL
+};
+
+
+EFI_STATUS
+CoreAllEfiServicesAvailable (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE if all AP services are availible.
+
+Arguments:
+ NONE
+
+Returns:
+ EFI_SUCCESS - All AP services are available
+ EFI_NOT_FOUND - At least one AP service is not available
+
+--*/
+{
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+GenericArchProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+ Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
+ This notify function is registered for every architectural protocol. This handler
+ updates mArchProtocol[] array entry with protocol instance data and sets it's
+ present flag to TRUE. If any constructor is required it is executed. The EFI
+ System Table headers are updated.
+
+Arguments:
+
+ Event - The Event that is being processed, not used.
+
+ Context - Event Context, not used.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+ VOID *Protocol;
+ BOOLEAN Found;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY TempLinkNode;
+
+ Found = FALSE;
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+
+ Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Found = TRUE;
+ Entry->Present = TRUE;
+
+ //
+ // Update protocol global variable if one exists. Entry->Protocol points to a global variable
+ // if one exists in the DXE core for this Architectural Protocol
+ //
+ if (Entry->Protocol != NULL) {
+ *(Entry->Protocol) = Protocol;
+ }
+
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) {
+ //
+ // Register the Core timer tick handler with the Timer AP
+ //
+ gTimer->RegisterHandler (gTimer, CoreTimerTick);
+ }
+
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) {
+ //
+ // When runtime architectural protocol is available, updates CRC32 in the Debug Table
+ //
+ CoreUpdateDebugTableCrc32 ();
+
+ //
+ // Update the Runtime Architectural protocol with the template that the core was
+ // using so there would not need to be a dependency on the Runtime AP
+ //
+
+ //
+ // Copy all the registered Image to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.ImageHead.ForwardLink; Link != &gRuntimeTemplate.ImageHead; Link = TempLinkNode.ForwardLink) {
+ EfiCommonLibCopyMem (&TempLinkNode, Link, sizeof(EFI_LIST_ENTRY));
+ InsertTailList (&gRuntime->ImageHead, Link);
+ }
+ //
+ // Copy all the registered Event to new gRuntime protocol
+ //
+ for (Link = gRuntimeTemplate.EventHead.ForwardLink; Link != &gRuntimeTemplate.EventHead; Link = TempLinkNode.ForwardLink) {
+ EfiCommonLibCopyMem (&TempLinkNode, Link, sizeof(EFI_LIST_ENTRY));
+ InsertTailList (&gRuntime->EventHead, Link);
+ }
+
+ //
+ // Clean up gRuntimeTemplate
+ //
+ gRuntimeTemplate.ImageHead.ForwardLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.ImageHead.BackLink = &gRuntimeTemplate.ImageHead;
+ gRuntimeTemplate.EventHead.ForwardLink = &gRuntimeTemplate.EventHead;
+ gRuntimeTemplate.EventHead.BackLink = &gRuntimeTemplate.EventHead;
+ }
+
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiStatusCodeRuntimeProtocolGuid)) {
+ //
+ // Update StatusCode instance used by DXE core
+ //
+ gStatusCode = (EFI_STATUS_CODE_PROTOCOL *) Protocol;
+ }
+//*** AMI PORTING BEGIN ***//
+ if (EfiCompareGuid (Entry->ProtocolGuid, &gEfiSecurityArchProtocolGuid)) {
+ //
+ // Security2 Arch protocol should be available at this time
+ //
+ Status = CoreLocateProtocol (&gEfiSecurity2ArchProtocolGuid, NULL, &gSecurity2);
+ }
+//*** AMI PORTING END ***//
+ }
+
+ //
+ // It's over kill to do them all every time, but it saves a lot of code.
+ //
+ if (Found) {
+ CalculateEfiHdrCrc (&gRT->Hdr);
+ CalculateEfiHdrCrc (&gBS->Hdr);
+ CalculateEfiHdrCrc (&gST->Hdr);
+ CalculateEfiHdrCrc (&gDS->Hdr);
+ }
+}
+
+
+
+VOID
+CoreNotifyOnArchProtocolInstallation (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Creates an event that is fired everytime a Protocol of a specific type is installed
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+{
+ EFI_STATUS Status;
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+
+ //
+ // Create the event
+ //
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ GenericArchProtocolNotify,
+ NULL,
+ &Entry->Event
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+ Status = CoreRegisterProtocolNotify (
+ Entry->ProtocolGuid,
+ Entry->Event,
+ &Entry->Registration
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ }
+}
+
+#ifdef EFI_DEBUG
+//
+// Following is needed to display missing architectural protocols in debug builds
+//
+typedef struct {
+ EFI_GUID *ProtocolGuid;
+ CHAR16 *GuidString;
+} GUID_TO_STRING_PROTOCOL_ENTRY;
+
+GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = {
+ { &gEfiSecurityArchProtocolGuid, L"Security" },
+ { &gEfiCpuArchProtocolGuid, L"CPU" },
+ { &gEfiMetronomeArchProtocolGuid, L"Metronome" },
+ { &gEfiTimerArchProtocolGuid, L"Timer" },
+ { &gEfiBdsArchProtocolGuid, L"Bds" },
+ { &gEfiWatchdogTimerArchProtocolGuid, L"Watchdog Timer" },
+ { &gEfiRuntimeArchProtocolGuid, L"Runtime" },
+ { &gEfiVariableArchProtocolGuid, L"Variable" },
+ { &gEfiVariableWriteArchProtocolGuid, L"Variable Write" },
+ #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ { &gEfiCapsuleArchProtocolGuid, L"Capsule" },
+ #endif
+ { &gEfiMonotonicCounterArchProtocolGuid, L"Monotonic Counter" },
+ { &gEfiResetArchProtocolGuid, L"Reset" },
+ { &gEfiStatusCodeRuntimeProtocolGuid, L"Status Code" },
+ { &gEfiRealTimeClockArchProtocolGuid, L"Real Time Clock" }
+};
+#endif
+
+DEBUG_CODE (
+VOID
+CoreDisplayMissingArchProtocols (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Displays Architectural protocols that were not loaded and are required for DXE core to function
+ Only used in Debug Builds
+
+Arguments:
+ NONE
+
+Returns:
+ NONE
+
+--*/
+{
+
+
+ GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry;
+
+ ARCHITECTURAL_PROTOCOL_ENTRY *Entry;
+
+
+ for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) {
+ if (!Entry->Present) {
+ MissingEntry = MissingProtocols;
+ for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) {
+ if (EfiCompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) {
+//*** AMI PORTING BEGIN ***//
+// MissingEntry->GuidString is a Unicode string, which in Aptio require a "%S" format specifier.
+// DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString));
+ DEBUG ((EFI_D_ERROR, "\n%S Arch Protocol not present!!\n", MissingEntry->GuidString));
+//*** AMI PORTING END *****//
+ break;
+ }
+ }
+ }
+
+ }
+}
+)
diff --git a/Core/CORE_DXE/EfiPerf.h b/Core/CORE_DXE/EfiPerf.h
new file mode 100644
index 0000000..c5d1637
--- /dev/null
+++ b/Core/CORE_DXE/EfiPerf.h
@@ -0,0 +1,99 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/EDK/DxeMain/EfiPerf.h 3 5/06/08 10:07a Felixp $
+//
+// $Revision: 3 $
+//
+// $Date: 5/06/08 10:07a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/EDK/DxeMain/EfiPerf.h $
+//
+// 3 5/06/08 10:07a Felixp
+//
+// 2 5/05/08 4:12p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: EfiPerf.h
+//
+// Description: This file provides performance API definitions used by DXE Core.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef _EFI_PERF_H_
+#define _EFI_PERF_H_
+
+#include <AmiDxeLib.h>
+#include <Protocol/Performance.h>
+
+#define DXE_PHASE 0
+#define SHELL_PHASE 1
+#define PEI_PHASE 2
+
+EFI_STATUS
+GetTimerValue (
+ OUT UINT64 *TimerValue
+ );
+
+EFI_STATUS
+InitializePerformanceInfrastructure (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN UINT64 Ticker
+ );
+
+EFI_STATUS
+UpdateMeasure (
+ IN EFI_HANDLE Handle,
+ IN UINT16 *Token,
+ IN UINT16 *Host,
+ IN EFI_HANDLE HandleNew,
+ IN UINT16 *TokenNew,
+ IN UINT16 *HostNew
+ );
+
+#ifdef EFI_DXE_PERFORMANCE
+#define PERF_ENABLE(handle, table, ticker) InitializePerformanceInfrastructure (handle, table, ticker)
+#define PERF_UPDATE(handle, token, host, handlenew, tokennew, hostnew) \
+ UpdateMeasure (handle, \
+ token, \
+ host, \
+ handlenew, \
+ tokennew, \
+ hostnew \
+ )
+#else
+#define PERF_ENABLE(handle, table, ticker)
+#define PERF_UPDATE(handle, token, host, handlenew, tokennew, hostnew)
+#endif
+
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Ffs.c b/Core/CORE_DXE/Ffs.c
new file mode 100644
index 0000000..3361ce2
--- /dev/null
+++ b/Core/CORE_DXE/Ffs.c
@@ -0,0 +1,266 @@
+/*++
+
+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:
+
+ Ffs.c
+
+Abstract:
+
+ FFS file access utilities.
+
+--*/
+
+
+#include "FwVolDriver.h"
+
+#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address)))
+
+
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Get the FFS file state by checking the highest bit set in the header's state field
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ FFS File state
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+ UINT8 HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity != 0) {
+ FileState = (EFI_FFS_FILE_STATE)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
+ HighestBit >>= 1;
+ }
+
+ return (EFI_FFS_FILE_STATE)HighestBit;
+}
+
+
+BOOLEAN
+IsBufferErased (
+ IN UINT8 ErasePolarity,
+ IN VOID *InBuffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Check if a block of buffer is erased
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ InBuffer - The buffer to be checked
+ BufferSize - Size of the buffer in bytes
+
+Returns:
+ TRUE - The block of buffer is erased
+ FALSE - The block of buffer is not erased
+
+--*/
+{
+ UINTN Count;
+ UINT8 EraseByte;
+ UINT8 *Buffer;
+
+ if(ErasePolarity == 1) {
+ EraseByte = 0xFF;
+ } else {
+ EraseByte = 0;
+ }
+
+ Buffer = InBuffer;
+ for (Count = 0; Count < BufferSize; Count++) {
+ if (Buffer[Count] != EraseByte) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+VerifyFvHeaderChecksum (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the firmware volume header
+
+Arguments:
+ FvHeader - Points to the firmware volume header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+{
+ UINT32 Index;
+ UINT32 HeaderLength;
+ UINT16 Checksum;
+ UINT16 *ptr;
+
+ HeaderLength = FvHeader->HeaderLength;
+ ptr = (UINT16 *)FvHeader;
+ Checksum = 0;
+
+ for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) {
+ Checksum = (UINT16)(Checksum + ptr[Index]);
+ }
+
+ if (Checksum == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+VerifyHeaderChecksum (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the FFS file header
+
+Arguments:
+ FfsHeader - Points to the FFS file header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+{
+ UINT32 Index;
+ UINT8 *ptr;
+ UINT8 HeaderChecksum;
+
+ ptr = (UINT8 *)FfsHeader;
+ HeaderChecksum = 0;
+ for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
+ HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]);
+ }
+
+ HeaderChecksum = HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File;
+
+ if (HeaderChecksum == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+IsValidFfsHeader (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_FFS_FILE_STATE *FileState
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file header
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header to be checked
+ FileState - FFS file state to be returned
+
+Returns:
+ TRUE - Valid FFS file header
+ FALSE - Invalid FFS file header
+
+--*/
+{
+ *FileState = GetFileState (ErasePolarity, FfsHeader);
+
+ switch (*FileState) {
+ case EFI_FILE_HEADER_VALID:
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ case EFI_FILE_DELETED:
+ //
+ // Here we need to verify header checksum
+ //
+ return VerifyHeaderChecksum (FfsHeader);
+
+ case EFI_FILE_HEADER_CONSTRUCTION:
+ case EFI_FILE_HEADER_INVALID:
+ default:
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+IsValidFfsFile (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file.
+ Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file to be checked
+
+Returns:
+ TRUE - Valid FFS file
+ FALSE - Invalid FFS file
+
+--*/
+{
+ EFI_FFS_FILE_STATE FileState;
+
+ FileState = GetFileState (ErasePolarity, FfsHeader);
+ switch (FileState) {
+
+ case EFI_FILE_DELETED:
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ //
+ // Some other vliadation like file content checksum might be done here.
+ // For performance issue, Tiano only do FileState check.
+ //
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif b/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif
new file mode 100644
index 0000000..f5ece83
--- /dev/null
+++ b/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "FrameworkHii"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\FrameworkHii\"
+ RefName = "FrameworkHii"
+[files]
+"FrameworkHii.sdl"
+"HIIDB.c"
+"FrameworkHiiUtils.c"
+<endComponent>
diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl b/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl
new file mode 100644
index 0000000..e10b1d4
--- /dev/null
+++ b/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl
@@ -0,0 +1,15 @@
+TOKEN
+ Name = "FrameworkHii_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable FrameworkHii support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "FrameworkHii_DIR"
+ Help = "Path to FrameworkHii Module in Project"
+End
+
diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c b/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c
new file mode 100644
index 0000000..c0ec1b8
--- /dev/null
+++ b/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c
@@ -0,0 +1,369 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c 3 2/23/10 10:17p Felixp $
+//
+// $Revision: 3 $
+//
+// $Date: 2/23/10 10:17p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c $
+//
+// 3 2/23/10 10:17p Felixp
+// SetBrowserData function is added
+//
+// 2 11/24/09 10:40a Felixp
+//
+// 1 10/09/09 6:10p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: UefiHiiUtils.c
+//
+// Description: Framework HII 0.91 HII Utilities Protocol Implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <AmiDxeLib.h>
+#include <Protocol/HiiUtilities.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+
+static EFI_HII_PROTOCOL *Hii=NULL;
+static EFI_GUID HiiResourcesFfsSectionGuid= HII_RESOURCES_FFS_SECTION_GUID;
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: SetCallback
+//
+// Description:
+// EFI_STATUS SetCallback(EFI_HII_IFR_PACK *pIfr,
+// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo,
+// CALLBACK_INFO **CallBackFound)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS SetCallback(
+ EFI_LOADED_IMAGE_PROTOCOL *Image,
+ EFI_IFR_FORM_SET *FormSet, UINTN NumberOfCallbacks,
+ CALLBACK_INFO *CallbackInfo, CALLBACK_INFO **CallBackFound,
+ EFI_HANDLE *CallbackHandle
+)
+{
+ UINTN i;
+ EFI_STATUS Status;
+ for(i=0; i<NumberOfCallbacks; i++)
+ {
+ if (
+ FormSet->Class==CallbackInfo[i].Class
+ && FormSet->SubClass==CallbackInfo[i].SubClass
+ && (!CallbackInfo[i].pGuid || !guidcmp(&FormSet->Guid,CallbackInfo[i].pGuid))
+ )
+ {
+ if (CallbackInfo[i].pFormCallback)
+ {
+ EFI_HANDLE Handle=NULL;
+ Status=pBS->InstallProtocolInterface(&Handle, &gEfiFormCallbackProtocolGuid, EFI_NATIVE_INTERFACE, CallbackInfo[i].pFormCallback);
+ if (EFI_ERROR(Status)) return Status;
+ FormSet->CallbackHandle=(EFI_PHYSICAL_ADDRESS)Handle;
+ if (CallbackHandle) *CallbackHandle=Handle;
+ }
+ if (CallBackFound) *CallBackFound=&CallbackInfo[i];
+ return EFI_SUCCESS;
+ }
+ }
+ if (CallBackFound) *CallBackFound=NULL;
+ return EFI_NOT_FOUND;
+}
+
+static EFI_STATUS PublishPackages(
+ IN VOID *PackagePointers, IN UINTN NumberOfPackages,
+ IN EFI_GUID *PackageGuid, IN EFI_HANDLE DriverHandle OPTIONAL,
+ OUT EFI_HII_HANDLE *HiiHandle
+){
+ EFI_STATUS Status;
+ EFI_HII_PACKAGES *PackageList;
+ EFI_HII_PACK_HEADER **Packages = PackagePointers;
+
+ if ( !Hii
+ && EFI_ERROR(Status=pBS->LocateProtocol(
+ &gEfiHiiProtocolGuid, NULL, &Hii
+ ))
+ ) return Status;
+
+ PackageList = Malloc(
+ sizeof(EFI_HII_PACKAGES)+sizeof(EFI_HII_PACK_HEADER*)*NumberOfPackages
+ );
+ if(PackageList==NULL) return EFI_OUT_OF_RESOURCES;
+ PackageList->NumberOfPackages=NumberOfPackages;
+ PackageList->GuidId = PackageGuid;
+ pBS->CopyMem(
+ PackageList+1, Packages, sizeof(EFI_HII_PACK_HEADER*)*NumberOfPackages
+ );
+ Status = Hii->NewPack(Hii, PackageList, HiiHandle);
+ pBS->FreePool(PackageList);
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadStrings
+//
+// Description:
+// EFI_STATUS LoadStrings(EFI_HANDLE ImageHandle,
+// EFI_HII_HANDLE *HiiHandle)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS LoadStrings(
+ EFI_HANDLE ImageHandle, EFI_HII_HANDLE *HiiHandle
+)
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ HII_RESOURCE_SECTION_HEADER *pSection;
+ UINTN SectionSize;
+ EFI_HII_PACK_HEADER *pPack;
+
+ if (EFI_ERROR(Status=pBS->HandleProtocol(
+ ImageHandle, &gEfiLoadedImageProtocolGuid, &Image
+ ))
+ ) return Status;
+#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1
+{
+#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_
+ UINT8 *pData;
+ pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize);
+ if (!pData) return EFI_NOT_FOUND;
+ pSection = Malloc(SectionSize);
+ pBS->CopyMem(pSection,pData,SectionSize);
+ Status = EFI_SUCCESS;
+}
+#else
+{
+ Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize);
+ if (EFI_ERROR(Status)) return Status;
+}
+#endif
+ pPack = (EFI_HII_PACK_HEADER*)(pSection+1);
+ if (pPack->Type == EFI_HII_STRING){
+ Status = PublishPackages(
+ &pPack, 1,
+ &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid,
+ NULL, HiiHandle
+ );
+ }else{
+ Status = EFI_INVALID_PARAMETER;
+ }
+ pBS->FreePool(pSection);
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadResources
+//
+// Description:
+// EFI_STATUS LoadResources(EFI_HANDLE ImageHandle,
+// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo,
+// INIT_HII_PACK InitFunction)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS LoadResources(
+ EFI_HANDLE ImageHandle, UINTN NumberOfCallbacks,
+ CALLBACK_INFO *CallbackInfo, INIT_HII_PACK InitFunction
+)
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ HII_RESOURCE_SECTION_HEADER *pSection;
+ UINTN SectionSize;
+ CALLBACK_INFO *pCallBackFound;
+ if (EFI_ERROR(Status=pBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, &Image))) return Status;
+#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1
+{
+#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_
+ UINT8 *pData;
+ pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize);
+ if (!pData) return EFI_NOT_FOUND;
+ pSection = Malloc(SectionSize);
+ pBS->CopyMem(pSection,pData,SectionSize);
+}
+#else
+{
+ Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize);
+ if (EFI_ERROR(Status)) return Status;
+}
+#endif
+{
+ EFI_HII_PACK_HEADER **IfrPackagPtr, **GlobalPackagPtr, **SharedPackagPtr;
+ UINTN NumberOfIfrPackages, NumberOfGlobalPackages, NumberOfSharedPackages, i;
+ UINT8 *PackagePtrBuffer;
+ EFI_HII_PACK_HEADER *PackagePtr;
+
+ PackagePtrBuffer = Malloc(3*pSection->NumberOfPackages*sizeof(EFI_HII_PACK_HEADER*));
+ IfrPackagPtr = (EFI_HII_PACK_HEADER**)PackagePtrBuffer;
+ GlobalPackagPtr = IfrPackagPtr+pSection->NumberOfPackages;
+ SharedPackagPtr = GlobalPackagPtr+pSection->NumberOfPackages;
+ NumberOfIfrPackages = 0;
+ NumberOfGlobalPackages = 0;
+ NumberOfSharedPackages = 0;
+
+ PackagePtr = (EFI_HII_PACK_HEADER*)(pSection+1);
+ while(PackagePtr < (EFI_HII_PACK_HEADER*)((UINT8*)pSection+SectionSize)){
+ switch(PackagePtr->Type){
+ case EFI_HII_IFR:
+ IfrPackagPtr[NumberOfIfrPackages++]=PackagePtr;
+ break;
+ case EFI_HII_FONT: case EFI_HII_KEYBOARD:
+ GlobalPackagPtr[NumberOfGlobalPackages++]=PackagePtr;
+ break;
+ default:
+ SharedPackagPtr[NumberOfSharedPackages++]=PackagePtr;
+ if (PackagePtr->Type==EFI_HII_STRING){
+ while(PackagePtr->Length)
+ PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length);
+ PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+sizeof(EFI_HII_STRING_PACK));
+ continue;
+ }
+ break;
+ }
+ PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length);
+ }
+ Status = PublishPackages(
+ GlobalPackagPtr, NumberOfGlobalPackages,
+ &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid,
+ NULL, &HiiHandle
+ );
+ for(i=0; i<NumberOfIfrPackages; i++){
+ EFI_HANDLE CallbackHandle;
+
+ SharedPackagPtr[NumberOfSharedPackages]=IfrPackagPtr[i];
+ SetCallback(
+ Image, (EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1),
+ NumberOfCallbacks,CallbackInfo,&pCallBackFound,&CallbackHandle
+ );
+ Status = PublishPackages(
+ SharedPackagPtr, NumberOfSharedPackages+1,
+ &((EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1))->Guid,
+ CallbackHandle, &HiiHandle
+ );
+ if (pCallBackFound) pCallBackFound->HiiHandle=HiiHandle;
+ if (InitFunction) InitFunction(HiiHandle,pCallBackFound);
+ pCallBackFound=NULL;
+ }
+ pBS->FreePool(PackagePtrBuffer);
+ pBS->FreePool(pSection);
+}
+ return EFI_SUCCESS;
+}
+
+//TODO: header
+static EFI_STATUS GetString(
+ IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId,
+ IN OUT UINTN *StringSize, OUT EFI_STRING String
+){
+ if ( !Hii
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiProtocolGuid, NULL, &Hii))
+ ) return EFI_NOT_FOUND;
+ return Hii->GetString(
+ Hii, HiiHandle, StringId, TRUE, NULL, StringSize, String
+ );
+}
+
+//TODO header
+static EFI_STATUS SetString(
+ IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, IN EFI_STRING String
+){
+ if ( !Hii
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiProtocolGuid, NULL, &Hii))
+ ) return EFI_NOT_FOUND;
+ return Hii->NewString(
+ Hii, L" ", HiiHandle, &StringId, String
+ );
+}
+
+static EFI_STATUS GetBrowserData(
+ IN UINTN *BufferSize, OUT VOID *Buffer,
+ IN CONST EFI_GUID *VarStoreGuid, OPTIONAL
+ IN CONST CHAR16 *VarStoreName OPTIONAL
+){
+ return EFI_UNSUPPORTED;
+}
+
+static EFI_STATUS SetBrowserData(
+ IN UINTN BufferSize, IN VOID *Buffer,
+ IN CONST EFI_GUID *VarStoreGuid, OPTIONAL
+ IN CONST CHAR16 *VarStoreName OPTIONAL
+){
+ return EFI_UNSUPPORTED;
+}
+
+HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol = {
+ LoadResources, LoadStrings, PublishPackages,
+ GetBrowserData, SetBrowserData, GetString, SetString
+};
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2010, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/FrameworkHii/HIIDB.c b/Core/CORE_DXE/FrameworkHii/HIIDB.c
new file mode 100644
index 0000000..b4bfbfc
--- /dev/null
+++ b/Core/CORE_DXE/FrameworkHii/HIIDB.c
@@ -0,0 +1,3511 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/HIIDB.c 5 2/10/10 5:08p Felixp $
+//
+// $Revision: 5 $
+//
+// $Date: 2/10/10 5:08p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/HIIDB.c $
+//
+// 5 2/10/10 5:08p Felixp
+// Bug fix in HiiExtGetFormInfo function.
+//
+// 4 2/10/10 3:43p Felixp
+// x64 compiler warnings are fixed.
+//
+// 3 12/29/09 2:38p Yakovlevs
+// Fixed issue with hanging in TSE big number of setup questions.
+// Changed size of Length fields in some HII internal structures from
+// UIN16 to UINTN.
+// Code clenup (removed not used variables changes to compile with W4)
+//
+// 2 12/04/09 2:16p Yakovlevs
+// 1.Fixed potential NULL pointer use in function NewFontPack()
+// 2.Fixed inconsistancy in VarStore management (requires updated HiiDb.h)
+//
+// 1 10/09/09 6:10p Felixp
+//
+// 45 6/03/09 10:58a Yakovlevs
+// if Hii->RemovePack is called reset global pointers to NULL since they
+// might pointing at data that was freed.
+//
+// 44 10/01/08 1:01p Yakovlevs
+// fixed bug in HiiExtGetFormLabels() function.
+//
+// 43 1/09/08 10:49a Yakovlevs
+//
+// 42 9/05/07 9:18p Felixp
+//
+// 41 9/05/07 5:59p Yakovlevs
+// Bug fixes in UpdateForm and RemovePack routines.
+//
+// 2 6/28/07 5:16p Yakovlevs
+// Fixed FormUpdate Protocol Function, and some other minor bug fixes.
+//
+// 39 5/23/07 4:32p Pavell
+// Reindexing formsets
+//
+// 38 3/18/07 3:10p Felixp
+// GetSecondaryLanguages fix: return EFI_NOT_FOUND when no languages found
+//
+// 37 3/12/07 6:06p Yakovlevs
+// Fixed NewKbPack function.
+//
+// 36 3/12/07 1:46p Yakovlevs
+// Handled a situation when there are no Keyboard Layout data in HII
+// Database.
+//
+// 35 3/07/07 8:21p Yakovlevs
+// Added GetKeyboardLayout function implamentation.
+//
+// 34 1/23/07 12:23p Yakovlevs
+//
+// 33 12/21/06 1:57p Felixp
+//
+// 32 12/20/06 10:37a Felixp
+//
+// 31 12/18/06 5:42p Pavell
+// Added a fix for variable size determination
+// 30 11/15/06 5:55p Yakovlevs
+//
+// 29 11/02/06 6:45p Yakovlevs
+// Fixed HiiTestString NON_SPACING attribute handling
+//
+// 27 10/31/06 11:15a Yakovlevs
+// HiiTestString fixed to skip none spacing characters.
+//
+// 25 10/30/06 6:09p Yakovlevs
+// HII Spec v 0.92 updates
+//
+// 24 9/27/06 7:44p Felixp
+// Improvement in GetHiiString:
+// If string is not found for the current system language language, try
+// with the package primary language.
+//
+// 23 9/26/06 9:03a Felixp
+// Multilanguage Support. Do not use hard-coded glyphs. Load font file
+// instead.
+//
+// 22 9/18/06 6:23p Felixp
+// Bug fix in HiiGetString: buffer overrun when Raw is FALSE
+//
+// 21 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 20 8/04/06 5:18p Felixp
+// Bug fix in NewFontPack function (wide glyph handling).
+//
+// 19 7/24/06 11:46a Yakovlevs
+// Hii->ExportDatabase support added.
+//
+// 18 3/13/06 5:30p Felixp
+//
+// 17 10/03/05 2:47p Markw
+// Fixed uninitialized variables.
+//
+// 16 7/20/05 6:43p Felixp
+// GlyphToBlt modifed to support wide characters
+//
+// 15 7/19/05 8:17p Felixp
+// NewString modified to support update for all languages when three
+// spaces Language provided
+//
+// 13 7/13/05 9:46p Felixp
+//
+// 12 6/24/05 2:03p Yakovlevs
+//
+// 11 6/23/05 5:43p Yakovlevs
+// Fixed "Missing String" message
+//
+// 10 5/27/05 12:16p Felixp
+// bug fix in HiiGetString
+//
+// 9 2/28/05 6:21p Yakovlevs
+// Fixed DateTime and Object Conditions issue;
+//
+// 8 3/17/05 1:57p Felixp
+// implementation of HiiNewPackNew updated
+//
+// 7 3/04/05 12:52p Felixp
+//
+// 6 3/04/05 9:23a Mandal
+//
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <This File Name>
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+//
+// Module Name: HIIDB.C
+//
+// Abstract: This file contains implementation of HII Database Protocol.
+//
+#include <HiiDb.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiUtilities.h>
+extern UINT8 *UsStdNarrowGlyphData;
+extern HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol;
+
+//==================================================================================
+// Some globals we need
+//==================================================================================
+
+//------------------------------------------
+//Prototypes
+EFI_STATUS InitPrivateData(EFI_HANDLE MyImgHandle);
+EFI_STATUS CreateLabelObjects(HII_LABEL *Label);
+//EFI_STATUS HiiNewPack (IN EFI_HII_PROTOCOL *This,
+// IN EFI_HII_PACK_LIST *Package,
+// OUT EFI_HII_HANDLE *Handle);
+
+//------------------------------------------
+//GUIDs
+EFI_GUID gEfiHiiProtocolGuidOld = EFI_HII_OLD_PROTOCOL_GUID;
+EFI_GUID gEfiHiiProtocolGuidNew = EFI_HII_NEW_PROTOCOL_GUID;
+static EFI_GUID gEfiExtHiiProtocolGuid = EFI_HII_EXT_PROTOCOL_GUID;
+//------------------------------------------
+//Data Vars
+
+//Define String Database Key fields
+#define STR_KEY 0
+#define STR_KEY_CNT 1
+//it is going to be combined key
+//Token->size16;LangIdx->size32;Handle->size16; total = 8 byte->UINT64
+//Token->Least Segnificant Field Handle Most Significant Field
+//the resulting Index for StringToken->23, LangIndex->2, Hii Handle=1 will be
+// Handle|LangIdx |Token
+// 0x0001|00000002|0023 -> easy to sort easy to find
+static DBE_OFFSET_KEY_CONTEXT gStrOffsetInfo = {EFI_FIELD_OFFSET(HII_STR ,Token), 8 };
+static DBE_KEY_FIELD gStrKey=OFFSET_KEY(gStrOffsetInfo);
+
+//Any Language Printable string
+static UINT16 gAnyLang[]=L"Any Language";
+//HII DATABASE global var
+static HII_DB gHiiDb;
+
+///////////////////////////////////////////////////////////////////
+//in order to save some time when LocateHandle routine been called
+//I have decide to save Current HandleInfo structure pionter
+//here rather than locate it every time
+static HII_HANDLE *mCurHnd=NULL;
+static HII_LANG *mCurLang=NULL;
+static UINTN mCurHid=0, mCurLid=0;
+
+///////////////////////////////////////////////////////////////////
+//in order to save some time when HiiGetLine routine been called
+//I have decide to save Current StringInfo structure pionter
+//here rather than locate it every time HiiGetLine been called
+static HII_STR *mCurStr=NULL;
+
+///////////////////////////////////////////////////////////////////
+// save the varstore context based on the formset
+static UINT16 CurrentVarId = 0;
+
+//==================================================================================
+// Entry Point
+//==================================================================================
+//**********************************************************************
+//<AMI_PHDR_START>
+//
+// Procedure: HiiDbEntryPoint()
+//
+// Description: Initialize HII Database (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+//
+// Input: EFI_HANDLE ImageHandle This Driver Image Handle.
+// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI System Table
+//
+// Output: EFI_STATUS EFI_SUCCESS - Driver Loadded.
+// Other - Driver Error
+//
+//<AMI_PHDR_END>
+//**********************************************************************
+
+EFI_STATUS HiiDbEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){
+ EFI_STATUS Status=0;
+ UINTN hCnt;
+ EFI_HANDLE *hBuf;
+//-----------------------------------
+ InitAmiLib(ImageHandle, SystemTable);
+
+ //Only one HII Driver has to be in the system
+ Status=pBS->LocateHandleBuffer(ByProtocol, &gEfiHiiProtocolGuidOld, NULL, &hCnt, &hBuf);
+
+ //If there was no error, report that we has been already started
+ if (!EFI_ERROR(Status)) {
+ if (!hBuf)pBS->FreePool(hBuf); //Don't forget to free the memory
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status=InitPrivateData(ImageHandle);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status = pBS->InstallMultipleProtocolInterfaces(&gHiiDb.HiiHandle,
+ &gEfiHiiProtocolGuidOld,&gHiiDb.HiiProtocolOld,
+ &gEfiHiiProtocolGuidNew,&gHiiDb.HiiProtocolNew,
+ &gEfiExtHiiProtocolGuid,&gHiiDb.HiiExtProtocol,
+ &gHiiUtilitiesProtocolGuid, &HiiUtilitiesProtocol,
+ NULL);
+ return Status;
+}
+
+///////////////////////////////////////////////////////////////////
+// Common Worker Functions
+///////////////////////////////////////////////////////////////////
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: GetDefaultLang
+//
+// Description:
+// EFI_STATUS GetDefaultLang(OUT CHAR16 *DefaultLang) returns the default
+// system language in the string specified by DefaultLang.
+//
+// Input:
+// OUT CHAR16 *DefaultLang
+// Pointer to the null-terminated Unicode string.
+//
+// Output:
+// EFI_NOT_FOUND, if the default language could not be found.
+// Otherwise, EFI_SUCCESS.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+//Get System Default Language
+EFI_STATUS GetDefaultLang(CHAR16 *DefaultLang){
+ EFI_GUID EfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+ EFI_STATUS Status=0;
+ UINT8 al[3];
+ UINTN i=sizeof(al);
+//-----------------------
+ Status=pRS->GetVariable(L"Lang",&EfiGlobalVariableGuid,NULL,&i,al);
+ if (EFI_ERROR(Status)) return Status;
+
+ for(i=0; i<sizeof(al) ;i++) DefaultLang[i]=al[i];
+ DefaultLang[sizeof(al)]=0;
+ return Status;
+}
+
+//-----------------------------------------------------------------
+//This Function will look in Item List and try to find mutch for Item of Size.
+//if it finds it will return Pointer to the matching Item and update Index if not - NULL
+EFI_STATUS LocateItem(T_ITEM_LIST *ItemLst, VOID *Item, UINTN Size, OUT UINTN *Index){
+ UINTN i;
+//-----------------
+ for(i=0; i<ItemLst->ItemCount; i++){
+ if(!MemCmp(ItemLst->Items[i],Item,Size)) {
+ if(Index)*Index=i;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+///////////////////////////////////////////////////////////////////
+//Will return Lenth of the screen representation of Str with respect
+//of wide narrow and non spacing glyphs it using
+//Len excluding '0' char (\n)
+UINT16 GetScrLen(CHAR16 *Str, UINT16 Len){
+ UINTN i;
+ UINT16 u,sl=0;
+ HII_N_FONT *fnt;
+//--------------------------------------
+ for(i=0;i<Len;i++){
+ u=Str[i];
+ if(u<0x20 || u>=0xfff0)continue;
+ fnt=gHiiDb.FontDb[u];
+ if(fnt){
+ if(fnt->Attr & GLYPH_NON_SPACING) continue;
+ if(fnt->Attr & GLYPH_WIDE) sl+=2;
+ else sl++;
+ } else sl++; //we will print empty rect for non existent glyph
+ }
+ return sl;
+}
+
+///////////////////////////////////////////////////////////////////
+//Will allocate Mem for the length of the string and Copy "Str" there
+UINT16* StrAlloc(UINT16 *Str,UINT16 *StrLen OPTIONAL, UINT16 *ScrLen OPTIONAL){
+ UINT16 len;
+ UINT16 *str;
+//-------------------------------------
+ len=(UINT16)Wcslen(Str);//terminator not included
+ str=(UINT16*)Malloc((len+1)*sizeof(UINT16));
+ if(!str)return NULL;
+ Wcscpy(str,Str);
+ if(StrLen)*StrLen=len+1;
+ if(ScrLen)*ScrLen=GetScrLen(Str,len);
+ return str;
+}
+
+///////////////////////////////////////////////////////////////////
+//This will Change Language Attributes
+//VOID SetLangAttr(UINTN Index, UINT32 Attr){
+// HII_LANG *lang;
+//--------------------
+// lang=(HII_LANG*)gHiiDb.LangDb.ResDsc[Index];
+// lang->Attr=Attr;
+//}
+
+///////////////////////////////////////////////////////////////////
+//this will find and return HII_LANG "Index",
+//if "Language" is stored In Hii Handle Database
+HII_LANG* LocateLang(UINT16 *Language, UINTN *Index){
+ EFI_STATUS Status;
+ UINTN idx;
+//------------------------
+ if( !mCurLang || MemCmp(&mCurLang->sName[0],Language,sizeof(mCurLang->sName)) )
+ {
+ Status=LocateItem(&gHiiDb.LangDb,Language,sizeof(UINT16)*4,&idx);
+ if(EFI_ERROR(Status)){
+ mCurLang=NULL; //flush Language Cache
+ mCurLid=0; //make index to generate exception if used
+ } else {
+ mCurLang=gHiiDb.LangDb.Items[idx];
+ mCurLid=idx;
+ }
+ }
+ if(mCurLang && Index)*Index=mCurLid;
+ return mCurLang;
+}
+
+HII_HANDLE *LocateHandleGuid(EFI_GUID *Guid, UINTN *Index){
+ HII_HANDLE *phnd=NULL;
+ UINTN i;
+//-------------------------------
+ for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){
+ phnd=gHiiDb.HandleDb.Items[i];
+ if(!MemCmp(&phnd->Guid,Guid,sizeof(EFI_GUID)))break;
+ else phnd=NULL;
+ }
+ if(phnd && Index)*Index=i;
+ return phnd;
+}
+
+///////////////////////////////////////////////////////////////////
+//This function will Locate another Handle with the same Guid as
+//passed Handle.
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//This function is Obsolete but I need it for compliance with Intel's
+//Setup because they using same guid more than once per Ifr and Strings pare.
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+VOID LocateSameGuidHandle(UINTN CurIdx, UINTN *IdxBuffer, UINTN *IdxCount){
+ HII_HANDLE *phnd=NULL,*chnd=gHiiDb.HandleDb.Items[CurIdx];
+ UINTN i, c=0;
+//----------------------------
+ for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){
+ if(i==CurIdx) continue;
+ phnd=gHiiDb.HandleDb.Items[i];
+ if(!MemCmp(&phnd->Guid,&chnd->Guid,sizeof(EFI_GUID))){
+ IdxBuffer[c]=i;
+ c++;
+ }else phnd=NULL;
+ }
+ *IdxCount=c;
+}
+
+///////////////////////////////////////////////////////////////////
+//if on passed handle in any string function there are no
+//strings associated with we need to find another handle with
+//the same guid having strings on it
+HII_HANDLE *LocateStrHandleGuid(UINTN CurIdx, UINTN *Index){
+ HII_HANDLE *phnd=NULL,*chnd=gHiiDb.HandleDb.Items[CurIdx];
+ UINTN i;
+//----------------------------
+ for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){
+ if(i==CurIdx) continue;
+ phnd=gHiiDb.HandleDb.Items[i];
+ if(!MemCmp(&phnd->Guid,&chnd->Guid,sizeof(EFI_GUID)) && phnd->HasStr){
+ if(Index)*Index=i;
+ break;
+ }else phnd=NULL;
+ }
+ return phnd;
+}
+
+///////////////////////////////////////////////////////////////////
+//this will find and return HII_HANDLE "Index",
+//if "Handle" is stored In Hii Handle Database
+static HII_HANDLE* LocateHandle(EFI_HII_HANDLE Handle, UINTN *Index){
+ EFI_STATUS Status;
+ UINTN idx;
+//------------------------
+ if((!mCurHnd) || (mCurHnd->Handle!=Handle)){
+ Status=LocateItem(&gHiiDb.HandleDb,&Handle,sizeof(EFI_HII_HANDLE),&idx);
+ if(EFI_ERROR(Status)){
+ mCurHnd=NULL; //flush Handle Cache
+ mCurHid=-1; //make index to generate exception if used
+ } else {
+ mCurHnd=gHiiDb.HandleDb.Items[idx];
+ mCurHid=idx;
+ }
+ }
+ if(mCurHnd && Index)*Index=mCurHid;
+ return mCurHnd;
+}
+
+///////////////////////////////////////////////////////////////////
+//this will find and return HII_HANDLE "Index",
+//if "Handle" is stored in Handle Database
+//or Append Handle Database with this Handle if not and return a new "Index"
+EFI_STATUS LocateHandleAdd(EFI_HII_HANDLE Handle, EFI_GUID *GuidId, UINTN *Index){
+ EFI_STATUS Status=0;
+ HII_HANDLE *phnd;
+//----------------
+ phnd=LocateHandle(Handle,Index);
+ if(!phnd){
+ phnd=MallocZ(sizeof(HII_HANDLE));
+ if(!phnd)return EFI_OUT_OF_RESOURCES;
+ pBS->CopyMem(&phnd->Guid,GuidId,sizeof(EFI_GUID));
+ phnd->Handle=Handle;
+ Status=AppendItemLst(&gHiiDb.HandleDb,phnd);
+ if(EFI_ERROR(Status)) return Status;
+ *Index=gHiiDb.HandleDb.ItemCount-1;
+ }
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+//this will find and return HII_LANG "Index",
+//if "Language" is stored in Handle Database
+//or Append Handle Database with this Handle if not and return a new "Index"
+EFI_STATUS LocateLangAdd(UINT16 *Language, UINT16 *PrintLanguage, UINTN *Index){
+ EFI_STATUS Status;
+ HII_LANG *lang;
+//------------------
+ //Check if we have the Language installed already
+ lang=LocateLang(Language,Index);
+ if(!lang){
+ lang=MallocZ(sizeof(HII_LANG));
+ if(!lang)return EFI_OUT_OF_RESOURCES;
+ pBS->CopyMem(&lang->sName,Language,sizeof(UINT16)*4);
+ if(PrintLanguage){
+ lang->lName=StrAlloc(PrintLanguage,NULL,NULL);
+ if(!lang->lName) return EFI_OUT_OF_RESOURCES;
+ }
+ Status=AppendItemLst(&gHiiDb.LangDb,lang);
+ if(EFI_ERROR(Status)) return Status;
+ if(Index)*Index=gHiiDb.LangDb.ItemCount-1;
+ }
+ return EFI_SUCCESS;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//This will check if Lang Index is present in Secondary Lang List
+//on this Handle
+///////////////////////////////////////////////////////////////////
+EFI_STATUS LocateSecLangAdd(HII_HANDLE *Hnd, UINTN *SecLangIdx, BOOLEAN AddIt){
+ UINTN i;
+//------------------------------
+ for(i=0; i<Hnd->SecLang.ItemCount; i++){
+ if(*SecLangIdx==(UINTN)(Hnd->SecLang.Items[i])) return EFI_SUCCESS;
+ }
+ if(AddIt)return AppendItemLst(&Hnd->SecLang,(VOID*)(*SecLangIdx));
+ else return EFI_NOT_FOUND;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//=================================================================
+//HII Database Protocol Functions
+//=================================================================
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+// Font related
+///////////////////////////////////////////////////////////////////
+EFI_STATUS NewFontPack(IN EFI_HII_FONT_PACK *Package)
+{
+ UINTN i;
+ UINT16 u;
+ EFI_NARROW_GLYPH *ng;
+ EFI_WIDE_GLYPH *wg;
+//--------------------------
+
+ //Set Pointer to the beginning of Package Data.
+ ng=(EFI_NARROW_GLYPH*)(Package+1);
+
+ if(Package->NumberOfNarrowGlyphs){
+ HII_N_FONT *fnt;
+ //---------------------------
+ //Allocate Space for Number of Narrow Glyphs
+ fnt=(HII_N_FONT*)Malloc(sizeof(HII_N_FONT)*Package->NumberOfNarrowGlyphs);
+ if(!fnt)return EFI_OUT_OF_RESOURCES;
+
+ for(i=0; i<Package->NumberOfNarrowGlyphs; i++){
+ u=ng[i].UnicodeWeight;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ //we will populate only empty spots in FontD or oposite
+//made SDL token for that
+ if(!gHiiDb.FontDb[u]){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ //fnt=(HII_FONT*)Malloc(sizeof(HII_FONT));
+ pBS->CopyMem((VOID*)&fnt[i], &ng[i].Attributes,sizeof(HII_N_FONT));
+ gHiiDb.FontDb[u]=&fnt[i];
+ }
+ }
+ }
+
+
+ if(Package->NumberOfWideGlyphs){
+ UINTN j,k;
+ HII_W_FONT *fnt;
+ //---------------
+ //Allocate Space for Number of Wide Glyphs
+ wg=(EFI_WIDE_GLYPH*)(ng+Package->NumberOfNarrowGlyphs);
+ fnt=(HII_W_FONT*)Malloc((sizeof(HII_W_FONT))*Package->NumberOfWideGlyphs);
+ if(!fnt)return EFI_OUT_OF_RESOURCES;
+
+ for(i=0; i<Package->NumberOfWideGlyphs; i++){
+ u=wg[i].UnicodeWeight;
+ if(!gHiiDb.FontDb[u]){
+ fnt[i].Attr=wg[i].Attributes;
+ for(j=0,k=0; j<NG_SIZE;j++, k+=2){
+ fnt[i].GlData[k]=wg[i].GlyphCol1[j];
+ fnt[i].GlData[k+1]=wg[i].GlyphCol2[j];
+ }
+ gHiiDb.FontDb[u]=(HII_N_FONT*)&fnt[i];
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiTestString(IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize)
+{
+ EFI_STATUS Status=0;
+ UINT32 i;
+ UINT32 bs=0;
+ HII_N_FONT *fnt;
+//------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+ if ((!FirstMissing)||(!StringToTest)||(!GlyphBufferSize)) return EFI_INVALID_PARAMETER;
+
+ i=*FirstMissing;
+ while (StringToTest[i]!=0){
+ fnt=gHiiDb.FontDb[ StringToTest[i] ];
+ if(fnt){
+ if(fnt->Attr& GLYPH_NON_SPACING ){
+ i++;
+ continue;
+ }
+ if(fnt->Attr&GLYPH_WIDE) bs+=WG_SIZE;
+ else bs+=NG_SIZE;
+ i++;
+ } else {
+ Status=EFI_NOT_FOUND;
+ break;
+ }
+ }
+ *FirstMissing=i;
+ *GlyphBufferSize=bs;
+ return Status;
+}
+
+static UINT8 gGE[NG_SIZE]=
+ {0x00,0x00,0x00,0x7E,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x7E,0x00,0x00,0x00};// \
+// 0x00,0x00,0x00,0x7E,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x7E,0x00,0x00,0x00};
+
+static EFI_WIDE_GLYPH gGB;
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetGlyph(IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus)
+{
+ UINTN i, bs=NG_SIZE;
+ HII_N_FONT *fnt;//=gHiiDb.FontDb[Source[j]];
+// HII_GL_COL *gc1=NULL, *gc2=NULL;
+// BOOLEAN w=FALSE;
+//------------------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ if((!GlyphBuffer)||(!Index)||(!Source)||(!BitWidth)) return EFI_INVALID_PARAMETER;
+ fnt=gHiiDb.FontDb[Source[*Index]];
+
+ if(!fnt) {
+ if(InternalStatus)*InternalStatus=(UINT32)-1;
+ //If after calling TestString somebody will call us with invalid Unicode Char
+ pBS->CopyMem(&gGB.GlyphCol1[0],&gGE, NG_SIZE);
+ *BitWidth=GLYPH_W;
+ *GlyphBuffer=(UINT8*)&gGB;
+ (*Index)++;
+ return EFI_NOT_FOUND;
+ }
+
+ //first char must not be the non-spacing character
+ if(fnt->Attr&GLYPH_NON_SPACING) return EFI_INVALID_PARAMETER;
+
+ if(fnt->Attr&GLYPH_WIDE){
+ *BitWidth=GLYPH_W*2;
+ bs=WG_SIZE;
+ } else *BitWidth=GLYPH_W;
+
+ pBS->SetMem(&gGB,sizeof(EFI_WIDE_GLYPH),0);
+ do{
+ fnt=gHiiDb.FontDb[Source[*Index]];
+ for(i=0;i<bs;i++) gGB.GlyphCol1[i]|=fnt->GlData[i];
+ (*Index)++;
+ } while(fnt->Attr&GLYPH_NON_SPACING);
+ *GlyphBuffer=(UINT8*)&gGB;
+ if(InternalStatus)*InternalStatus=0;
+
+ return EFI_SUCCESS;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//!!!! this function suppose to take care of thing with mixed size gpyphs
+EFI_STATUS HiiGlyphToBlt(IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_UGA_PIXEL Foreground,
+ IN EFI_UGA_PIXEL Background,
+ IN UINTN Count,//Number of NARROW Glyps left in BltBuffer
+ //or count from the end of the buffer in terms of NARROW glyphs
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_UGA_PIXEL *BltBuffer)
+{
+// UINTN x,y;//,i,o;
+// UINT8 k = Width > GLYPH_W ? 2 : 1;
+//------------------------------------
+// if(!This) return EFI_INVALID_PARAMETER;
+// if( !(Width==GLYPH_W || Width==(GLYPH_W*2)) || Height!=GLYPH_H )return EFI_INVALID_PARAMETER;
+/* for (y=0,o=0; y<Height; y++){
+ for(i=0; i<Width/GLYPH_W; i++){
+ for (x=0; x<GLYPH_W; x++){
+ if ( GlyphBuffer[y*k+i] & (0x80 >> x)) BltBuffer[y*GLYPH_W*Count+x+o]=Foreground;
+ else BltBuffer[y*GLYPH_W*Count+x+o]=Background;
+ }
+ o=GLYPH_W;
+ }
+ }
+
+ return EFI_SUCCESS;
+ UINTN X;
+ UINTN Y;
+*/
+ UINT8 Mask;
+ UINTN Index, Line, Part;
+ UINTN TotalParts = Width/GLYPH_W;
+ EFI_NARROW_GLYPH *Glyph = (EFI_NARROW_GLYPH *)GlyphBuffer;
+ if(!This) return EFI_INVALID_PARAMETER;
+ if( !(Width==GLYPH_W || Width==GLYPH_W*2) || Height!=GLYPH_H || Count<TotalParts)return EFI_INVALID_PARAMETER;
+ for (Line = 0, Index=0; Line < Height; Line++, Index+=GLYPH_W * (Count-TotalParts)) {
+ for(Part=0; Part<TotalParts; Part++){
+ for (Mask = 0x80; Mask > 0; Mask>>=1, Index++) {
+ if (Glyph->GlyphCol1[Line*TotalParts+Part] & Mask)
+ BltBuffer[Index] = Foreground;
+ else
+ BltBuffer[Index] = Background;
+ }
+ }
+ }
+/*///
+ BltBuffer[Index] = (Glyph->GlyphCol1[y] & (1 << x)) ? Foreground : Background;
+ if (Width > GLYPH_W)
+ BltBuffer[Index+GLYPH_W] = (Glyph->GlyphCol1[GLYPH_H+y] & (1 << x)) ? Foreground : Background;
+///
+ EFI_NARROW_GLYPH *Glyph = (EFI_NARROW_GLYPH *)GlyphBuffer;
+ for (y = 0; y < Height; y++) {
+ for (x = 0; x < GLYPH_W; x++) {
+ UINTN Index = y * GLYPH_W * Count + (GLYPH_W - x - 1);
+ for(i=0; i<Width/GLYPH_W; i++)
+ if ((Glyph->GlyphCol1[i*GLYPH_H+y] & (1 << x)) != 0)
+ BltBuffer[Index+GLYPH_W*i] = Foreground;
+ else
+ BltBuffer[Index+GLYPH_W*i] = Background;
+ }
+ }*/
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+// String related
+///////////////////////////////////////////////////////////////////
+HII_STR *LocateString(HII_HANDLE *PHnd, UINTN LangIdx, STRING_REF Token/*, UINTN HandleIdx OPTIONAL*/){
+ UINTN li=LangIdx, j;
+ HII_STR sd = {0,0,0,0,NULL};
+ INT8 v;
+ VOID **cs;
+//-----------------
+ //if CurrentString must be refreshed
+ if(!mCurStr || mCurStr->LangIdx!=LangIdx || mCurStr->Token!=Token || mCurStr->Handle!=PHnd->Handle)
+ {
+
+ //---------------------
+ do {
+ sd.Handle=PHnd->Handle;
+ sd.LangIdx=(UINT32)li;
+ sd.Token=Token;
+
+ DbeLocateKey(&gHiiDb.StringDb,STR_KEY,(VOID*)&sd,(VOID**)&cs,&v,&j);
+
+ if(v)mCurStr=NULL;
+ else {
+ mCurStr=(HII_STR*)(*cs);
+ break;
+ }
+
+ //if we were looking for any language and failed
+ //just get Primary Package Language
+ if(!li)li=PHnd->PriLang;
+ else break;
+ } while(v);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this patch was made to keep compatibility with Intel's implemntation
+//of BDS - DevicerManagerVfrBin and FrontPageVfrBin uses the same Guid
+//and Same String Pack expecting valid strings on from one StringPack
+//when passing different GUIDs?????????
+/* if(!mCurStr){
+ HII_HANDLE *phnd;
+ UINTN i,sgib[10]={0,0,0,0,0,0,0,0,0,0};//same GUID index Buffer
+ //----------------------------------
+ LocateSameGuidHandle(HandleIdx,&sgib[0],&c);
+ for(i=0; i<c;i++){
+ li=LangIdx;
+ phnd=gHiiDb.HandleDb.Items[sgib[i]];
+ do {
+ sd.Handle=phnd->Handle;
+ sd.LangIdx=(UINT32)li;
+ sd.Token=Token;
+
+ DbeLocateKey(&gHiiDb.StringDb,STR_KEY,(VOID*)&sd,(VOID**)&cs,&v,&j);
+
+ if(v)mCurStr=NULL;
+ else {
+ mCurStr=(HII_STR*)(*cs);
+ break;
+ }
+ //if we were looking for any language and faild
+ //just get Primary Package Language
+ if(!li)li=PHnd->PriLang;
+ else break;
+ } while(v);
+ if(mCurStr)break;
+ }
+ }
+*/
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ }
+ return mCurStr;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS ReplaceString(HII_STR *StrData, UINT16 *Replacement)
+{
+ UINT16 *str;
+ UINT16 len,slen;
+//-----------------------------
+ str=StrAlloc(Replacement, &len, &slen);
+ if(!str)return EFI_OUT_OF_RESOURCES;
+
+ if(StrData->NewStr.StrPtr)pBS->FreePool(StrData->NewStr.StrPtr);
+
+ StrData->NewStr.StrLen=len;
+ StrData->NewStr.ScrLen=slen;
+ StrData->NewStr.StrPtr=str;
+
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS AddString(UINTN LangIdx, HII_HANDLE *PHandle, UINT16 *String, BOOLEAN Initial, STRING_REF *Token)
+{
+ HII_STR *str;
+//-------------------------------------
+ str=MallocZ(sizeof(HII_STR));
+ if(!str) return EFI_OUT_OF_RESOURCES;
+
+ if(Initial){
+ str->String.StrPtr=StrAlloc(String,&str->String.StrLen,&str->String.ScrLen);
+ if(!(str->String.StrPtr))return EFI_OUT_OF_RESOURCES;
+ } else {
+ str->NewStr.StrPtr=StrAlloc(String,&str->NewStr.StrLen, &str->NewStr.ScrLen);
+ if(!(str->NewStr.StrPtr))return EFI_OUT_OF_RESOURCES;
+ }
+
+ str->LangIdx=(UINT32)LangIdx;
+ //if Token is provided, use it. Otherwise assign new one.
+ if (Token && *Token) str->Token=*Token;
+ else
+ {
+ str->Token=PHandle->NextStrToken;
+ PHandle->NextStrToken++;
+ if (Token) *Token = str->Token;
+ }
+ str->Handle=PHandle->Handle;
+
+ return DbeInsert(&gHiiDb.StringDb,(VOID*)str);
+}
+
+EFI_STATUS UpdateString(IN UINTN li,
+ IN HII_HANDLE *phnd,
+ IN STRING_REF *Reference,
+ IN CHAR16 *NewString)
+{
+ EFI_STATUS Status;
+ //Check if String with this Token# already present in String Db
+ if((*Reference)==0){
+ Status=AddString(li,phnd,NewString,FALSE,Reference);
+ if(EFI_ERROR(Status)) return Status;
+ } else {
+ HII_STR *str;
+ if (*Reference >= phnd->NextStrToken) return EFI_INVALID_PARAMETER;
+ str=LocateString(phnd,li,*Reference);
+ //if str is NULL, it means that string with this token has been created
+ //for a different language
+ Status= (str) ? ReplaceString(str,NewString) : AddString(li,phnd,NewString,FALSE,Reference);
+ }
+ return Status;
+
+}
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiNewString(IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF *Reference,
+ IN CHAR16 *NewString)
+{
+ UINTN li=0, hi=0;
+ HII_LANG *lang;
+ HII_HANDLE *phnd;
+ EFI_STATUS Status=0;
+ UINT16 dl[4]={0x20,0x20,0x20,0}, *pdl;//Any Lang
+//-------------------------------
+ if(!This || !Reference || !NewString) return EFI_INVALID_PARAMETER;
+ //first Check if the Handle is valid.
+ phnd=LocateHandle(Handle,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+
+ if(!phnd->HasStr){
+ phnd=LocateStrHandleGuid(hi,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+ }
+
+ if(!Language){
+ pdl=&dl[0];
+ if(EFI_ERROR( GetDefaultLang(pdl))){
+ pdl=(UINT16*)gHiiDb.LangDb.Items[phnd->PriLang];
+ }
+ } else pdl=Language;
+
+ //dl has a language string "xxx"
+ lang=LocateLang(pdl,&li);
+
+ if (!li)
+ {//language index 0 referes to language " ", which means we have to update
+ //string for all languages
+ //update string for primary language
+ Status = UpdateString(phnd->PriLang,phnd,Reference,NewString);
+ //update string for all secondary languages
+ for(li=0; !EFI_ERROR(Status) && li<phnd->SecLang.ItemCount; li++)
+ Status = UpdateString((UINTN)phnd->SecLang.Items[li],phnd,Reference,NewString);
+ return Status;
+ }
+
+ if(!lang) return EFI_INVALID_PARAMETER;
+
+ //If language is valid but not mutch Pack PriLang
+ if(phnd->PriLang!=li){
+ Status=LocateSecLangAdd(phnd,&li,FALSE);
+ if(EFI_ERROR(Status))li=phnd->PriLang;
+ //lang=(HII_LANG*)gHiiDb.LangDb.Items[li];
+ }
+ return UpdateString(li,phnd,Reference,NewString);
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS GetLanguageFromPack(EFI_HII_STRING_PACK *Pack, UINTN *LangIndex){
+ UINT16 *sn, *ln;
+ UINT8 *ofs=(UINT8*)Pack;//(Pack+1);
+//-------------------------
+ sn=(UINT16*)(ofs+Pack->LanguageNameString);
+ ln=(UINT16*)(ofs+Pack->PrintableLanguageName);
+ return LocateLangAdd(sn,ln,LangIndex);
+}
+
+///////////////////////////////////////////////////////////////////
+BOOLEAN IsLastStrPack(EFI_HII_STRING_PACK *Pack){
+ if(Pack->Header.Type==EFI_HII_STRING &&
+ Pack->Header.Length == 0 && Pack->Attributes == 0 &&
+ Pack->LanguageNameString == 0 && Pack->NumStringPointers == 0 &&
+ Pack->PrintableLanguageName == 0 ) return TRUE;
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetPrimaryLanguage(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString)
+{
+ HII_HANDLE *phnd;
+ HII_LANG *lang;
+ UINTN hi;
+ UINT16 *ls,*bp;
+//----------------------
+ if(!This || !LanguageString) return EFI_INVALID_PARAMETER;
+
+ phnd=LocateHandle(Handle,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+ if(!phnd->HasStr){
+ phnd=LocateStrHandleGuid(hi,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+ }
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//???????????????????????????????????????
+ //if for some reson Somebody submit just IFR vith no Strings
+ //there are no way to determine language so I just put there 0 -Any Language
+ //but Intel's code expect me to return something like "eng"
+ //so I will return Default System Lang.
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ ls=Malloc(sizeof(UINT16)*3*(phnd->SecLang.ItemCount+1)+1); //4 characters
+ if(!ls) return EFI_OUT_OF_RESOURCES;
+
+ bp=ls;
+ lang=gHiiDb.LangDb.Items[phnd->PriLang];
+ pBS->CopyMem(ls,&lang->sName,sizeof(UINT16)*3);
+ bp+=3;
+
+ for(hi=0;hi<phnd->SecLang.ItemCount; hi++){
+ lang=gHiiDb.LangDb.Items[(UINTN)phnd->SecLang.Items[hi]];
+ pBS->CopyMem(bp,&lang->sName,sizeof(UINT16)*3);
+ bp+=3;
+ }
+ *bp=0;
+ *LanguageString=ls;
+
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+//
+EFI_STATUS HiiGetSecondaryLanguages(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString)
+{
+ UINTN id,i;
+ HII_HANDLE *phnd;
+ HII_LANG *lang;
+ UINT16 *ls;
+//----------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ phnd=LocateHandle(Handle,NULL);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+
+ //Some how caller managed to scrue up with parameters.
+ lang=LocateLang(PrimaryLanguage,&id);//Lang provided does not mutch with what we've recorded
+ if( !lang || phnd->PriLang!=id ) return EFI_INVALID_PARAMETER;
+
+ if(phnd->SecLang.ItemCount>0){
+ UINT16 *l;
+ //----------------
+ ls=Malloc(sizeof(UINT16)*3*phnd->SecLang.ItemCount+1);
+ if(!ls) return EFI_OUT_OF_RESOURCES;
+ l=ls;
+ for(i=0; i<phnd->SecLang.ItemCount; i++){
+ //we are not returning Any Language str " "
+ //And Any Lang String has index 0 upon initialization
+ if((UINTN)(phnd->SecLang.Items[i])){
+ lang=(HII_LANG*)gHiiDb.LangDb.Items[(UINTN)(phnd->SecLang.Items[i])];
+ pBS->CopyMem(l,&lang->sName[0],sizeof(UINT16)*3);//4 unicode chars;
+ l+=3;
+ }
+ }//resulting string will be consist of N*3xUINT16+TERMINATOR
+ *l=0x0000; //put terminator at the end of set of sec lang
+ *LanguageString=ls;
+ }else { *LanguageString=NULL; return EFI_NOT_FOUND;}
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+//This is a worker function to avoid dubliceted code in HiiGetString,
+//HiiGetLine and ExtHiiGetStrInfo
+HII_STR *GetHiiString(EFI_HII_HANDLE Handle, UINT16 *Lang, STRING_REF Token){
+ UINTN li,hi;
+ UINT16 dl[4]={0x20,0x20,0x20,0}, *pdl;
+ HII_HANDLE *phnd;
+ HII_STR *str;
+//------------------------------
+ phnd=LocateHandle(Handle,&hi);
+ if(!phnd) return NULL;
+
+ if(!phnd->HasStr){
+ phnd=LocateStrHandleGuid(hi,&hi);
+ if(!phnd) return NULL;
+ }
+
+ if(!Lang){
+ pdl=&dl[0];
+ if(EFI_ERROR(GetDefaultLang(pdl)))pdl=(UINT16*)gHiiDb.LangDb.Items[phnd->PriLang];
+ } else pdl=Lang;
+
+ //dl has a language string it " " or "xxx"
+ //lang=LocateLang(pdl,&li);
+ if(!LocateLang(pdl,&li)) return NULL;
+ str=LocateString(phnd,li,Token);
+
+ // If String is not found and language is not specified,
+ // let's try with the primary package language.
+ if (!str && !Lang) str=LocateString(phnd,0,Token);
+
+ return str;
+}
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetStringNew(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLength, //in units of UINT16
+ OUT EFI_STRING StringBuffer)
+{
+ HII_STR *str;
+ UINTN j,i;
+ UINT16 *ps, sl;
+//--------------------------
+
+ if( !This || !BufferLength || *BufferLength && !StringBuffer ) return EFI_INVALID_PARAMETER;
+
+ str=GetHiiString(Handle,LanguageString,Token);
+ if(!str) return EFI_INVALID_PARAMETER;
+
+ if(str->NewStr.StrPtr){
+ ps=str->NewStr.StrPtr;
+ sl=str->NewStr.StrLen;
+ } else {
+ ps=str->String.StrPtr;
+ sl=str->String.StrLen;
+ }
+ //str->StrLen in UINT16 units
+ if(*BufferLength<sl*sizeof(UINT16)) {
+ *BufferLength=sl*sizeof(UINT16);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if(Raw){
+ pBS->CopyMem(&StringBuffer[0],ps,sl*sizeof(UINT16));
+ *BufferLength=sl*sizeof(UINT16);
+ } else {
+ for(i=0,j=0;i<(UINTN)(sl-1);i++){
+ //replace <CR> with <Space>
+ //if(ps[i]==0x0013)
+ // StringBuffer[j]=0x0020;
+ //else {
+ //skip all Special and Control Characters.
+ if((ps[i]>=0xFFF0 && ps[i]<=0xFFFF))
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//It is amazing how Intel's engineers not in compliance with
+//their own Specs.
+//"If (Raw) TRUE, the string is returned unedited in the internal storage format described
+//above. If FALSE, the string returned is edited by replacing !!<cr>!! with <space> and by
+//removing special characters such as the ??<wide>?? prefix."
+// ||(ps[i]>=0x0000 && ps[i]<=0x001F))
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ continue;
+ //Copy the rest of chars
+ else StringBuffer[j]=ps[i];
+ //}
+ j++;
+ }
+ StringBuffer[j]=0;//Terminate String!!
+ *BufferLength=(UINT16)((j+1)*sizeof(UINT16));
+ }
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetStringOld(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINT16 *BufferLength, //in units of UINT16
+ OUT EFI_STRING StringBuffer)
+{
+ EFI_STATUS Status;
+ UINTN bl;
+//-----------------
+ if(BufferLength==NULL) return EFI_INVALID_PARAMETER;
+
+ bl=(UINTN)(*BufferLength);
+ Status=HiiGetStringNew(This,Handle,Token,Raw,LanguageString,&bl,StringBuffer);
+ (*BufferLength)=(UINT16)bl;
+
+ if((Status==EFI_BUFFER_TOO_SMALL) && (bl > 0xFFFF)) Status=EFI_INVALID_PARAMETER;
+
+ return Status;
+}
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetLine(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN OUT UINT16 *Index,
+ IN UINT16 LineWidth,
+ IN CHAR16 *LanguageString,
+ IN OUT UINT16 *BufferLength,
+ OUT EFI_STRING StringBuffer)
+{
+ HII_STR *str;
+ UINTN j,i;
+ UINT16 *ps, sl;
+ BOOLEAN cr=FALSE;
+//--------------------------
+
+ if( !This || !BufferLength || !StringBuffer ) return EFI_INVALID_PARAMETER;
+
+ str=GetHiiString(Handle,LanguageString,Token);
+ if(!str) return EFI_INVALID_PARAMETER;
+
+ if(str->NewStr.StrPtr){
+ ps=str->NewStr.StrPtr;
+ sl=str->NewStr.StrLen;
+ } else {
+ ps=str->String.StrPtr;
+ sl=str->String.StrLen;
+ }
+
+ //I don't know should I remove a special chars or not
+ // So I will for now
+ for(j=0,i=*Index; (i<sl || i<LineWidth); i++ ){
+ //replace <CR> with <Space>
+ if(ps[i]==0x0013){
+ if(cr) { //if <CR> hit second time in a row - terminate string
+ StringBuffer[j]=0x0000;
+ *Index=(UINT16)i;
+ break;
+ } else { //else replece it with space an set "cr" flag
+ StringBuffer[j]=0x0020;
+ cr=TRUE;
+ }
+ }else{
+ cr=FALSE; //if we here - reset "cr" flarg
+ //skip all Special and Control Characters.
+ if((ps[i]>=0xFFF0 && ps[i]<=0xFFFF)||(ps[i]<=0x001F))
+ continue; //will not increase "j" the buffer index
+ //Copy the rest of chars into the Buffer
+ else
+ StringBuffer[j]=ps[i];
+ }
+ j++;
+ }
+ StringBuffer[j]=0;//Terminate String!!
+ *BufferLength=(UINT16)((j+1)*sizeof(UINT16));
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiResetStrings(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle)
+{
+ HII_STR *str;
+ UINTN i,hi;//,j,gbi[10],gc=0;
+ HII_HANDLE *phnd;
+//------------------------
+
+ if(!This) return EFI_INVALID_PARAMETER;
+ phnd=LocateHandle(Handle,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+
+ if(!phnd->HasStr){
+ phnd=LocateStrHandleGuid(hi,&hi);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+ }
+ //LocateSameGuidHandle(hi, &gbi[0], &gc);
+
+ //for(j=0; j<=gc; j++){
+ for(i=0; i<gHiiDb.StringDb.RecordCount;i++){
+ //if(!phnd->HasStr) break;
+ DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,i,&str);
+ if(str->Handle==phnd->Handle){
+ if(str->NewStr.StrPtr){
+ pBS->FreePool(str->NewStr.StrPtr);
+ str->NewStr.StrPtr=NULL;
+ str->NewStr.StrLen=0;
+ str->NewStr.ScrLen=0;
+ //Cleanup Dtabase from RECORDS which was addes
+ //after initial Package
+ if(!str->String.StrPtr){
+ DbeDelete(&gHiiDb.StringDb, str, TRUE);
+ i--;//we ned to step on the same data index
+ continue;
+ //since we have delited current one
+ //phnd->NextStrToken--;
+ }
+
+ }
+ }
+ if(str->Handle>phnd->Handle) break;
+ }
+ phnd->NextStrToken=phnd->StrCount;
+
+ // if(j<gc)phnd=gHiiDb.HandleDb.Items[gbi[j]];
+ //}
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS NewStringPack(IN EFI_HII_STRING_PACK *Package,
+ UINTN HandleId)
+{
+ UINTN i,lid;
+ UINT8 *ofs;
+ UINT16 *str;
+ RELOFST *ps;//string pointer
+ EFI_HII_STRING_PACK *cp=Package;
+ EFI_STATUS Status=0;
+ BOOLEAN f=TRUE;
+ HII_HANDLE *phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleId];
+//--------------------------------
+ while(!IsLastStrPack(cp)){
+ ps=(RELOFST*)(cp+1);
+ ofs=(UINT8*)cp;
+ //Check if Language exists already
+ Status=GetLanguageFromPack(cp,&lid);
+ if(EFI_ERROR(Status)) return Status;
+ if(f){//if this is first string pack make this lang Primary
+ phnd->PriLang=(UINT32)lid;
+ f=FALSE;
+ } else {
+ //All other languages if any will be Secondary languages
+ Status=LocateSecLangAdd(phnd,&lid,TRUE);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ for(i=0; i<Package->NumStringPointers; i++){
+ phnd->NextStrToken=(STRING_REF)i;
+ if(!ps[i]) continue;
+ str=(UINT16*)(ofs+ps[i]);
+ Status=AddString(lid,phnd,str,TRUE,NULL);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+
+ cp=(EFI_HII_STRING_PACK*)((UINT8*)cp+cp->Header.Length);
+ }
+ phnd->StrCount=(STRING_REF)Package->NumStringPointers;
+ phnd->HasStr=TRUE;
+ return Status;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// IFR Releated Functions
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+//this one will calculate length in bytes for the buffer designed
+//to receive a copy of form instance
+//UINT16 GetFormLen(HII_FORM *Form){
+// HII_LABEL *lbl;
+// UINTN i;
+// UINT16 len=Form->BufferLength;
+//------------------------
+// for(i=0; i<Form->Labels.ItemCount; i++){
+// lbl=Form->Labels.Items[i];
+// if(lbl->Erased) len-=lbl->OrgDataLength;
+// len+=lbl->UpdDataLength;
+// }
+// return len;
+//}
+
+///////////////////////////////////////////////////////////////////
+//this one will calculate length in bytes for the buffer designed
+//to receive a copy of FormSet instance
+//UINT16 GetFormSetLen(HII_FORMSET *FormSet){
+// UINT16 len=0;
+// UINTN i;
+// HII_FORM *frm;
+//------------------
+// for(i=0; i<FormSet->Forms.ItemCount; i++){
+// frm=FormSet->Forms.Items[i];
+// len+=GetFormLen(frm);
+// }
+// return len+FormSet->FormSetData->Header.Length+FormSet->EndFormSet->Header.Length;
+//}
+
+UINTN GetDataLen( UINT8 *OpCode, UINTN *Count, BOOLEAN Remove){
+ UINTN i;
+ UINTN len=0;
+ UINT8 *p=OpCode;
+//------------------------
+ for(i=0; i<*Count; i++){
+// if( !Remove &&
+// ( (*p)==EFI_IFR_END_FORM_OP || (*p)==EFI_IFR_LABEL_OP )
+// ){
+// i=i;
+// }
+ if( ( Remove && ( (*p)==EFI_IFR_END_FORM_OP || (*p)==EFI_IFR_LABEL_OP )
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ //when adding data I expect that caller knows what he is doing and
+ //passes me correct Data Count. Guess what? This is not TRUE in Intel's Setup.
+ //Intel uses Zeroed buffer to fill with desired Opcodes, set Data count to 0xFF and here we go.
+ //In this case if in buffer we will found junk which satisfy conditions below
+ //we can seriousely scrue up!!!!!
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ || ((*p)==0 || (*p)>EFI_IFR_VARSTORE_SELECT_PAIR_OP ))){
+ *Count=i;
+ break;
+ }
+ len = len + ((EFI_IFR_OP_HEADER*)p)->Length;
+ p=OpCode+len;
+ }
+ return len;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//this will copy form from HII DB private storage to decignated Buffer
+VOID CopyForm(UINT8* Buffer, HII_FORM *Form, UINTN *BytesCnt){
+ UINTN i,cnt=0;
+ HII_LABEL *lbl=NULL;
+ UINT8 *bp=Buffer;
+//----------------
+
+ //Now First Label has data starting from opcode next to FORM_OP
+ //and lbl->Label of very first label in the list actualy FORM_OP
+ //so don't need following code
+
+ //if(Form->Labels.ItemCount)lbl=(HII_LABEL*)Form->Labels.Items[0];
+ //1. copy form till first label (including LABEL OPCODE)
+ //if(lbl)//Total Bufferlength including EOF opcode
+ // cnt=(UINT8*)(lbl->Label)-(UINT8*)Form->FormData;
+ //else
+ // cnt=Form->BufferLength-Form->EndForm->Header.Length;
+
+ //pBS->CopyMem(bp,Form->FormData,For);
+ //bp+=cnt; //Advance buffer pointer;
+ //(*BytesCnt)=cnt;
+ (*BytesCnt)=0;
+ //Keep circling trough Labels copying corresponded data
+ for(i=0;i<Form->Labels.ItemCount;i++){
+ lbl=(HII_LABEL*)Form->Labels.Items[i];
+ //copy Label OpCode
+ pBS->CopyMem(bp,lbl->Label,lbl->Label->Header.Length);
+ bp+=lbl->Label->Header.Length;
+ (*BytesCnt)+=lbl->Label->Header.Length;
+
+ //if Label was updated copy Update data first...
+ if(lbl->LabelData){
+ pBS->CopyMem(bp,lbl->LabelData,lbl->DataLength);
+ bp+=lbl->DataLength;
+ (*BytesCnt)+=lbl->DataLength;
+ }
+ }
+ //Copy EOF opcode
+ cnt=Form->EndForm->Header.Length;
+ pBS->CopyMem(bp,Form->EndForm,cnt);
+ (*BytesCnt)+=cnt;
+ return;
+}
+
+///////////////////////////////////////////////////////////////////
+//will copy entire formset data excluding Pcakage Header
+VOID CopyFormSet(UINT8* Buffer, HII_FORMSET *FormSet, UINTN *BytesCnt){
+ UINTN i;
+ UINT8 *bp=Buffer,*pp;
+ UINTN cnt;
+ HII_FORM *frm;
+//----------------
+ bp=Buffer;
+ //Copy Formset OpCode...
+ pBS->CopyMem(bp,FormSet->FormSetData,FormSet->FormSetData->Header.Length);
+ bp+=FormSet->FormSetData->Header.Length;
+ *BytesCnt=FormSet->FormSetData->Header.Length;
+ //Copy any information that we might have from end of FormSet Opcode
+ //to the befinning of FOrm OpCode VARSTORE for example.
+ if(FormSet->Forms.ItemCount){
+ pp=(UINT8*)FormSet->FormSetData+FormSet->FormSetData->Header.Length;
+ frm=FormSet->Forms.Items[0];
+ cnt=(UINTN)((UINT8*)frm->FormData-pp);
+ pBS->CopyMem(bp,pp,cnt);
+ bp+=cnt;
+ *BytesCnt+=cnt;
+ }
+
+ for(i=0; i<FormSet->Forms.ItemCount; i++){
+ frm=FormSet->Forms.Items[i];
+ CopyForm(bp,frm,&cnt);
+ bp+=cnt;
+ *BytesCnt+=cnt;
+ }
+ //copy END_OF_FORM_SET OP here
+ cnt=FormSet->EndFormSet->Header.Length;
+ pBS->CopyMem(bp,&FormSet->EndFormSet->Header.OpCode,cnt);
+ *BytesCnt+=cnt;
+ return;
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// Cache Form and Formset
+HII_FORM *LocateForm(HII_FORMSET *FormSet, EFI_FORM_ID FormId){
+ EFI_STATUS Status=0;
+ UINTN fid;
+//----------------------------------------------
+ Status=LocateItem(&FormSet->Forms,&FormId,sizeof(EFI_FORM_ID),&fid);
+ if(EFI_ERROR(Status)) return NULL;
+
+ return (HII_FORM*)FormSet->Forms.Items[fid];
+}
+
+///////////////////////////////////////////////////////////////////
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// Cache Form and Formset
+HII_FORMSET *LocateFormSet(UINTN HandleIdx, UINTN* FormSetIdx){
+ EFI_STATUS Status=0;
+ UINTN fsid;
+//--------------------------
+ Status=LocateItem(&gHiiDb.IfrDb,&((UINT32)HandleIdx),sizeof(UINT32),&fsid);
+ if(EFI_ERROR(Status)) return NULL;
+ if(FormSetIdx!=NULL)*FormSetIdx=fsid;
+ return (HII_FORMSET*)gHiiDb.IfrDb.Items[fsid];
+}
+
+
+HII_LABEL *LocateFormLabel(HII_FORM *Form, EFI_FORM_LABEL LabelId, UINTN *LabelIdx){
+ EFI_STATUS Status=0;
+ UINTN lid;
+//----------------------------------------------
+ Status=LocateItem(&Form->Labels,&LabelId, sizeof(EFI_FORM_LABEL),&lid);
+ if(EFI_ERROR(Status)) return NULL;
+
+ *LabelIdx=lid;
+ return (HII_LABEL*)Form->Labels.Items[lid];
+}
+
+HII_LABEL *LocateFormSetLabel(HII_FORMSET *FormSet, EFI_FORM_LABEL LabelId, UINTN *LabelIdx){
+ EFI_STATUS Status=0;
+ UINTN lid;
+//----------------------------------------------
+ Status=LocateItem(&FormSet->Labels,&LabelId, sizeof(EFI_FORM_LABEL),&lid);
+ if(EFI_ERROR(Status)) return NULL;
+
+ if(LabelIdx)*LabelIdx=lid;
+ return (HII_LABEL*)FormSet->Labels.Items[lid];
+}
+
+
+///////////////////////////////////////////////////////////////////
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//This MUST be here to make Shell working
+static UINT8 gDummyVfr[] = {
+ //Header
+ 0x2c, 0x00, 0x00, 0x00, //Actual Length of Data Buffer
+ 0x03, 0x00, //Type;
+ // start of IFR data
+ /*O*/ 0x0E, //Opcode=EFI_IFR_FORM_SET_OP
+ /*L*/ 0x24, //Length
+ //Offset=8
+ /*G*/ 0xBC, 0x30, 0x0C, 0x9E, 0x06, 0x3F, 0xA6, 0x4B, 0x82, 0x88, 0x09, 0x17, 0x9B, 0x85, 0x5D, 0xBE, //GUID
+ /*S*/ 0x02, 0x00, //FormSet Title
+ /*S*/ 0x00, 0x00, //Help
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//Callback
+ 0x00, 0x00, //Class
+ 0x00, 0x00, //SubClass
+ 0x00, 0x00, //NvDataSize
+ /*O*/ 0x0D, //OpCOde=EFI_IFR_END_FORM_SET_OP
+ /*L*/ 0x02,
+};
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+///////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetFormsNew(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLength,
+ OUT UINT8 *Buffer)
+{
+ UINTN hid;
+ HII_FORMSET *fs;
+ HII_FORM *frm;
+ HII_HANDLE *phnd;
+ UINTN len;
+//--------------------------------------
+ if(This==NULL && BufferLength==NULL) return EFI_INVALID_PARAMETER;
+ //phnd=LocateHandle(Handle, &hid);
+ //TODO: Felix: by the HII Spec. we should return EFI_INVALID_PARAMETER
+ //However, Intel Device Manager expects EFI_NOT_FOUND
+ //(it hangs if it is something else)
+ phnd=LocateHandle(Handle, &hid);
+ if(!phnd) return EFI_NOT_FOUND;
+
+ fs=LocateFormSet(hid, NULL);
+ if(!fs){
+ if(!FormId){
+ //Technically I must Return NOT_FOUND ERROR but...
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this patch was made to keep Shell working. Shell and HII coexistance is
+//based on assumption that "It must be some IFR pack associated with String pack"
+//If this statement FALSE Shell will hang in INFINITE LOOP!!!!
+////////////////////////////////////////////////////////////////////////
+//this comments I took from Intel's HII Database Driver
+// "If someone is passing in a string only, create a dummy IfrPack with a Guid
+// to enable future searching of this data."
+////////////////////////////////////////////////////////////////////////
+ if(*BufferLength< sizeof(gDummyVfr)) {
+ *BufferLength=sizeof(gDummyVfr);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *BufferLength=sizeof(gDummyVfr);
+ pBS->CopyMem(Buffer,&gDummyVfr[0],sizeof(gDummyVfr));
+ //copy handle guid here Shell expect it to mutch with some standart guids
+ pBS->CopyMem((VOID*)(Buffer+8),(VOID*)&(phnd->Guid),sizeof(EFI_GUID));
+ return EFI_SUCCESS;
+ } else return EFI_NOT_FOUND;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ }
+
+ if(!FormId){//we must return whole FormSet
+ //STUPID SHELL expect me to return formset with EFI_HII_PACK_HEADER
+ // why? I don't know!
+ len=fs->BufferLength+sizeof(EFI_HII_PACK_HEADER);
+ } else {
+ frm=LocateForm(fs,FormId);
+ if(!frm) return EFI_NOT_FOUND;
+ len=frm->BufferLength;
+ }
+
+ if(*BufferLength<len){
+ *BufferLength=len;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *BufferLength=len;
+
+ //If "FormId" we must return whole FormSet
+ if(!FormId){
+ //STUPID SHELL expect me to return formset with EFI_HII_PACK_HEADER
+ //Create it
+ *((UINT32*)Buffer)=(UINT32)len;
+ *((UINT16*)(Buffer+4))=3;//IFR Type
+ CopyFormSet(Buffer+6,fs,&hid);
+ }
+ else
+ CopyForm(Buffer,frm,&hid);
+
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiGetFormsOld(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINT16 *BufferLength,
+ OUT UINT8 *Buffer)
+{
+ EFI_STATUS Status=0;
+ UINTN bl;
+//--------------------------------
+ if(BufferLength==NULL) return EFI_INVALID_PARAMETER;
+
+ bl=(UINTN)(*BufferLength);
+ Status=HiiGetFormsNew(This,Handle,FormId,&bl,Buffer);
+ (*BufferLength)=(UINT16)bl;
+
+ if((Status==EFI_BUFFER_TOO_SMALL) && (bl > 0xFFFF)) Status=EFI_INVALID_PARAMETER;
+ return Status;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//Will free all memory blocks associated with Label->Objects structures
+VOID DeleteLabelObjects(HII_LABEL *Label){
+ UINTN i;
+ HII_OBJECT *obj;
+//------------------
+ for(i=0;i<Label->Objects.ItemCount; i++){
+ obj=Label->Objects.Items[i];
+ ClearItemLst(&obj->Conditions,FALSE);
+ ClearItemLst(&obj->Options,FALSE);
+ }
+ ClearItemLst(&Label->Objects,TRUE);
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiUpdateForm(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN EFI_HII_UPDATE_DATA *Data)
+{
+ EFI_STATUS Status=0;
+ UINTN hid,lid;
+ HII_FORMSET *fs;
+ HII_FORM *frm;
+ HII_LABEL *lbl;
+ UINTN len,cnt;
+ UINT8 *ub;
+ EFI_IFR_OP_HEADER *op;
+//-------------------------
+ if(!This || !Data ) return EFI_INVALID_PARAMETER;
+
+ if(!LocateHandle(Handle, &hid)) return EFI_INVALID_PARAMETER;
+
+ //Find Formset
+ fs=LocateFormSet(hid, NULL);
+ if(!fs) return EFI_INVALID_PARAMETER;
+
+ //Find Label
+ //FormUpdate= TRUE means just change Form Title!!!
+ if(Data->FormUpdate){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//In Intel's HII implementation Data->FormValue field is missing
+ //Find Form using UPDATE Data
+// frm=LocateForm(fs,Data->FormValue);
+// if(!frm) return EFI_NOT_FOUND;
+ //Update Form Title
+// frm->FormData->FormTitle=Data->FormTitle;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ }
+
+ //
+ if(Data->DataCount){
+ //Find Label
+ lbl=LocateFormSetLabel(fs, Label, &lid);
+ if(!lbl) return EFI_NOT_FOUND;
+ frm=lbl->OwnerForm;
+ cnt=Data->DataCount;
+ if(AddData){
+ op=(EFI_IFR_OP_HEADER*)&Data->Data;
+ if(!op->OpCode || !op->Length) return EFI_INVALID_PARAMETER;
+ //Calculate size of UPDATE data
+ len=GetDataLen((UINT8*)op,&cnt,FALSE);
+ ub=Malloc(len+lbl->DataLength);
+ if(!ub) return EFI_OUT_OF_RESOURCES;
+
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ //Copy Update Data in Private Buffer
+ pBS->CopyMem(ub,op,len);
+ //Copy Old Data in same Private Buffer
+ if(lbl->LabelData)pBS->CopyMem((VOID*)(ub+len),lbl->LabelData,lbl->DataLength);
+//for coimpatibility with Intel's setup I've change order in which the chanks of opcodes
+// been copied in a new label buffer - New data will be added after the old data
+ //if(lbl->LabelData)pBS->CopyMem(ub,lbl->LabelData,lbl->DataLength);
+ //pBS->CopyMem((VOID*)(ub+lbl->DataLength),op,len);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+
+ //Update Buffer parameters in every structure affected by update
+ lbl->DataLength = lbl->DataLength + len;
+ lbl->DataCount = lbl->DataCount + Data->DataCount;
+ if(lbl->Updated && lbl->LabelData)pBS->FreePool(lbl->LabelData);
+ lbl->LabelData=(EFI_IFR_OP_HEADER*)ub;
+ fs->BufferLength = fs->BufferLength + len;
+ frm->BufferLength = frm->BufferLength + len;
+ //Delete Old Data
+ DeleteLabelObjects(lbl);
+ }else{
+ //we will not erase an empty Label!
+ if(lbl->LabelData){
+ op=lbl->LabelData;
+ if(Data->DataCount>=lbl->DataCount){
+ cnt=lbl->DataCount;
+ len=lbl->DataLength;
+ } else len=GetDataLen((UINT8*)op,&cnt,TRUE);
+
+ //if after erasing no data has left, no need to allocate new buffer
+ if((INTN)(lbl->DataLength-len)>0){
+ ub=Malloc(lbl->DataLength-len);
+ if(!ub)
+ return EFI_OUT_OF_RESOURCES;
+ //Copy rest of Old Data in Private Buffer
+ pBS->CopyMem(ub,(UINT8*)lbl->LabelData+len,lbl->DataLength-len);
+ } else ub=NULL;
+
+ //Update Buffer parameters in every structure affected by update
+ lbl->DataLength = lbl->DataLength - len;
+ lbl->DataCount = lbl->DataCount - cnt;
+ if(lbl->Updated && lbl->LabelData)pBS->FreePool(lbl->LabelData);
+ lbl->LabelData=(EFI_IFR_OP_HEADER*)ub;
+ fs->BufferLength = fs->BufferLength - len;
+ frm->BufferLength = frm->BufferLength - len;
+ DeleteLabelObjects(lbl);
+ }
+ }
+ //Populate pointers on Label Objects from Label Dtat Buffer
+ if(lbl->LabelData!=NULL)Status=CreateLabelObjects(lbl);
+ if(EFI_ERROR(Status))return Status;
+ lbl->Updated=TRUE;
+
+ if(lbl->UpdateCallBack) lbl->UpdateCallBack(Label, Handle,AddData);
+ }
+
+ if(Data->FormSetUpdate){
+ fs->FormSetData->CallbackHandle=Data->FormCallbackHandle;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS InitDefStorage(HII_FORMSET *FormSet){
+ EFI_STATUS Status;
+ HII_STORE *st;
+ static CHAR8 *ss="Setup";//{'S','e','t','u','p',0};
+ CHAR8 *pn;//pointer to var name;
+//------------------------------------------------
+ st=MallocZ(sizeof(HII_STORE));
+ if(!st)return EFI_OUT_OF_RESOURCES;
+
+ Status=AppendItemLst(&FormSet->Storages,st);
+
+ st->VarStore=MallocZ(sizeof(EFI_IFR_VARSTORE)+6);
+ if(!st->VarStore)return EFI_OUT_OF_RESOURCES;
+
+ //Init Default VarStore Structure VarId is Always 0x0000
+ st->VarStore->Header.Length=sizeof(EFI_IFR_VARSTORE)+6;
+ st->VarStore->Header.OpCode=EFI_IFR_VARSTORE_OP;
+ st->VarStore->Size=FormSet->FormSetData->NvDataSize;
+
+ //Copy formset GUID here
+ pBS->CopyMem(&st->VarStore->Guid,&FormSet->FormSetData->Guid,sizeof(EFI_GUID));
+
+ pn=(CHAR8*)st->VarStore;
+ pn+=sizeof(EFI_IFR_VARSTORE);
+ pBS->CopyMem(pn,ss,6);
+
+ return EFI_SUCCESS;
+}
+
+//Selects Var Store Object
+HII_STORE *LocateStorage(HII_FORMSET *FormSet, UINT16 VarId, UINTN *StoreId OPTIONAL){
+ UINTN i;
+ HII_STORE *st;
+//---------------------
+ for(i=0; i<FormSet->Storages.ItemCount; i++){
+ st=(HII_STORE*)FormSet->Storages.Items[i];
+ if(st->VarStore->VarId==VarId) {
+ if(StoreId)*StoreId=i;
+ return st;
+ }
+ }
+ return NULL;
+}
+
+
+EFI_STATUS CreateLabelObjects(HII_LABEL *Label)
+{
+ EFI_IFR_OP_HEADER *op;
+ UINTN i,j=0, k;
+ HII_OBJECT *obj=NULL;
+ HII_STORE *st1=NULL, *st2=NULL;
+ static T_ITEM_LIST clst={0,0,NULL},olst={0,0,NULL}; //temp conditions and objects list list
+ static T_ITEM_LIST supprstores = {0, 0, NULL};
+ EFI_STATUS Status;
+ BOOLEAN cf=FALSE; //conditions flag
+ BOOLEAN Suppress = FALSE;
+//-------------------------------------------
+ op=Label->LabelData;
+
+ obj=NULL;
+ //st1=(HII_STORE*)Label->OwnerForm->Owner->Storages.Items[0];
+ st1 = LocateStorage(Label->OwnerForm->Owner, CurrentVarId, NULL);
+ if(!st1) { st1=(HII_STORE*)Label->OwnerForm->Owner->Storages.Items[0]; CurrentVarId = 0; }
+ st2=NULL;
+ for(i=0;i<Label->DataCount;i++){
+ //Select Default Storage so Store1
+ switch(op->OpCode){
+ //Storage Select Opcodes
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ {
+ EFI_IFR_VARSTORE_SELECT *vs=(EFI_IFR_VARSTORE_SELECT*)op;
+ HII_STORE *st=LocateStorage(Label->OwnerForm->Owner,vs->VarId,NULL);
+ // preserve the varstore selection - to be reset only by the next varstore select
+ // or a new formset
+ //------------------------
+ if(st) { st1=st; CurrentVarId = vs->VarId; }
+ }
+ break;
+ case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
+ {
+ EFI_IFR_VARSTORE_SELECT_PAIR *v2=(EFI_IFR_VARSTORE_SELECT_PAIR*)op;
+ HII_STORE *s1=LocateStorage(Label->OwnerForm->Owner,v2->VarId,NULL);
+ HII_STORE *s2=LocateStorage(Label->OwnerForm->Owner,v2->SecondaryVarId,NULL);
+ //------------------------
+ if(s1) { st1=s1; CurrentVarId = v2->VarId; }
+ if(s2) st2=s2;
+ }
+ break;
+ //Condition OpCodes
+ case EFI_IFR_GRAYOUT_IF_OP:
+ case EFI_IFR_SUPPRESS_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ //if we found some logical expression and local ovject list(olst) has some objects
+ //we must add this objects with no conditions to the Label->Objects list
+ //and clear local object list to start fill it with objects who has conditions.
+ if(!cf){
+ for(j=0;j<olst.ItemCount;j++){
+ obj=olst.Items[j];
+ Status=AppendItemLst(&Label->Objects,obj);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+ ClearItemLst(&olst,FALSE);
+ obj=NULL;
+ }
+ cf=TRUE;
+ if( op->OpCode == EFI_IFR_SUPPRESS_IF_OP) Suppress = TRUE;
+ else Suppress = FALSE;
+ ///////////////////////////////////////////////////////////////////////
+ //Do not add break instruction here it is not present for a reason!!!!
+ ///////////////////////////////////////////////////////////////////////
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_EQ_ID_VAL_OP:
+ case EFI_IFR_EQ_ID_ID_OP:
+ case EFI_IFR_EQ_ID_LIST_OP:
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ //Add Opcode to the temp Condition list;
+ Status=AppendItemLst(&clst,op);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;//out of resources
+
+ if(op->OpCode == EFI_IFR_EQ_ID_VAL_OP && Suppress)
+ {
+ Status = AppendItemLst(&supprstores, st1);
+ ASSERT(!EFI_ERROR(Status));
+ }
+ break;
+ //end of conditions OpCode
+ case EFI_IFR_END_IF_OP:
+ //this is definetely end of object presentation,
+ //but some times it might be no object to add conditions info to
+ if(!olst.ItemCount){
+ for(j=0; j<clst.ItemCount;j++) {
+ Status=AppendItemLst(&Label->Conditions,clst.Items[j]);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }
+ for(j=0;j<olst.ItemCount;j++){
+ obj=olst.Items[j];
+ //I'm trying to allocate exactly as mutch memory as I need for Conditions.Items[] array.
+ //If you initialize ItemList.InitialCount with some specific value>0, then next call to
+ //Append ItemLst function will allocate this number of entries for ItemList.Items[] Array.
+ obj->Conditions.InitialCount=clst.ItemCount;
+ Status=AppendItemLst(&obj->Conditions,clst.Items[0]);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ pBS->CopyMem(&obj->Conditions.Items[1],&clst.Items[1],sizeof(VOID*)*(clst.ItemCount-1));
+ obj->Conditions.ItemCount=clst.ItemCount;
+ for(k = 0; k < supprstores.ItemCount; k++)
+ {
+ Status=AppendItemLst(&obj->SuppressStores,supprstores.Items[k]);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ Status=AppendItemLst(&Label->Objects,obj);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+ ClearItemLst(&clst,FALSE); //don't need to free data - it's VFR pointers!
+ ClearItemLst(&olst,FALSE);
+ ClearItemLst(&supprstores,FALSE);
+ obj=NULL;
+ cf=FALSE;
+ Suppress = FALSE;
+ break;
+ //visual opcodes
+ case EFI_IFR_SUBTITLE_OP:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_INVENTORY_OP:
+ case EFI_IFR_GRAPHIC_OP:
+ case EFI_IFR_CHECKBOX_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_REF_OP:
+ case EFI_IFR_DATE_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_SAVE_DEFAULTS_OP:
+ case EFI_IFR_RESTORE_DEFAULTS_OP:
+ case EFI_IFR_HIDDEN_OP:
+ //continiouse
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_ORDERED_LIST_OP:
+ ASSERT(!obj); //obj pointer must be cleared when we enter there
+ if(obj)return EFI_INVALID_PARAMETER;
+ obj=MallocZ(sizeof(HII_OBJECT));
+ ASSERT(obj);//Allocation Problems!
+ if(!obj) return EFI_OUT_OF_RESOURCES;
+ obj->ObjectCode=op;
+ obj->Store1=st1;
+ obj->Store2=st2;
+ Status=AppendItemLst(&olst,obj);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ //in case of DATE or Time opcode advance by 2 opcodes
+ if(op->OpCode==EFI_IFR_TIME_OP || op->OpCode==EFI_IFR_DATE_OP){
+ op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ i+=2;
+ }
+ obj=NULL;
+ break;
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ ASSERT(olst.ItemCount);
+ if(!olst.ItemCount) return EFI_INVALID_PARAMETER;
+ obj=(HII_OBJECT*)olst.Items[olst.ItemCount-1];
+ if(!obj) return EFI_INVALID_PARAMETER; //obj must be allocated!
+ Status=AppendItemLst(&obj->Options,op);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;//out of resources
+ break;
+ case EFI_IFR_END_ONE_OF_OP:
+ obj=NULL;
+ break;
+
+ }//end switch;
+ //Advance to next opcode
+ op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ }
+ //If there were no any Condition Opcodes contents of the ObjectList(olst) was not copied to the Label.Objects
+ for(j=0;j<olst.ItemCount;j++){
+ obj=olst.Items[j];
+ Status=AppendItemLst(&Label->Objects,obj);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+ ClearItemLst(&olst,FALSE);
+ return EFI_SUCCESS;
+}
+
+//This Routine is called to parse FormVfr and Create Objects which must be shown on the screen;
+EFI_STATUS CreateFormObjects(HII_FORM *Form){
+ UINTN i;
+ EFI_STATUS Status = EFI_SUCCESS;
+//---------------------------------
+
+ for(i=0; i<Form->Labels.ItemCount; i++){
+ Status=CreateLabelObjects((HII_LABEL*)Form->Labels.Items[i]);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status))return Status;
+ }
+ return Status;
+}
+
+EFI_STATUS NewKbdPack(EFI_HII_KEYBOARD_PACK *Package,
+ UINTN HandleId)
+{
+ EFI_STATUS Status;
+ HII_KB_LAYOUT_DATA *kbld;
+//--------------------
+ //Get Some Memory to accomodate Kb Layout Buffer
+ kbld=Malloc(sizeof(EFI_KEY_DESCRIPTOR)*Package->DescriptorCount+sizeof(HII_KB_LAYOUT_DATA));
+ ASSERT(kbld);
+ if(kbld==NULL) return EFI_OUT_OF_RESOURCES;
+
+ kbld->HandleIndex=HandleId; //just in case to find HII_HANDLE structure assotiated with this PACK
+ kbld->KeyDscCount=Package->DescriptorCount;
+ //We will store KB Layout Data right after the HII_KB_LAYOUT_DATA structure itself
+ kbld->KeyDsc=(EFI_KEY_DESCRIPTOR*)(kbld+1);
+ MemCpy((VOID*)kbld->KeyDsc, (VOID*)Package->Descriptor, sizeof(EFI_KEY_DESCRIPTOR)*kbld->KeyDscCount);
+
+ //Add saved KB Layout Data to the HII DB
+ Status=AppendItemLst((T_ITEM_LIST*)&gHiiDb.KeybdDb.KblInitCount,(VOID*)kbld);
+ ASSERT_EFI_ERROR(Status);
+
+ //Set recently submitted KB Layout as the current one
+ gHiiDb.KeybdDb.ActiveLayout=gHiiDb.KeybdDb.KblCount-1;
+
+ return Status;
+}
+
+EFI_STATUS NewIfrPack(EFI_HII_IFR_PACK *Package,
+ UINTN HandleId)
+{
+ EFI_STATUS Status;
+ EFI_IFR_OP_HEADER *op;
+// INT32 id=0;
+ HII_FORM *cf=NULL;
+ HII_FORMSET *cfs=NULL;
+ HII_LABEL *cl=NULL;
+ HII_STORE *st=NULL;
+ HII_HANDLE *phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleId];
+ UINT8 *p;
+ BOOLEAN la=FALSE;//label active flag - helps count OPCODES and Label.dLength
+//---------------------------------------------
+ //Copy Data to a new Storage =(EFI_IFR_OP_HEADER*)(Package+1);
+ p=Malloc(Package->Header.Length);
+ if(!p) return EFI_OUT_OF_RESOURCES;
+ pBS->CopyMem(p,Package,Package->Header.Length);
+
+ op=(EFI_IFR_OP_HEADER*)(p+sizeof(EFI_HII_PACK_HEADER));
+ //Parse IFR and crete Working set of data
+ //Every IFR Pack must start from FORM_SET_OP
+ while(/*(op->OpCode!=EFI_IFR_END_FORM_SET_OP)||*/((UINTN)op<((UINTN)p)+Package->Header.Length)){
+ switch (op->OpCode){
+ //Take care of Forms Sets
+ case EFI_IFR_FORM_SET_OP:
+ CurrentVarId = 0;
+ cfs=MallocZ(sizeof(HII_FORMSET));
+ if(!cfs) return EFI_OUT_OF_RESOURCES;
+ //cfs->BufferLength=0; it is 0
+ cfs->FormSetData=(EFI_IFR_FORM_SET*)op;
+ cfs->HandleId=(UINT32)HandleId;
+ cfs->Handle=phnd->Handle;
+ //Setup Initial Storage var
+ Status=InitDefStorage(cfs);
+ if(EFI_ERROR(Status)) return Status;
+ break;
+ case EFI_IFR_VARSTORE_OP:
+ if(!cfs) return EFI_INVALID_PARAMETER;
+ st=MallocZ(sizeof(HII_STORE));
+ if(!st) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&cfs->Storages,st);
+ st->VarStore=(EFI_IFR_VARSTORE*)op;
+ break;
+ case EFI_IFR_END_FORM_SET_OP:
+ if(!cfs)return EFI_INVALID_PARAMETER; //found EFI_IFR_END_FORM_SET_OP without EFI_IFR_FORM_SET_OP
+ //cfs->BufferLength=(UINT16)((UINT8*)op+op->Length-(UINT8*)cfs->FormSetData);
+ CurrentVarId = 0;
+ cfs->EndFormSet=(EFI_IFR_END_FORM_SET*)op;
+ cfs->HandleId=(UINT32)HandleId;
+ cfs->BufferLength = cfs->BufferLength + op->Length;
+ Status=AppendItemLst(&gHiiDb.IfrDb,(VOID*)cfs);
+ if(EFI_ERROR(Status)) return Status;
+ cfs=NULL;
+ break;
+ //Take care of Forms and Labels
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_LABEL_OP:
+ {
+ EFI_IFR_OP_HEADER *nxt;
+ //----------------------------
+ if(op->OpCode==EFI_IFR_FORM_OP){
+ //it must be some FORM_SET OpCode before we met FORM OpCode
+ if(!cfs) return EFI_INVALID_PARAMETER;
+ cf=MallocZ(sizeof(HII_FORM));
+ if(!cf) return EFI_OUT_OF_RESOURCES;
+ //cf->BufferLength=0;
+ cf->FormData=(EFI_IFR_FORM*)op;
+ cf->FormId=cf->FormData->FormId;
+ cf->Owner=cfs;
+ }
+ if(!cf && !cfs )return EFI_INVALID_PARAMETER; //Form mus be present
+ cl=MallocZ(sizeof(HII_LABEL));
+ if(!cl) return EFI_OUT_OF_RESOURCES;
+
+ cl->OwnerForm=cf;
+ cl->Label=(EFI_IFR_LABEL*)op;
+ //it must be a valid opcode next...
+ nxt=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ if(nxt->OpCode!=EFI_IFR_END_FORM_OP && nxt->OpCode!=EFI_IFR_LABEL_OP)cl->LabelData=nxt;
+
+ if(op->OpCode==EFI_IFR_FORM_OP){
+ cl->LabelId=0xFACE; //Fake LabelID
+ } else {
+ cl->LabelId=cl->Label->LabelId;
+ Status=AppendItemLst(&cfs->Labels,cl);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ Status=AppendItemLst(&cf->Labels,cl);
+ if(EFI_ERROR(Status)) return Status;
+
+ la=TRUE;
+ }
+ break;
+ case EFI_IFR_END_FORM_OP:
+ if(!cf)return EFI_INVALID_PARAMETER; //found EFI_IFR_END_FORM_OP without EFI_IFR_FORM_OP
+ //cf->BufferLength=(UINT16)((UINT8*)op+op->Length-(UINT8*)cf->FormData);
+ cf->EndForm=(EFI_IFR_END_FORM*)op;
+ cf->BufferLength = cf->BufferLength + op->Length;
+ Status=AppendItemLst(&cfs->Forms,cf);
+ if(EFI_ERROR(Status)) return Status;
+ Status=CreateFormObjects(cf);
+ cf=NULL;
+ la=FALSE;
+ break;
+ //Labels Has Left
+ /*case EFI_IFR_LABEL_OP:{
+ EFI_IFR_OP_HEADER *nxt;
+ //---------------------------
+ if(!cf && !cfs )return EFI_INVALID_PARAMETER; //Form mus be present
+ cl=MallocZ(sizeof(HII_LABEL));
+ if(!cl) return EFI_OUT_OF_RESOURCES;
+
+ cl->Label=(EFI_IFR_LABEL*)op;
+ cl->LabelId=cl->Label->LabelId;
+ cl->OwnerForm=cf;
+ nxt=(EFI_IFR_OP_HEADER*)(cl->Label+1);
+ //it must be a valid opcode next...
+ if(nxt->OpCode!=EFI_IFR_END_FORM_OP && nxt->OpCode!=EFI_IFR_LABEL_OP)cl->LabelData=nxt;
+
+ Status=AppendItemLst(&cf->Labels,cl);
+ if(EFI_ERROR(Status)) return Status;
+
+ Status=AppendItemLst(&cfs->Labels,cl);
+ if(EFI_ERROR(Status)) return Status;
+ la=TRUE;
+ break;
+ }
+ */
+ default :
+ if(la){
+ cl->DataCount++;
+ cl->DataLength = cl->DataLength + op->Length;
+ }
+ } //Switch
+ if(cfs)cfs->BufferLength = cfs->BufferLength + op->Length;
+ if(cf)cf->BufferLength = cf->BufferLength + op->Length;
+ op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ }
+ phnd->Ifr=p;
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+// Common Interface functions
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiNewPackNew(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *Packages,
+ OUT EFI_HII_HANDLE *Handle)
+{
+ UINTN i;
+ EFI_HII_PACK_HEADER *hdr, **hdrptr;
+ EFI_STATUS Status=0;
+ UINTN c=0,hid=0;
+ HII_HANDLE *phnd=NULL;
+ BOOLEAN sp=0,vp=0,hp=0;
+//-----------------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ hdrptr=(EFI_HII_PACK_HEADER**)(Packages+1);
+ for(i=0; i<Packages->NumberOfPackages; i++){
+ hdr=hdrptr[i];
+ switch(hdr->Type){
+ case EFI_HII_FONT:
+ Status=NewFontPack((EFI_HII_FONT_PACK*)hdr);
+ if(EFI_ERROR(Status)) return Status;
+ break;
+ case EFI_HII_STRING:
+ if(sp)return EFI_INVALID_PARAMETER;
+ phnd=LocateHandleGuid(Packages->GuidId,&hid);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this is wrong !!!
+ //here we are trying to check if somebody using passed GuidId registered Ifr with us
+ //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different
+ //Ifr instances. To maintain compatibility I'll try to patch code...
+ if(!phnd || phnd->HasStr){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Packages->GuidId,&hid);
+ if(Status) return Status;
+ else c++;
+ phnd=gHiiDb.HandleDb.Items[hid];
+ }
+ Status=NewStringPack((EFI_HII_STRING_PACK*)hdr, hid);
+ if(EFI_ERROR(Status)) return Status;
+ sp=TRUE;
+ break;
+ case EFI_HII_IFR:
+ if(vp)return EFI_INVALID_PARAMETER;
+ phnd=LocateHandleGuid(Packages->GuidId,&hid);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this is wrong !!!//same goes gor IFR
+ if(!phnd || phnd->Ifr){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Packages->GuidId,&hid);
+ if(Status) return Status;
+ else c++;
+ phnd=gHiiDb.HandleDb.Items[hid];
+ }
+
+ Status=NewIfrPack((EFI_HII_IFR_PACK*)hdr, hid);
+ if(EFI_ERROR(Status)) return Status;
+ vp=TRUE;
+ break;
+ case EFI_HII_KEYBOARD:
+ Status=NewKbdPack((EFI_HII_KEYBOARD_PACK*)hdr, hid);
+ break;
+ case EFI_HII_HANDLES:
+ if(hp)return EFI_INVALID_PARAMETER;
+//TODO
+ hp=TRUE;
+ break;
+ case EFI_HII_VARIABLE:
+//TODO
+ break;
+ case EFI_HII_DEVICE_PATH:
+//TODO
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }//switch
+ }
+ if(c)gHiiDb.NextHiiHandle++;
+
+ if(phnd)*Handle=phnd->Handle;
+ else *Handle=0;
+
+ return Status;
+}
+
+EFI_STATUS HiiNewPackOld (IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACK_LIST *Package,
+ OUT EFI_HII_HANDLE *Handle)
+{
+ EFI_STATUS Status=0;
+ UINTN c=0,hid;
+ HII_HANDLE *phnd=NULL;
+//----------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ //Check if we have this GUID ib GuidDb already
+ //For Font and Keyboadr Data HAndle is allways = 0
+ if(Package->FontPack) Status=NewFontPack(Package->FontPack);
+ if(EFI_ERROR(Status)) return Status;
+
+ if(Package->StringPack){
+ phnd=LocateHandleGuid(Package->GuidId,&hid);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this is wrong !!!
+ //here we are trying to check if somebody using passed GuidId registered Ifr with us
+ //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different
+ //Ifr instances. To maintain compatibility I'll try to patch code...
+ if(!phnd || phnd->HasStr){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// if(!phnd){
+ Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Package->GuidId,&hid);
+ if(Status) return Status;
+ else c++;
+ phnd=gHiiDb.HandleDb.Items[hid];
+ }
+
+ //if(phnd->HasStr) return EFI_INVALID_PARAMETER;
+ Status=NewStringPack(Package->StringPack, hid);
+ if(EFI_ERROR(Status)) return Status;
+ }
+
+ if(Package->IfrPack){
+ phnd=LocateHandleGuid(Package->GuidId,&hid);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this is wrong !!!
+ //here we are trying to check if somebody using passed GuidId registered Ifr with us
+ //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different
+ //Ifr instances. To maintain compatibility I'll try to patch code...
+ if(!phnd || phnd->Ifr){
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// if(!phnd){
+ Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Package->GuidId,&hid);
+ if(Status) return Status;
+ else c++;
+ phnd=gHiiDb.HandleDb.Items[hid];
+ }
+
+ //if(phnd->HasIfr) return EFI_INVALID_PARAMETER;
+ Status=NewIfrPack(Package->IfrPack, hid);
+ if(EFI_ERROR(Status)) return Status;
+ }
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//nothing is done for keyboard layout functions
+//this is empty spot in spec!
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ if(c)gHiiDb.NextHiiHandle++;
+
+ if(phnd)*Handle=phnd->Handle;
+ else *Handle=0;
+
+ return Status;
+}
+
+///////////////////////////////////////////////////////////////////
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+//this function even not in spec yet so UNSUPPORT it!!!
+// here is an explanation I've got from Initial's Source
+// "This function allows to extract the NV Image
+// that represents the default storage image"
+//Still Unclear what to do with it
+EFI_STATUS HiiGetDefaultImageOld(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ IN OUT UINT16 *BufferLength,
+ IN OUT UINT8 *Buffer)
+{
+ HII_HANDLE *phnd;
+ HII_FORMSET *fs;
+ EFI_IFR_OP_HEADER *op;
+ UINTN hi,fsi,i,t=0,cv=0;
+ UINT8 *fsb;//formset buffer
+ BOOLEAN ol=FALSE;
+ EFI_STATUS Status;
+//---------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ phnd=LocateHandle(Handle,&hi);
+ if(!phnd || !phnd->Ifr) return EFI_INVALID_PARAMETER;
+
+ fs=LocateFormSet(hi,&fsi);
+ if(!fs) return EFI_INVALID_PARAMETER;
+
+ if(*BufferLength<fs->FormSetData->NvDataSize){
+ *BufferLength=fs->FormSetData->NvDataSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *BufferLength=fs->FormSetData->NvDataSize;
+ i=*BufferLength;
+
+ if (DefaultMask & EFI_IFR_FLAG_DEFAULT)
+ Status=pRS->GetVariable(L"SetupDefaultOverride",&phnd->Guid,NULL,&i,Buffer);
+ else {
+ if (DefaultMask & EFI_IFR_FLAG_MANUFACTURING)
+ Status=pRS->GetVariable(L"SetupManufacturingOverride",&phnd->Guid,NULL,&i,Buffer);
+ else {
+ DefaultMask = DefaultMask | EFI_IFR_FLAG_DEFAULT;
+ Status=pRS->GetVariable(L"Setup",&phnd->Guid,NULL,&i,Buffer);
+ }
+ }
+
+ fsb=Malloc(fs->BufferLength);
+ if(!fsb) return EFI_OUT_OF_RESOURCES;
+ CopyFormSet(fsb,fs,&i);
+
+ op=(EFI_IFR_OP_HEADER*)fsb;
+ while(op->OpCode!=EFI_IFR_END_FORM_SET_OP){
+ switch(op->OpCode){
+ case EFI_IFR_ORDERED_LIST_OP:
+ ol=TRUE;
+ i=((EFI_IFR_ONE_OF*)op)->QuestionId;
+ t=((EFI_IFR_ONE_OF*)op)->Width;
+ break;
+ case EFI_IFR_ONE_OF_OP:
+ ol=FALSE;
+ i=((EFI_IFR_ONE_OF*)op)->QuestionId;
+ t=((EFI_IFR_ONE_OF*)op)->Width;
+ break;
+ case EFI_IFR_ONE_OF_OPTION_OP:{
+ EFI_IFR_ONE_OF_OPTION *ifro=(EFI_IFR_ONE_OF_OPTION*)op;
+ //-----------------
+ if(!cv){
+ if(ol){
+ //pBS->CopyMem(&Buffer[i],&((EFI_IFR_ONE_OF_OPTION*)op)->Value, 1);
+ pBS->CopyMem(&Buffer[i],&ifro->Value, 1);
+ i++;
+ } else {
+ //if (((EFI_IFR_ONE_OF_OPTION*)op)->Flags & DefaultMask)
+ // pBS->CopyMem(&Buffer[i],&((EFI_IFR_ONE_OF_OPTION*)op)->Value,t);
+ if (ifro->Flags & DefaultMask)
+ pBS->CopyMem(&Buffer[i],&ifro->Value,t);
+ }
+ }
+ } break;
+ case EFI_IFR_END_OP:
+ t=0;
+ break;
+ case EFI_IFR_CHECKBOX_OP:{
+ EFI_IFR_CHECK_BOX *ifrc=(EFI_IFR_CHECK_BOX*)op;
+ //--------------------
+ if(!cv){
+ //if(((EFI_IFR_CHECK_BOX*)op)->Flags & DefaultMask)
+ // Buffer[((EFI_IFR_CHECK_BOX*)op)->QuestionId] = 1;
+ //else
+ // Buffer[((EFI_IFR_CHECK_BOX*)op)->QuestionId] = 0;
+ if(ifrc->Flags & DefaultMask)
+ Buffer[ifrc->QuestionId] = 1;
+ else
+ Buffer[ifrc->QuestionId] = 0;
+ }
+ } break;
+ case EFI_IFR_NUMERIC_OP:{
+ EFI_IFR_NUMERIC *ifrn=(EFI_IFR_NUMERIC*)op;
+ //--------------------------
+ //if (!cv)pBS->CopyMem(&Buffer[((EFI_IFR_NUMERIC*)op)->QuestionId],
+ // &((EFI_IFR_NUMERIC*)op)->Default,((EFI_IFR_NUMERIC*)op)->Width);
+ if (!cv){
+ pBS->CopyMem(&Buffer[ifrn->QuestionId], &ifrn->Default,ifrn->Width);
+ }
+ } break;
+
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
+ cv=((EFI_IFR_VARSTORE_SELECT*)op)->VarId;
+ break;
+ }
+ op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length);
+ }
+ pBS->FreePool(fsb);
+ return EFI_SUCCESS;
+}
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiFindHandles(IN EFI_HII_PROTOCOL *This,
+ //spec not says in what units assume, for now, it is in EFI_HII_HANDLE
+ IN OUT UINT16 *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle)
+{
+ UINTN i;
+ HII_HANDLE *hnd;
+//-------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ if(*HandleBufferLength<gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE)){
+ *HandleBufferLength = (UINT16)gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *HandleBufferLength = (UINT16)gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE);
+ for (i=0; i<gHiiDb.HandleDb.ItemCount; i++){
+ hnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i];
+ Handle[i]=hnd->Handle;
+ }
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+// Will remove all stuff associated with form set on particular handle
+// including all Update Data and Free all memory used to store private data
+// This function assumes "HandleIdx" is valid.
+VOID RemoveFormSet(UINTN HandleIdx){
+ HII_FORMSET *fst;
+ HII_FORM *frm;
+ HII_LABEL *lbl;
+ UINTN i,j,fsi;
+//--------------------------------
+ while(TRUE) { //it might be more then one formset with the same Handle
+ fst=LocateFormSet(HandleIdx, &fsi);
+ if(!fst) return; //Not a single form set was registred with this Handle
+
+ for(i=0;i<fst->Forms.ItemCount;i++){
+ frm=(HII_FORM*)fst->Forms.Items[i];
+ for(j=0;j<frm->Labels.ItemCount;j++){
+ lbl=frm->Labels.Items[j];
+ DeleteLabelObjects(lbl);
+ if(lbl->LabelData && lbl->Updated) pBS->FreePool(lbl->LabelData);
+ }
+ ClearItemLst(&frm->Labels,TRUE);
+ }
+ ClearItemLst(&fst->Labels,FALSE);
+ ClearItemLst(&fst->Forms,TRUE);
+ DeleteItemLst(&gHiiDb.IfrDb,fsi,TRUE);
+ }
+}
+
+///////////////////////////////////////////////////////////////////
+// Will remove all String records associated with "HandleIdx" for
+// all languages. This function assumes "HandleIdx" is valid.
+VOID RemoveStrings(UINTN HandleIdx){
+ HII_HANDLE *hnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleIdx];
+ HII_STR *str;
+ INTN i;
+//-----------------------
+ for(i=0; (UINTN)i<gHiiDb.StringDb.RecordCount; i++){
+ DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str);
+ if(str->Handle==hnd->Handle){
+ if(str->String.StrPtr)pBS->FreePool(str->String.StrPtr);
+ if(str->NewStr.StrPtr)pBS->FreePool(str->NewStr.StrPtr);
+ DbeDelete(&gHiiDb.StringDb,str,TRUE);
+ i--;
+ continue;
+ }
+ if(str->Handle>hnd->Handle) break;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiRemovePack(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle)
+
+{
+ UINTN hid;
+ HII_HANDLE *phnd;
+ HII_FORMSET *fs;
+ UINTN i;
+//--------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ //Here we will try to remove Pack from DB
+ phnd=LocateHandle(Handle,&hid);
+ if(!phnd) return EFI_INVALID_PARAMETER;
+
+ //So we found requested Handle, now remove all stuff associated with it.
+ //Remove IFRs
+ if(phnd->Ifr){
+ RemoveFormSet(hid);
+ pBS->FreePool(phnd->Ifr);
+ }
+ //Remove Strings
+ if(phnd->HasStr)RemoveStrings(hid);
+
+ //Free Items[] buffer if it was allocated
+ //if no Secondary Languages installed for this HII_HANDLE nothing has to be done
+ if(phnd->SecLang.ItemCount)ClearItemLst(&phnd->SecLang,FALSE);
+
+ //reindexing remaining formsets to take care of
+ //removed HII_HANDLE record from HiiDB.HandleDb[]
+ for(i=0; i<gHiiDb.IfrDb.ItemCount; i++) {
+ fs=gHiiDb.IfrDb.Items[i];
+ if(fs->HandleId>hid) fs->HandleId--;
+ }
+
+ DeleteItemLst(&gHiiDb.HandleDb, hid, TRUE);
+
+ //The current saved handle might be pointing on the one been removed.
+ //so reset them to initial values.
+ mCurHnd=NULL;
+ mCurLang=NULL;
+ mCurHid=0;
+ mCurLid=0;
+ mCurStr=NULL;
+
+ return EFI_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////
+//HelperFunction to calculate size needed to dump the database
+//excluding EFI_HII_DATA_TABLE header
+UINTN GetHandleExpBuffSize(HII_HANDLE *HiiHandle, UINTN HndIndex){
+ UINTN sz=0, i, li=(UINTN)-1;
+ HII_FORMSET *fs=NULL;
+ HII_STR *str=NULL;
+ HII_STORE *st=NULL;
+//-------------------------------------
+
+ //This is an order of data structures as provided in Intel's implementation
+ //DevPath Data stuff Dummy so far just reserve space for DP_PACK and END_OF_DP
+ sz+=sizeof(EFI_HII_DEVICE_PATH_PACK)+sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+ //Find Formset we are working with
+ fs=LocateFormSet(HndIndex, NULL);
+
+ if(!fs) sz+= sizeof(gDummyVfr); //no formset no VAR data just Dummy Formset
+ else {
+ //Variable data
+ for(i=0; i<fs->Storages.ItemCount; i++){
+ //--------------------
+ st=fs->Storages.Items[i];
+ if(st->VarStore->Size){
+ UINT8 *p;
+ UINTN ind = 0, vsize = 0;
+ UINT16 VarName[256] = {0};
+ //---------------------
+ sz+=sizeof(EFI_HII_VARIABLE_PACK);
+ //sz+=st->VarStore->Size;
+ p=(UINT8*)(st->VarStore+1);
+ while(*p){
+ p++;
+ vsize+=sizeof(UINT16);
+ }
+ vsize+=sizeof(UINT16);//NULL terminator
+ sz+=vsize;
+
+ p=(UINT8*)(st->VarStore+1);
+ while(*p && ind < sizeof(VarName)){
+ VarName[ind] = (CHAR16)*p;
+ p++; ind++;
+ }
+ vsize=0;
+ pRS->GetVariable(VarName,&st->VarStore->Guid,NULL,&vsize,NULL);
+ if(vsize)
+ sz+=vsize;
+ else
+ sz += st->VarStore->Size;
+ }
+ }
+ if(fs->Storages.ItemCount > 0)
+ sz+=sizeof(EFI_HII_VARIABLE_PACK); // !! added dummy VARIABLE PACK
+
+ //formset data size
+ sz+=fs->BufferLength+sizeof(EFI_HII_PACK_HEADER);// !! changed to +=
+ }
+
+ //string data size
+ if(HiiHandle->HasStr){
+ for(i=0; i<gHiiDb.StringDb.RecordCount; i++){
+ DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str);
+ if(str->Handle==HiiHandle->Handle){
+ if((li==-1)||(li!=str->LangIdx)){
+ li=str->LangIdx;
+ sz+=sizeof(EFI_HII_STRING_PACK); //new pack for new language
+ }
+ //the StrLen stored in UNICODECHAR units
+ if(str->NewStr.StrPtr)sz+=str->NewStr.StrLen*sizeof(CHAR16)+sizeof(RELOFST);
+ else sz+=str->String.StrLen*sizeof(CHAR16)+sizeof(RELOFST);
+ }
+ if((str->Handle>HiiHandle->Handle)||(i==gHiiDb.StringDb.RecordCount-1)){
+ sz+=sizeof(EFI_HII_STRING_PACK);//terminator pack
+ break;
+ }
+ }
+ }
+ return sz;
+}
+
+
+UINT32 CountStrOfLang(HII_HANDLE *HiiHandle, UINTN StartIdx, UINTN LangIdx ){
+ UINTN i;
+ UINT32 cnt=0;
+ HII_STR *str;
+//----------------------
+ for (i=StartIdx; i<gHiiDb.StringDb.RecordCount;i++){
+ DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,i,&str);
+ if(str->Handle==HiiHandle->Handle){
+ if(str->LangIdx==LangIdx)cnt++;
+ else break;
+ } else break;
+ }
+ return cnt;
+}
+
+
+VOID ExportHandleData(IN HII_HANDLE *HiiHandle, IN UINTN HndIndex,
+ IN EFI_HII_DATA_TABLE *DataTbl, IN OUT UINT8 **BufferPointer)
+{
+ UINTN sz=0, i;
+ HII_FORMSET *fs;
+ HII_STR *str;
+ HII_STORE *st;
+ UINT8 *p1=*BufferPointer, *p2;
+ EFI_STATUS Status;
+//-------------------------------------
+
+ //This is an order of data structures as provided in Intel's implementation
+ //DevPath Data stuff Dummy so far END_OF_DP
+ DataTbl->DevicePathOffset=(UINT32)(p1-(UINT8*)DataTbl);
+
+ ((EFI_HII_DEVICE_PATH_PACK*)p1)->Header.Type=EFI_HII_DEVICE_PATH;
+
+ //points to the space after EFI_HII_DEVICE_PATH_PACK structure
+ p2=(p1+sizeof(EFI_HII_DEVICE_PATH_PACK));
+
+ ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Type=0xFF;
+ ((EFI_DEVICE_PATH_PROTOCOL*)p2)->SubType=0xFF;
+// ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length=0;
+ ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length[0]=0;
+ ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length[1]=0;
+ ((EFI_HII_DEVICE_PATH_PACK*)p1)->Header.Length=(UINT32)(p2-p1+sizeof(EFI_DEVICE_PATH_PROTOCOL));
+
+ p1=p2+sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+ //Find Formset we are working with
+ fs=LocateFormSet(HndIndex, NULL);
+ if(!fs) {
+ //No formset no VAR data
+ DataTbl->VariableDataOffset=0;
+
+ //Copy a Dummy formset to be compatible with Intel
+ DataTbl->IfrDataOffset=(UINT32)(p1-(UINT8*)DataTbl);
+
+ pBS->CopyMem(p1,&gDummyVfr[0],sizeof(gDummyVfr));
+ //copy handle guid here Shell expect it to mutch with some standart guids
+ pBS->CopyMem((VOID*)(p1+8),(VOID*)&HiiHandle->Guid,sizeof(EFI_GUID));
+ //Adjust the pointer
+ p1+=sizeof(gDummyVfr);
+ } else {
+ //Variable data
+ DataTbl->VariableDataOffset=(UINT32)(p1-(UINT8*)DataTbl);
+ for(i=0; i<fs->Storages.ItemCount; i++){
+ //--------------------
+ st=fs->Storages.Items[i];
+ if(st->VarStore->Size){
+ UINT8 *p;
+ //---------------------
+ p2=p1+sizeof(EFI_HII_VARIABLE_PACK);
+ ((EFI_HII_VARIABLE_PACK*)p1)->Header.Type=EFI_HII_VARIABLE;
+ //pBS->CopyMem((VOID*)&(((EFI_HII_VARIABLE_PACK*)p1)->VariableGuid),
+ // &st->VarStore.Guid, sizeof(EFI_GUID));
+
+ ((EFI_HII_VARIABLE_PACK*)p1)->VariableGuid=st->VarStore->Guid;
+ ((EFI_HII_VARIABLE_PACK*)p1)->VariableId=st->VarStore->VarId;
+
+ p=(UINT8*)(st->VarStore+1);
+ while(*p){
+ *p2=*p;
+ p++;
+ p2+=sizeof(UINT16);
+ //per spec VariableLength goes in Bytes
+ ((EFI_HII_VARIABLE_PACK*)p1)->VariableNameLength+=sizeof(UINT16);
+ }
+ p2+=sizeof(UINT16); //Null terminaterd
+ ((EFI_HII_VARIABLE_PACK*)p1)->VariableNameLength+=sizeof(UINT16);
+ //Copy contents of the variable at present p2
+ p=p1+sizeof(EFI_HII_VARIABLE_PACK);
+ sz=st->VarStore->Size;
+ Status=pRS->GetVariable((UINT16*)p,&st->VarStore->Guid,NULL,&sz,p2);
+
+ DataTbl->NumberOfVariableData++;
+ //don't forget to update size of Var Data in Pack Header
+ ((EFI_HII_VARIABLE_PACK*)p1)->Header.Length=(UINT32)(p2+sz-p1);
+
+ p1=p2+sz;
+ }
+ }
+ if(!DataTbl->NumberOfVariableData)DataTbl->VariableDataOffset=0;
+ else { // !! Add zero-terminating EFI HII variable
+ ((EFI_HII_VARIABLE_PACK*)p1)->Header.Type=EFI_HII_VARIABLE;
+ ((EFI_HII_VARIABLE_PACK*)p1)->Header.Length = sizeof(EFI_HII_VARIABLE_PACK);
+ p1 += sizeof(EFI_HII_VARIABLE_PACK);
+ }
+ //Formset goes data here
+ DataTbl->IfrDataOffset=(UINT32)(p1-(UINT8*)DataTbl);
+ p2=p1+sizeof(EFI_HII_PACK_HEADER);
+ ((EFI_HII_PACK_HEADER*)p1)->Length=(UINT32)fs->BufferLength+sizeof(EFI_HII_PACK_HEADER);
+ ((EFI_HII_PACK_HEADER*)p1)->Type=EFI_HII_IFR;
+
+ i=0;
+ CopyFormSet(p2,fs,&i);
+ p1=p2+i;
+ }
+ //If HIIHandle Data don't have Strings make p2==p1 since we are returning p2 value
+ p2=p1;
+ //string data goes here
+ if(HiiHandle->HasStr){
+ UINT8 *p=p1;
+ UINT32 li=(UINTN)-1;
+ //-----------------
+ DataTbl->StringDataOffset=(UINT32)(p1-(UINT8*)DataTbl);
+ for(i=0; i<gHiiDb.StringDb.RecordCount; i++){
+ DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str);
+ if(str->Handle==HiiHandle->Handle){
+
+ if((li==-1)||(li!=str->LangIdx)){
+ //p1 points on the EFI_HII_STRING_PACK
+ p1=p;
+ ((EFI_HII_STRING_PACK*)p1)->Header.Type=EFI_HII_STRING;
+ DataTbl->NumberOfLanguages++;
+ //p2 points on the RELOFS array
+ p2=p1+sizeof(EFI_HII_STRING_PACK);
+
+ li=str->LangIdx;
+
+ ((EFI_HII_STRING_PACK*)p1)->NumStringPointers=CountStrOfLang(HiiHandle,i,li);
+ //p points on the UnicodeString;
+ p=p2+((EFI_HII_STRING_PACK*)p1)->NumStringPointers*sizeof(UINT32);
+ ((EFI_HII_STRING_PACK*)p1)->LanguageNameString=(UINT32)((UINTN)p-(UINTN)p1);
+ ((EFI_HII_STRING_PACK*)p1)->PrintableLanguageName=((EFI_HII_STRING_PACK*)p1)->LanguageNameString
+ +4*sizeof(CHAR16);
+ ((EFI_HII_STRING_PACK*)p1)->Header.Length=sizeof(EFI_HII_STRING_PACK)+
+ ((EFI_HII_STRING_PACK*)p1)->NumStringPointers*sizeof(UINT32);
+
+ }
+ //update offset table
+ *((UINT32*)p2)=(UINT32)((UINTN)p-(UINTN)p1);
+ //the StrLen stored in UNICODECHAR units including NULL CHAR16
+ if(str->NewStr.StrPtr){
+ pBS->CopyMem(p, str->NewStr.StrPtr, str->NewStr.StrLen*sizeof(CHAR16));
+ p+=str->NewStr.StrLen*sizeof(CHAR16);
+ ((EFI_HII_STRING_PACK*)p1)->Header.Length+=str->NewStr.StrLen*sizeof(CHAR16);
+ } else {
+ pBS->CopyMem(p, str->String.StrPtr, str->String.StrLen*sizeof(CHAR16));
+ p+=str->String.StrLen*sizeof(CHAR16);
+ ((EFI_HII_STRING_PACK*)p1)->Header.Length+=str->String.StrLen*sizeof(CHAR16);
+ }
+ p2+=sizeof(UINT32);
+ }
+ //don't forget to put terminator pack at the very end of the string data
+ if((str->Handle > HiiHandle->Handle) || (i==gHiiDb.StringDb.RecordCount-1)){
+ //Create a terminator pack
+ p1=p;
+ ((EFI_HII_STRING_PACK*)p1)->Header.Type=EFI_HII_STRING;
+ p2=p1+sizeof(EFI_HII_STRING_PACK);
+ break;
+ }
+ }
+ }
+
+ *BufferPointer=p2;
+
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+EFI_STATUS HiiExport(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer )
+{
+ UINTN sz, i;
+ HII_HANDLE *phnd=NULL;
+ EFI_HII_EXPORT_TABLE *expt=NULL;
+ EFI_HII_DATA_TABLE *cdt=NULL;
+ UINT8 *bp=NULL;
+//----------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ sz=sizeof(EFI_HII_EXPORT_TABLE);
+
+ //Calculate buffer Size
+ for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){
+ phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i];
+ if(Handle && Handle!=phnd->Handle) continue;
+ sz+=GetHandleExpBuffSize(phnd,i) + sizeof(EFI_HII_DATA_TABLE);
+ }
+ //Check the buffer size provided
+ if(sz > *BufferSize){
+ *BufferSize=sz;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ pBS->SetMem(Buffer, sz, 0);
+ //Export Table
+ expt=(EFI_HII_EXPORT_TABLE*)Buffer;
+ if((UINTN)This == (UINTN)&gHiiDb.HiiProtocolOld) expt->Revision=gEfiHiiProtocolGuidOld;
+ else expt->Revision=gEfiHiiProtocolGuidNew;
+
+ bp=(UINT8*)(expt+1);
+
+ //Start dumping the data
+ for(i=0 ; i<gHiiDb.HandleDb.ItemCount; i++){
+
+ phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i];
+ if(Handle && Handle!=phnd->Handle) continue;
+ //CurrentDataTable
+ cdt=(EFI_HII_DATA_TABLE*)bp;
+ bp+=sizeof(EFI_HII_DATA_TABLE);
+
+ sz=GetHandleExpBuffSize(phnd,i);
+
+ cdt->HiiHandle=phnd->Handle;
+ cdt->PackageGuid=phnd->Guid;
+ cdt->DataTableSize=(UINT32)(sz+sizeof(EFI_HII_DATA_TABLE));
+
+ ExportHandleData(phnd, i, cdt, &bp);
+//debug+ just to test how bp gets incremented
+ ASSERT((UINTN)cdt+sizeof(EFI_HII_DATA_TABLE)+sz==(UINTN)bp);
+//debug-
+ expt->NumberOfHiiDataTables++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GetVarStoreData(HII_FORMSET *FormSet, HII_STORE *VarData, UINT8* Buffer, UINTN DefaultMask){
+ HII_LABEL *lbl;
+ HII_OBJECT *obj;
+ HII_FORM *frm;
+ EFI_IFR_OP_HEADER *op;
+ UINTN i,x,j,k,offs,len;
+//------------------
+
+ for(i=0; i<FormSet->Forms.ItemCount; i++){
+ frm=FormSet->Forms.Items[i];
+ for(x=0; x< frm->Labels.ItemCount; x++){
+ //iterate trough the Labels to get each HII_OBJECT
+ lbl=frm->Labels.Items[x];
+ for(j=0; j<lbl->Objects.ItemCount; j++){
+ //iterate trough the Objects to see if
+ obj=lbl->Objects.Items[j];
+
+ if( VarData->VarStore->VarId!=obj->Store1->VarStore->VarId ||
+ MemCmp(&VarData->VarStore->Guid, &obj->Store1->VarStore->Guid, sizeof(EFI_GUID))
+ ) continue;
+
+ //we focused at the Object which has the same VarStore Properies as passed "VarData"
+ //So parse the object to see if it has any default flags set
+ op=obj->ObjectCode;
+ switch(op->OpCode){
+
+ //ONE_OF and ORDERED_LIST has almost the same encoding
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ {
+ EFI_IFR_ONE_OF_OPTION *opt;
+ //-----------------------
+ offs=((EFI_IFR_ONE_OF*)op)->QuestionId;
+ len=((EFI_IFR_ONE_OF*)op)->Width;
+
+//DEBUG CODE to check if update runs out of bound
+ if(offs>=VarData->VarStore->Size) {
+ ASSERT_EFI_ERROR(EFI_BUFFER_TOO_SMALL);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+//DEBUG CODE to check if update runs out of bound
+
+ for(k=0; k<obj->Options.ItemCount; k++){
+ opt=(EFI_IFR_ONE_OF_OPTION*)obj->Options.Items[k];
+ //for ORDERED_LIST it would not be any Defaults
+ if(op->OpCode==EFI_IFR_ORDERED_LIST_OP){
+ pBS->CopyMem(&Buffer[offs],&opt->Value, 1);
+ offs++;
+
+//DEBUG CODE to check if update runs out of bound
+ if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL;
+//DEBUG CODE to check if update runs out of bound
+
+ } else {
+ UINTN f=(UINTN)opt->Flags;
+ //------------------
+ if (f & DefaultMask) {
+ pBS->CopyMem(&Buffer[offs],&opt->Value,len);
+ break;
+ }
+ }
+ }
+ }break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ {
+ EFI_IFR_CHECK_BOX *cb=(EFI_IFR_CHECK_BOX*)obj->ObjectCode;
+ UINTN f=(UINTN)cb->Flags;
+ //--------------------
+ offs=cb->QuestionId;
+
+//DEBUG CODE to check if update runs out of bound
+ if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL;
+//DEBUG CODE to check if update runs out of bound
+
+ if(f & DefaultMask) Buffer[offs] = 1;
+ else Buffer[offs] = 0;
+
+ } break;
+
+ case EFI_IFR_NUMERIC_OP:
+ {
+ EFI_IFR_NUMERIC *num =(EFI_IFR_NUMERIC*)obj->ObjectCode;
+ //--------------------------
+ offs=num->QuestionId;
+ len=num->Width;
+
+//DEBUG CODE to check if update runs out of bound
+ if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL;
+//DEBUG CODE to check if update runs out of bound
+
+ pBS->CopyMem(&Buffer[offs],&num->Default,len);
+ } break;
+
+ } //switch(obj->ObjectCode->Opcode)
+
+ } //for(j) loop
+ }//for(x) loop
+ } //for(i) loop
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS HiiGetDefaultImageNew(IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList)
+{
+ EFI_STATUS Status=EFI_NOT_FOUND;
+ UINTN i, j, k, hidx, vnl=0, tbsz=0;
+ HII_HANDLE *phnd;
+ EFI_HII_VARIABLE_PACK_LIST *vpl, *fvpl=NULL, *pvpl=NULL;
+ HII_FORMSET *fs;
+ HII_STORE *st;
+ UINT8 *pdb, *pnb;
+//----------------------------------
+
+ //Check Parameters
+ if(This==NULL || VariablePackList==NULL || !Handle ) return EFI_INVALID_PARAMETER;
+
+ //Find the handle
+ phnd=LocateHandle(Handle, &hidx);
+ if(phnd==NULL) return EFI_NOT_FOUND;
+
+ //If no VarStores associated with passed Handle will return NULL
+ *VariablePackList=NULL;
+
+ //If Handle Exists then find a FormSet associated with this Handle
+ fs=LocateFormSet(hidx, NULL);
+ //No formset found => no IFR data
+ if(fs==NULL) return EFI_NOT_FOUND;
+
+ //Collect the Variable data
+ for(i=0, hidx=0; i<fs->Storages.ItemCount; i++){
+ st=fs->Storages.Items[i];
+ if(!st->VarStore->Size) continue;
+
+ Status=EFI_SUCCESS;
+ hidx++;
+ //get the variable name length in bytes(ASCII)
+ vnl=st->VarStore->Header.Length-sizeof(EFI_IFR_VARSTORE);
+ //determine how much memory we need to accomodate
+ //EFI_VARIABLE_PACK_LIST + EFI_VARIABLE_PACK + VarName + VarData
+ vpl=MallocZ(sizeof(EFI_HII_VARIABLE_PACK_LIST)+ //EFI_VARIABLE_PACK_LIST
+ sizeof(EFI_HII_VARIABLE_PACK)+ //EFI_VARIABLE_PACK
+ (vnl*sizeof(UINT16))+ //EFI_VARIABLE_PACK has VarName in UINT16
+ st->VarStore->Size); //Size of actual NV Var Data
+
+ tbsz+=(sizeof(EFI_HII_VARIABLE_PACK_LIST)+ //EFI_VARIABLE_PACK_LIST
+ sizeof(EFI_HII_VARIABLE_PACK)+ //EFI_VARIABLE_PACK
+ (vnl*sizeof(UINT16))+ //EFI_VARIABLE_PACK has VarName in UINT16
+ st->VarStore->Size); //Size of actual NV Var Data
+
+ if(!vpl) return EFI_OUT_OF_RESOURCES;
+
+ //determine where in VPL buffer Actual VAriable data suppose to start
+ pdb=(UINT8*)vpl+sizeof(EFI_HII_VARIABLE_PACK_LIST)+sizeof(EFI_HII_VARIABLE_PACK)+(vnl*sizeof(UINT16));
+
+ GetVarStoreData(fs,st,pdb,DefaultMask);
+
+ //if this is the first structure in the list remember it we must return it's address
+ if(fvpl==NULL)fvpl=vpl;
+ //if PreviouseVariablePackList ptr was initialized update pointer to next VPL with current VPL
+ if(pvpl!=NULL)pvpl->NextVariablePack=vpl;
+ //reinitialize PreviouseVariablePackList ptr with current VPL pointer
+ pvpl=vpl;
+
+ //Update context of the VariablePack pointer to the next data byte afer itself(per .92 spec)
+ vpl->VariablePack = (EFI_HII_VARIABLE_PACK*)(vpl+1);
+
+ //Now fill out fields of HII_VARIABLE_PACK structure
+ vpl->VariablePack->Header.Type=EFI_HII_VARIABLE;
+ vpl->VariablePack->Header.Length=(UINT32)(sizeof(EFI_HII_VARIABLE_PACK)+(vnl*sizeof(UINT16))+st->VarStore->Size);
+ vpl->VariablePack->VariableId=st->VarStore->VarId;
+ vpl->VariablePack->VariableNameLength=(UINT32)(vnl*sizeof(UINT16)); // per spec length in bytes.
+ pBS->CopyMem(&vpl->VariablePack->VariableGuid, &st->VarStore->Guid, sizeof(EFI_GUID));
+ //now copy Variable name "pdb" points at the befinning of VarName buffer
+ pdb=(UINT8*)vpl+sizeof(EFI_HII_VARIABLE_PACK_LIST)+sizeof(EFI_HII_VARIABLE_PACK);
+ pnb=(UINT8*)(st->VarStore+1);
+ //since in VARIABLE_PACKAGE VAR NAME is UNICODE simple MemCpy wouldn't do.
+ for(j=0,k=0; j<vnl; j++, k+=2) {
+ pdb[k]=pnb[j];
+ }
+ }
+
+ //Per Spec we have to dump all data in single buffer.
+ //Update the IN/OUT parameter
+ if(tbsz) {
+ *VariablePackList=Malloc(tbsz);
+ if(*VariablePackList==NULL) return EFI_OUT_OF_RESOURCES;
+ } else *VariablePackList=NULL;
+ vpl=fvpl;
+ pdb=(UINT8*)(*VariablePackList);
+ while (vpl){
+ //copy Var_PACK_LIST + VARPACK to the Common Buffer
+ pBS->CopyMem(pdb,vpl,sizeof(EFI_HII_VARIABLE_PACK_LIST)+vpl->VariablePack->Header.Length);
+ pvpl=(EFI_HII_VARIABLE_PACK_LIST*)pdb;
+ pvpl->VariablePack=(EFI_HII_VARIABLE_PACK*)(pdb+sizeof(EFI_HII_VARIABLE_PACK_LIST));
+
+ pdb+=(sizeof(EFI_HII_VARIABLE_PACK_LIST)+vpl->VariablePack->Header.Length);
+ if(vpl->NextVariablePack!=NULL)pvpl->NextVariablePack=(EFI_HII_VARIABLE_PACK_LIST*)pdb;
+
+ pvpl=vpl;
+ vpl=vpl->NextVariablePack;
+
+ pBS->FreePool(pvpl);
+ }
+
+ return Status;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//Keyboard
+EFI_STATUS HiiGetKeyboardLayout(IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT EFI_KEY_DESCRIPTOR *Descriptor)
+{
+ HII_KB_LAYOUT_DATA *kbld;
+//-------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ if(!gHiiDb.KeybdDb.KblCount) return EFI_NOT_FOUND;
+
+ kbld=gHiiDb.KeybdDb.KbLayout[gHiiDb.KeybdDb.ActiveLayout];
+
+ //we got small buffer
+ if(*DescriptorCount<kbld->KeyDscCount) {
+ *DescriptorCount=kbld->KeyDscCount;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ MemCpy((VOID*)Descriptor, (VOID*)kbld->KeyDsc, sizeof(EFI_KEY_DESCRIPTOR)*kbld->KeyDscCount);
+
+ return EFI_SUCCESS;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+//EXTENDED HII INTERFACE
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+EFI_STATUS HiiExtGetStringInfo(
+ IN EXT_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN CHAR16 *Lang,
+ OUT EXT_STR_INFO **ExtStrInfo)
+{
+ HII_STR *str;
+//-----------------------------------------
+ if(!This || !ExtStrInfo ) return EFI_INVALID_PARAMETER;
+
+ str=GetHiiString(Handle,Lang,Token);
+ if(!str) return EFI_NOT_FOUND;
+
+ if(str->NewStr.StrPtr)*ExtStrInfo=&str->NewStr;
+ else *ExtStrInfo=&str->String;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS HiiExtGetFormInfo(IN EXT_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ OUT HII_FORM **ExtFormInfo)
+{
+ HII_FORM *frm;
+ UINTN hi;
+ HII_HANDLE *phnd;
+ HII_FORMSET *fs;
+//-----------------------------------------
+ if(!This || !ExtFormInfo ) return EFI_INVALID_PARAMETER;
+
+ phnd=LocateHandle(Handle,&hi);
+ ASSERT(phnd);
+ if(!phnd)return EFI_NOT_FOUND;
+
+ fs=LocateFormSet(hi,NULL);
+ ASSERT(fs);
+ if(!fs)return EFI_NOT_FOUND;
+
+ frm=LocateForm(fs,FormId);
+ ASSERT(frm);
+ if(!frm)return EFI_NOT_FOUND;
+ *ExtFormInfo=frm;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS HiiExtRegisterLabelUpdateCallback(IN EXT_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL LabelId,
+ IN HII_LABEL_UPDATE_CALLBACK CallBack)
+{
+ UINTN hi;
+ HII_LABEL *lbl;
+ HII_FORMSET *fs;
+//----------------------------------
+ if(!This || !CallBack ) return EFI_INVALID_PARAMETER;
+
+ if(!LocateHandle(Handle, &hi)) return EFI_INVALID_PARAMETER;
+
+ //Find Formset
+ fs=LocateFormSet(hi, NULL);
+ if(!fs) return EFI_INVALID_PARAMETER;
+
+ lbl=LocateFormSetLabel(fs,LabelId,NULL);
+ if(!lbl) return EFI_NOT_FOUND;
+
+ lbl->UpdateCallBack=CallBack;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiExtUnregisterLabelUpdateCallback(IN EXT_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL LabelId)
+{
+ UINTN hi;
+ HII_LABEL *lbl;
+ HII_FORMSET *fs;
+//----------------------------------
+ if(!This) return EFI_INVALID_PARAMETER;
+
+ if(!LocateHandle(Handle, &hi)) return EFI_INVALID_PARAMETER;
+
+ //Find Formset
+ fs=LocateFormSet(hi, NULL);
+ if(!fs) return EFI_INVALID_PARAMETER;
+
+ lbl=LocateFormSetLabel(fs,LabelId,NULL);
+ if(!lbl) return EFI_NOT_FOUND;
+
+ lbl->UpdateCallBack=NULL;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiExtGetFormSetInfo(IN EXT_HII_PROTOCOL *This,
+ IN UINT16 ClassMask, //if ==0xFFFF all Classes
+ IN UINT16 SubClass, //if ==0xFFFF all SubClasses
+ OUT T_ITEM_LIST *FormSetList)
+{
+ UINTN i;
+ HII_FORMSET *fs;
+//------------------------------
+ if(!This || !FormSetList) return EFI_INVALID_PARAMETER;
+
+ //Make sure the list is empty
+ ClearItemLst(FormSetList,FALSE);
+ for(i=0; i<gHiiDb.IfrDb.ItemCount;i++){
+ fs=gHiiDb.IfrDb.Items[i];
+ if(SubClass!=0xFFFF && SubClass!=fs->FormSetData->SubClass) continue;
+ if((fs->FormSetData->Class & ClassMask)==fs->FormSetData->Class) AppendItemLst(FormSetList,fs);
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiExtGetFormLabels(IN EXT_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormID,
+ OUT T_ITEM_LIST *LabelList)
+{
+ UINTN i;
+ HII_FORMSET *fs;
+ HII_FORM *frm;
+ HII_LABEL *lbl;
+ EFI_STATUS Status;
+//-----------------------------------------
+ if(!This || !LabelList ) return EFI_INVALID_PARAMETER;
+
+ if(!LocateHandle(Handle,&i)) return EFI_INVALID_PARAMETER;;
+
+ fs=LocateFormSet(i,NULL);
+ ASSERT(fs);
+ if(!fs)return EFI_NOT_FOUND;
+
+ frm=LocateForm(fs,FormID);
+ ASSERT(frm);
+ if(!frm)return EFI_NOT_FOUND;
+
+ ClearItemLst(LabelList,FALSE);
+ for(i=1;i<frm->Labels.ItemCount;i++){
+ lbl=frm->Labels.Items[i];
+ Status=AppendItemLst(LabelList,lbl);
+ ASSERT(!EFI_ERROR(Status));
+ if(EFI_ERROR(Status))return Status;
+ }
+ return EFI_SUCCESS;
+}
+
+
+///////////////////////////////////////////////////////////////////
+//Init All Private Data
+EFI_STATUS InitPrivateData(EFI_HANDLE MyImgHandle){
+ EFI_STATUS Status=0;
+ //HII_LANG *al;//any lang
+//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST
+ EFI_HII_PACK_LIST *pl=Malloc(sizeof(EFI_HII_PACK_LIST));
+ // {BB2F3C9D-C7A1-4283-8AE2-4F4362990E2E}
+ static EFI_GUID pguid={ 0xbb2f3c9d, 0xc7a1, 0x4283, 0x8a, 0xe2, 0x4f, 0x43, 0x62, 0x99, 0x0e, 0x2e };
+ EFI_HII_HANDLE fph;//,sth;
+// UINT16 bl;
+// UINT8 *fsb;
+//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST
+//-----------------------------
+ pBS->SetMem(&gHiiDb, sizeof(HII_DB),0 );
+
+ gHiiDb.ImageHandle=MyImgHandle;
+ gHiiDb.NextHiiHandle=1; //Zero Handle is Invalid it must be 1 based
+
+ //Create Any Langguage Entry - empty string L" "
+ Status=LocateLangAdd(L" ",L"Any Language",NULL);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Create and Initialize String Database
+ gHiiDb.StringDb.KeyCount=STR_KEY_CNT;
+ gHiiDb.StringDb.InitialCount=STRING_DB_MAX_COUNT;
+ gHiiDb.StringDb.KeyField=&gStrKey;
+ gHiiDb.StringDb.MemoryType=EfiBootServicesData;
+ gHiiDb.StringDb.RecordCount=0;
+ gHiiDb.StringDb.IndexArray=MallocZ(sizeof(VOID*)*gHiiDb.StringDb.InitialCount*gHiiDb.StringDb.KeyCount);
+ if(!gHiiDb.StringDb.IndexArray) return EFI_OUT_OF_RESOURCES;
+
+ //Init Protocol Instance here
+ gHiiDb.HiiProtocolOld.NewPack=HiiNewPackOld;
+ gHiiDb.HiiProtocolNew.NewPack=HiiNewPackNew;
+
+ gHiiDb.HiiProtocolOld.RemovePack=HiiRemovePack;
+ gHiiDb.HiiProtocolNew.RemovePack=HiiRemovePack;
+
+ gHiiDb.HiiProtocolOld.FindHandles=HiiFindHandles;
+ gHiiDb.HiiProtocolNew.FindHandles=HiiFindHandles;
+
+ gHiiDb.HiiProtocolOld.GetDefaultImage=HiiGetDefaultImageOld;
+ gHiiDb.HiiProtocolNew.GetDefaultImage=HiiGetDefaultImageNew;
+
+ gHiiDb.HiiProtocolOld.TestString=HiiTestString;
+ gHiiDb.HiiProtocolNew.TestString=HiiTestString;
+
+ gHiiDb.HiiProtocolOld.GetGlyph=HiiGetGlyph;
+ gHiiDb.HiiProtocolNew.GetGlyph=HiiGetGlyph;
+
+ gHiiDb.HiiProtocolOld.GlyphToBlt=HiiGlyphToBlt;
+ gHiiDb.HiiProtocolNew.GlyphToBlt=HiiGlyphToBlt;
+
+ gHiiDb.HiiProtocolOld.NewString=HiiNewString;
+ gHiiDb.HiiProtocolNew.NewString=HiiNewString;
+
+ gHiiDb.HiiProtocolOld.GetPrimaryLanguages=HiiGetPrimaryLanguage;
+ gHiiDb.HiiProtocolNew.GetPrimaryLanguages=HiiGetPrimaryLanguage;
+
+ gHiiDb.HiiProtocolOld.GetSecondaryLanguages=HiiGetSecondaryLanguages;
+ gHiiDb.HiiProtocolNew.GetSecondaryLanguages=HiiGetSecondaryLanguages;
+
+ gHiiDb.HiiProtocolOld.GetString=HiiGetStringOld;
+ gHiiDb.HiiProtocolNew.GetString=HiiGetStringNew;
+
+ gHiiDb.HiiProtocolOld.GetLine=HiiGetLine;
+ gHiiDb.HiiProtocolNew.GetLine=HiiGetLine;
+
+ gHiiDb.HiiProtocolOld.GetForms=HiiGetFormsOld;
+ gHiiDb.HiiProtocolNew.GetForms=HiiGetFormsNew;
+
+ gHiiDb.HiiProtocolOld.UpdateForm=HiiUpdateForm;
+ gHiiDb.HiiProtocolNew.UpdateForm=HiiUpdateForm;
+
+ gHiiDb.HiiProtocolOld.GetKeyboardLayout=HiiGetKeyboardLayout;
+ gHiiDb.HiiProtocolNew.GetKeyboardLayout=HiiGetKeyboardLayout;
+
+ gHiiDb.HiiProtocolOld.ResetStrings=HiiResetStrings;
+ gHiiDb.HiiProtocolNew.ResetStrings=HiiResetStrings;
+
+ gHiiDb.HiiProtocolOld.ExportDatabase=HiiExport;
+ gHiiDb.HiiProtocolNew.ExportDatabase=HiiExport;
+
+ //Now do Extended Hii Interface
+ gHiiDb.HiiExtProtocol.ExtGetStringInfo=HiiExtGetStringInfo;
+ gHiiDb.HiiExtProtocol.ExtGetFormInfo=HiiExtGetFormInfo;
+ gHiiDb.HiiExtProtocol.ExtGetFormsetInfo=HiiExtGetFormSetInfo;
+ gHiiDb.HiiExtProtocol.ExtRegLblCallBack=HiiExtRegisterLabelUpdateCallback;
+ gHiiDb.HiiExtProtocol.ExtUnregLblCallBack=HiiExtUnregisterLabelUpdateCallback;
+ gHiiDb.HiiExtProtocol.ExtGetFormLabels=HiiExtGetFormLabels;
+
+ //------------------------------------
+ //init Font Data
+ pl->FontPack=(EFI_HII_FONT_PACK*)&UsStdNarrowGlyphData;
+ pl->GuidId=&pguid;
+ pl->IfrPack=NULL;//(EFI_HII_IFR_PACK*)&FrontPageVfrBin;
+ pl->KeyboardPack=NULL;
+ pl->StringPack=NULL;//(EFI_HII_STRING_PACK*)&FrontPageStrings;
+///// Load Font Pack
+{
+#define FONT_FFS_FILE_GUID { 0xdac2b117, 0xb5fb, 0x4964, { 0xa3, 0x12, 0xd, 0xcc, 0x77, 0x6, 0x1b, 0x9b } }
+static EFI_GUID guidFontFile = FONT_FFS_FILE_GUID;
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *pFV;
+ UINTN DataSize;
+ EFI_GUID *pSectionGuid = NULL;
+ UINT32 Authentication;
+ EFI_HANDLE *pHandle;
+ UINTN Number,i;
+ Status = pBS->LocateHandleBuffer(ByProtocol,&guidFV, NULL, &Number, &pHandle);
+ for(i=0;i<Number; i++)
+ {
+ Status=pBS->HandleProtocol(pHandle[i], &guidFV, &pFV);
+ if (EFI_ERROR(Status)) continue;
+ pSectionGuid=NULL;
+ DataSize=0;
+ Status=pFV->ReadSection (
+ pFV,&guidFontFile,
+ EFI_SECTION_FREEFORM_SUBTYPE_GUID,0, &pSectionGuid, &DataSize,
+ &Authentication
+ );
+ if (!EFI_ERROR(Status))
+ {
+ pl->FontPack=(EFI_HII_FONT_PACK*)((UINT32*)(pSectionGuid+1)+1);
+ break;
+ }
+ }
+ Status=HiiNewPackOld((EFI_HII_PROTOCOL*)&gHiiDb.HiiProtocolOld,pl,&fph);
+ pBS->FreePool(pSectionGuid);
+}
+////////////////////
+ if(EFI_ERROR(Status)) return Status;
+
+//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST
+/* pl->FontPack=NULL;
+ pl->IfrPack=NULL;
+ pl->KeyboardPack=NULL;
+ pl->StringPack=(EFI_HII_STRING_PACK*)&SetupStrings;
+
+ Status=HiiNewPack(&gHiiDb.HiiProtocol,pl,&sth);
+ if(EFI_ERROR(Status)) return Status;
+
+ fsb=NULL;
+ bl=0;
+ Status=HiiGetForms(&gHiiDb.HiiProtocol,fph,0,&bl,fsb);
+ if(Status==EFI_BUFFER_TOO_SMALL);
+ else if(EFI_ERROR(Status)) return Status;
+ fsb=Malloc(bl);
+ if(!fsb) return EFI_OUT_OF_RESOURCES;
+ Status=HiiGetForms(&gHiiDb.HiiProtocol,fph,0,&bl,fsb);
+
+ //Now, I'll try to ges some strings from FrontPageDb
+ {
+ UINT16 mystr[81];
+ EFI_STRING plan, slan;
+ EFI_IFR_FORM_SET *fs=(EFI_IFR_FORM_SET*)fsb;
+ UINT32 gb,i=0;
+ //-----------------------------------
+
+ Status=HiiGetPrimaryLanguage(&gHiiDb.HiiProtocol,fph,&plan);
+ //it might be more than 1 Sec Lang.
+ Status=HiiGetSecondaryLanguages(&gHiiDb.HiiProtocol,fph,plan,&slan);
+
+
+ bl=80;
+
+ Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->FormSetTitle,TRUE,slan,&bl,&mystr[0]);
+
+ Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->FormSetTitle,TRUE,plan,&bl,&mystr[0]);
+
+ Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->Help,TRUE,slan,&bl,&mystr[0]);
+
+ Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->Help,TRUE,plan,&bl,&mystr[0]);
+
+ Status=HiiTestString(&gHiiDb.HiiProtocol,&mystr[0],&i,&gb);
+
+ }
+
+*/
+//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST
+ pBS->FreePool(pl);
+//
+// return pBS->InstallMultipleProtocolInterfaces( gHiiDb.ImageHandle,
+// &gEfiHiiProtocolGuid,&gHiiDb.HiiProtocol,NULL,NULL);
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/FwVol.c b/Core/CORE_DXE/FwVol.c
new file mode 100644
index 0000000..47057a2
--- /dev/null
+++ b/Core/CORE_DXE/FwVol.c
@@ -0,0 +1,589 @@
+/*++
+
+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:
+
+ FwVol.c
+
+Abstract:
+
+ Firmware File System driver that produce Firmware Volume protocol.
+ Layers on top of Firmware Block protocol to produce a file abstraction
+ of FV based files.
+
+--*/
+
+#include "FwVolDriver.h"
+#include "DxeCore.h"
+
+
+#define KEYSIZE sizeof (UINTN)
+
+//
+// Protocol notify related globals
+//
+VOID *gEfiFwVolBlockNotifyReg;
+EFI_EVENT gEfiFwVolBlockEvent;
+
+FV_DEVICE mFvDevice = {
+ FV_DEVICE_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FvGetVolumeAttributes,
+ FvSetVolumeAttributes,
+ FvReadFile,
+ FvReadFileSection,
+ FvWriteFile,
+ FvGetNextFile,
+ KEYSIZE,
+ NULL
+ #if (PI_SPECIFICATION_VERSION >= 0x00010000)
+ ,
+ FvGetVolumeInfo,
+ FvSetVolumeInfo
+ #endif
+ },
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ { NULL, NULL },
+ 0
+};
+
+
+//
+// FFS helper functions
+//
+
+EFI_STATUS
+GetFwVolHeader (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
+ )
+/*++
+
+Routine Description:
+ given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
+ copy the volume header into it.
+
+Arguments:
+ Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
+ header
+ FwVolHeader - Pointer to pointer to allocated buffer in which the volume
+ header is returned.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
+ EFI_SUCCESS - Successfully read volume header to the allocated buffer.
+
+--*/
+
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER TempFvh;
+ UINTN FvhLength;
+ UINT8 *Buffer;
+
+
+ //
+ //Determine the real length of FV header
+ //
+ FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);
+
+ //
+ // Allocate a buffer for the caller
+ //
+ *FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength);
+ if (*FwVolHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the standard header into the buffer
+ //
+ EfiCommonLibCopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+
+ //
+ // Read the rest of the header
+ //
+ FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);
+ Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);
+ if (EFI_ERROR (Status)) {
+ //
+ // Read failed so free buffer
+ //
+ CoreFreePool (*FwVolHeader);
+ }
+
+ return Status;
+}
+
+
+STATIC
+VOID
+FreeFvDeviceResource (
+ IN FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Free FvDevice resource when error happens
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be freed.
+
+Returns:
+ None.
+
+--*/
+{
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ EFI_LIST_ENTRY *NextEntry;
+
+ //
+ // Free File List Entry
+ //
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;
+ while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
+ NextEntry = (&FfsFileEntry->Link)->ForwardLink;
+
+ if (FfsFileEntry->StreamHandle != 0) {
+ //
+ // Close stream and free resources from SEP
+ //
+ FfsFileEntry->Sep->CloseSectionStream (FfsFileEntry->Sep, FfsFileEntry->StreamHandle);
+ }
+
+ CoreFreePool (FfsFileEntry);
+
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry;
+ }
+
+
+ //
+ // Free the cache
+ //
+ CoreFreePool (FvDevice->CachedFv);
+
+ //
+ // Free Volume Header
+ //
+ CoreFreePool (FvDevice->FwVolHeader);
+
+ return;
+}
+
+
+EFI_STATUS
+FvCheck (
+ IN OUT FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Check if a FV is consistent and allocate cache
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be checked.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
+ EFI_SUCCESS - FV is consistent and cache is allocated.
+ EFI_VOLUME_CORRUPTED - File system is corrupted.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINT8 *CacheLocation;
+ UINTN LbaOffset;
+ UINTN Index;
+ EFI_LBA LbaIndex;
+ UINTN Size;
+ UINTN FileLength;
+ EFI_FFS_FILE_STATE FileState;
+ UINT8 *TopFvAddress;
+ UINTN TestLength;
+
+
+ Fvb = FvDevice->Fvb;
+ FwVolHeader = FvDevice->FwVolHeader;
+
+//*** AMI PORTING BEGIN ***//
+//Update function name to match the spec
+// Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
+ Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
+//*** AMI PORTING END *****//
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Size is the size of the FV minus the head. We have already allocated
+ // the header to check to make sure the volume is valid
+ //
+ Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);
+ FvDevice->CachedFv = CoreAllocateZeroBootServicesPool (Size);
+ if (FvDevice->CachedFv == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Remember a pointer to the end fo the CachedFv
+ //
+ FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
+
+ //
+ // Copy FV minus header into memory using the block map we have all ready
+ // read into memory.
+ //
+ BlockMap = FwVolHeader->FvBlockMap;
+ CacheLocation = FvDevice->CachedFv;
+ LbaIndex = 0;
+ LbaOffset = FwVolHeader->HeaderLength;
+ while ((BlockMap->NumBlocks != 0) || (BlockMap->BlockLength != 0)) {
+
+ for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {
+
+ Size = BlockMap->BlockLength;
+ if (Index == 0) {
+ //
+ // Cache does not include FV Header
+ //
+ Size -= LbaOffset;
+ }
+ Status = Fvb->Read (Fvb,
+ LbaIndex,
+ LbaOffset,
+ &Size,
+ CacheLocation
+ );
+ //
+ // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength
+ //
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // After we skip Fv Header always read from start of block
+ //
+ LbaOffset = 0;
+
+ LbaIndex++;
+ CacheLocation += Size;
+ }
+ BlockMap++;
+ }
+
+ //
+ // Scan to check the free space & File list
+ //
+ if (FvbAttributes & EFI_FVB_ERASE_POLARITY) {
+ FvDevice->ErasePolarity = 1;
+ } else {
+ FvDevice->ErasePolarity = 0;
+ }
+
+
+ //
+ // go through the whole FV cache, check the consistence of the FV.
+ // Make a linked list off all the Ffs file headers
+ //
+ Status = EFI_SUCCESS;
+ InitializeListHead (&FvDevice->FfsFileListHeader);
+
+ //
+ // Build FFS list
+ //
+ FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv;
+ TopFvAddress = FvDevice->EndOfCachedFv;
+ while ((UINT8 *)FfsHeader < TopFvAddress) {
+
+ TestLength = TopFvAddress - ((UINT8 *)FfsHeader);
+ if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
+ TestLength = sizeof (EFI_FFS_FILE_HEADER);
+ }
+
+ if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {
+ //
+ // We have found the free space so we are done!
+ //
+ goto Done;
+ }
+
+ if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {
+ if ((FileState == EFI_FILE_HEADER_INVALID) ||
+ (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
+ FfsHeader++;
+
+ continue;
+
+ } else {
+ //
+ // File system is corrputed
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+ }
+
+ if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) {
+ //
+ // File system is corrupted
+ //
+ Status = EFI_VOLUME_CORRUPTED;
+ goto Done;
+ }
+
+ //
+ // Size[3] is a three byte array, read 4 bytes and throw one away
+ //
+ FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF;
+
+ FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader);
+
+ //
+ // check for non-deleted file
+ //
+ if (FileState != EFI_FILE_DELETED) {
+ //
+ // Create a FFS list entry for each non-deleted file
+ //
+ FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY));
+ if (FfsFileEntry == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ FfsFileEntry->FfsHeader = FfsHeader;
+ InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
+ }
+
+ FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength);
+
+ //
+ // Adjust pointer to the next 8-byte aligned boundry.
+ //
+ FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);
+
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ FreeFvDeviceResource (FvDevice);
+ }
+
+ return Status;
+}
+
+
+STATIC
+VOID
+EFIAPI
+NotifyFwVolBlock (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+ This notification function is invoked when an instance of the
+ EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
+ EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where
+ the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done.
+
+Arguments:
+ Event - The event that occured
+ Context - For EFI compatiblity. Not used.
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ FV_DEVICE *FvDevice;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+#endif
+
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = CoreLocateHandle (
+ ByRegisterNotify,
+ NULL,
+ gEfiFwVolBlockNotifyReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the FirmwareVolumeBlock protocol on that handle
+ //
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, &Fvb);
+ ASSERT_EFI_ERROR (Status);
+
+
+ //
+ // Make sure the Fv Header is O.K.
+ //
+ Status = GetFwVolHeader (Fvb, &FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ if (!VerifyFvHeaderChecksum (FwVolHeader)) {
+ CoreFreePool (FwVolHeader);
+ continue;
+ }
+
+
+ //
+ // Check to see that the file system is indeed formatted in a way we can
+ // understand it...
+ //
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ if (!EfiCompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) {
+#else
+ if (!EfiCompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) {
+#endif
+ continue;
+ }
+
+ //
+ // Check if there is an FV protocol already installed in that handle
+ //
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, &Fv);
+ #else
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ #endif
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update Fv to use a new Fvb
+ //
+ FvDevice = _CR (Fv, FV_DEVICE, Fv);
+ if (FvDevice->Signature == FV_DEVICE_SIGNATURE) {
+ //
+ // Only write into our device structure if it's our device structure
+ //
+ FvDevice->Fvb = Fvb;
+ }
+
+ } else {
+ //
+ // No FwVol protocol on the handle so create a new one
+ //
+ FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
+ if (FvDevice == NULL) {
+ return;
+ }
+
+ FvDevice->Fvb = Fvb;
+ FvDevice->Handle = Handle;
+ FvDevice->FwVolHeader = FwVolHeader;
+ FvDevice->Fv.ParentHandle = Fvb->ParentHandle;
+
+ //
+ // Install an New FV protocol on the existing handle
+ //
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ Status = CoreInstallProtocolInterface (
+ &Handle,
+ &gEfiFirmwareVolumeProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FvDevice->Fv
+ );
+ #else
+ Status = CoreInstallProtocolInterface (
+ &Handle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FvDevice->Fv
+ );
+
+ #endif
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, and registers two notification functions. These notification
+ functions are responsible for building the FV stack dynamically.
+
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+
+Returns:
+ EFI_SUCCESS - Function successfully returned.
+
+--*/
+{
+ gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent (
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ EFI_TPL_CALLBACK,
+ NotifyFwVolBlock,
+ NULL,
+ &gEfiFwVolBlockNotifyReg,
+ TRUE
+ );
+ return EFI_SUCCESS;
+}
+
diff --git a/Core/CORE_DXE/FwVolAttrib.c b/Core/CORE_DXE/FwVolAttrib.c
new file mode 100644
index 0000000..ab156df
--- /dev/null
+++ b/Core/CORE_DXE/FwVolAttrib.c
@@ -0,0 +1,244 @@
+/*++
+
+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:
+
+ FwVolAttrib.c
+
+Abstract:
+
+ Implements get/set firmware volume attributes
+
+--*/
+
+#include "FwVolDriver.h"
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+ Fvb = FvDevice->Fvb;
+
+ if (FvDevice->CachedFv == NULL) {
+ Status = FvCheck (FvDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // First get the Firmware Volume Block Attributes
+ //
+ Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
+
+ //
+ // Mask out Fvb bits that are not defined in FV
+ //
+ FvbAttributes &= 0xfffff0ff;
+
+ *Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes;
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+#else
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+ Fvb = FvDevice->Fvb;
+
+ if (FvDevice->CachedFv == NULL) {
+ Status = FvCheck (FvDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // First get the Firmware Volume Block Attributes
+ //
+//*** AMI PORTING BEGIN ***//
+//Update function name to match the spec
+// Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes);
+ Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
+//*** AMI PORTING END *****//
+
+ //
+ // Mask out Fvb bits that are not defined in FV
+ //
+ FvbAttributes &= 0xfffff0ff;
+
+ *Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes;
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeInfo (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Return information of type InformationType for the requested firmware
+ volume.
+
+Arguments:
+ This - Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
+ InformationType - InformationType for requested.
+ BufferSize - On input, size of Buffer.On output, the amount of
+ data returned in Buffer.
+ Buffer - A poniter to the data buffer to return.
+Returns:
+ EFI_SUCCESS - Successfully got volume Information.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeInfo (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN CONST VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Set information of type InformationType for the requested firmware
+ volume.
+
+Arguments:
+ This - Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
+ InformationType - InformationType for requested.
+ BufferSize - On input, size of Buffer.On output, the amount of
+ data returned in Buffer.
+ Buffer - A poniter to the data buffer to return.
+Returns:
+ EFI_SUCCESS - Successfully set volume Information.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+#endif
+
diff --git a/Core/CORE_DXE/FwVolBlock.c b/Core/CORE_DXE/FwVolBlock.c
new file mode 100644
index 0000000..9f409ff
--- /dev/null
+++ b/Core/CORE_DXE/FwVolBlock.c
@@ -0,0 +1,790 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ FwVolBlock.c
+
+Abstract:
+
+ Firmware Volume Block protocol.. Consumes FV hobs and creates
+ appropriate block protocols.
+
+ Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
+ block protocols fro them also... (this is TBD)
+
+--*/
+
+#include "Tiano.h"
+#include "FwVolBlock.h"
+//*** AMI PORTING BEGIN ***//
+// This header contains FFS definitions that do not exist in in FFS.h and other Aptio4 headers
+#include "EfiFirmwareVolumeHeader.h"
+#include <Protocol/FlashProtocol.h>
+//*** AMI PORTING END *****//
+
+EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = {
+ FVB_DEVICE_SIGNATURE,
+ NULL,
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8),
+ EfiMemoryMappedIO,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ },
+ },
+ {
+ FwVolBlockGetAttributes,
+ (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes,
+ FwVolBlockGetPhysicalAddress,
+ FwVolBlockGetBlockSize,
+ FwVolBlockReadBlock,
+ (EFI_FVB_WRITE)FwVolBlockWriteBlock,
+ (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock,
+ NULL
+ },
+ 0,
+ NULL,
+ 0,
+ 0
+};
+
+
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Since we are read only, it's safe to get attributes data from our in-memory copy.
+ //
+ *Attributes = FvbDevice->FvbAttributes;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockSetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Modifies the current settings of the firmware volume according to the input parameter.
+
+Arguments:
+ This - Calling context
+ Attributes - input buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+ EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
+ declared in the firmware volume header.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockEraseBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+/*++
+
+Routine Description:
+ The EraseBlock() function erases one or more blocks as denoted by the
+variable argument list. The entire parameter list of blocks must be verified
+prior to erasing any blocks. If a block is requested that does not exist
+within the associated firmware volume (it has a larger index than the last
+block of the firmware volume), the EraseBlock() function must return
+EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
+ the list.
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
+ written. The firmware device may have been partially erased.
+ EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
+ EFI_UNSUPPORTED - Not supported.
+
+--*/
+{
+//*** AMI PORTING BEGIN ***//
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ FLASH_PROTOCOL *FlashProtocol;
+ EFI_STATUS Status;
+ VA_LIST Marker;
+ EFI_LBA StartLba;
+ UINTN NumOfLba;
+ UINT64 i;
+ UINT8 *EraseAddress;
+ UINTN EraseSize;
+
+ Status = CoreLocateProtocol(&gFlashProtocolGuid, NULL, &FlashProtocol);
+ if(EFI_ERROR(Status))
+ return EFI_UNSUPPORTED;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+ //
+ // Check if This FW can be erased
+ //
+ if ((FvbDevice->FvbAttributes & EFI_FVB_WRITE_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ VA_START(Marker, This);
+ do {
+ StartLba = VA_ARG(Marker, EFI_LBA);
+ if(StartLba == EFI_LBA_LIST_TERMINATOR)
+ break;
+
+ NumOfLba = VA_ARG(Marker, UINTN);
+ if(NumOfLba == 0)
+ return EFI_INVALID_PARAMETER;
+
+ for(i = StartLba; i < StartLba + NumOfLba; i++) {
+ if(i >= FvbDevice->NumBlocks)
+ return EFI_INVALID_PARAMETER;
+
+ EraseAddress = (UINT8 *)((UINTN)FvbDevice->BaseAddress + FvbDevice->LbaCache[(UINT32)i].Base);
+ EraseSize = FvbDevice->LbaCache[(UINT32)i].Length;
+ Status = FlashProtocol->Erase(EraseAddress, EraseSize);
+ if(EFI_ERROR(Status))
+ return EFI_DEVICE_ERROR;
+ }
+ } while(Status == EFI_SUCCESS);
+ VA_END(Marker);
+ return Status;
+//*** AMI PORTING END ***//
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockReadBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Read the specified number of bytes from the block to the input buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to read.
+ Offset - Offset into the block at which to begin reading.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually read.
+ Buffer - Pinter to a caller-allocated buffer that contains the destine
+ for the read.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully.
+ EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
+ EFI_ACCESS_DENIED - Access denied.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT8 *LbaOffset;
+ UINTN LbaStart;
+ UINTN NumOfBytesRead;
+ UINTN LbaIndex;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Check if This FW can be read
+ //
+ if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ LbaIndex = (UINTN)Lba;
+ if (LbaIndex >= FvbDevice->NumBlocks) {
+ //
+ // Invalid Lba, read nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // all exceed boundry, read nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumOfBytesRead = *NumBytes;
+ if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // partial exceed boundry, read data from current postion to end.
+ //
+ NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;
+ }
+
+ LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
+ LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
+
+ //
+ // Perform read operation
+ //
+ EfiCommonLibCopyMem (Buffer, LbaOffset, NumOfBytesRead);
+
+ if (NumOfBytesRead == *NumBytes) {
+ return EFI_SUCCESS;
+ }
+
+ *NumBytes = NumOfBytesRead;
+ return EFI_BAD_BUFFER_SIZE;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockWriteBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Writes the specified number of bytes from the input buffer to the block.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to write to.
+ Offset - Offset into the block at which to begin writing.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually written.
+ Buffer - Pinter to a caller-allocated buffer that contains the source
+ for the write.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully.
+ EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
+ NumBytes contains the total number of bytes actually written.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+//*** AMI PORTING BEGIN ***//
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT8 *LbaOffset;
+ UINTN LbaStart;
+ UINTN NumOfBytesWritten;
+ UINTN LbaIndex;
+ EFI_STATUS Status;
+ FLASH_PROTOCOL *FlashProtocol;
+
+ Status = CoreLocateProtocol(&gFlashProtocolGuid, NULL, &FlashProtocol);
+ if(EFI_ERROR(Status))
+ return EFI_UNSUPPORTED;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Check if This FW can be written
+ //
+ if ((FvbDevice->FvbAttributes & EFI_FVB_WRITE_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ LbaIndex = (UINTN)Lba;
+ if (LbaIndex >= FvbDevice->NumBlocks) {
+ //
+ // Invalid Lba, write nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // all exceed boundry, write nothing.
+ //
+ *NumBytes = 0;
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumOfBytesWritten = *NumBytes;
+ if (Offset + NumOfBytesWritten > FvbDevice->LbaCache[LbaIndex].Length) {
+ //
+ // partial exceed boundry, write data from current postion to end.
+ //
+ NumOfBytesWritten = FvbDevice->LbaCache[LbaIndex].Length - Offset;
+ }
+
+ LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
+ LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
+
+ //
+ // Perform write operation
+ //
+ Status = FlashProtocol->Write(LbaOffset, NumOfBytesWritten, Buffer);
+ if(EFI_ERROR(Status))
+ return EFI_DEVICE_ERROR;
+
+ if (NumOfBytesWritten == *NumBytes) {
+ return EFI_SUCCESS;
+ }
+
+ *NumBytes = NumOfBytesWritten;
+ return EFI_BAD_BUFFER_SIZE;
+//*** AMI PORTING END ***//
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetPhysicalAddress (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+/*++
+
+Routine Description:
+ Get Fvb's base address.
+
+Arguments:
+ This - Indicates the calling context.
+ Address - Fvb device base address.
+
+Returns:
+ EFI_SUCCESS - Successfully got Fvb's base address.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) {
+ *Address = FvbDevice->BaseAddress;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetBlockSize (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+ Retrieves the size in bytes of a specific block within a firmware volume.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - Indicates the block for which to return the size.
+ BlockSize - Pointer to a caller-allocated UINTN in which the size of the
+ block is returned.
+ NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of
+ consecutive blocks starting with Lba is returned. All blocks
+ in this range have a size of BlockSize.
+Returns:
+ EFI_SUCCESS - The firmware volume base address is returned.
+ EFI_INVALID_PARAMETER - The requested LBA is out of range.
+--*/
+{
+ UINTN TotalBlocks;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ //
+ // Do parameter checking
+ //
+ if (Lba >= FvbDevice->NumBlocks) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
+
+ PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+
+ //
+ // Search the block map for the given block
+ //
+ TotalBlocks = 0;
+ while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->BlockLength !=0 )) {
+ TotalBlocks += PtrBlockMapEntry->NumBlocks;
+ if (Lba < TotalBlocks) {
+ //
+ // We find the range
+ //
+ break;
+ }
+
+ PtrBlockMapEntry++;
+ }
+
+ *BlockSize = PtrBlockMapEntry->BlockLength;
+ *NumberOfBlocks = TotalBlocks - (UINTN)Lba;
+
+ return EFI_SUCCESS;
+}
+
+
+#define SANE_MAX_FW_VOL_SIZE 0x40000000 //1GB
+#define SANE_MAX_FW_VOL_NO_BLOCKS SANE_MAX_FW_VOL_SIZE / sizeof(LBA_CACHE)
+
+
+EFI_STATUS
+ProduceFVBProtocolOnBuffer (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_HANDLE ParentHandle,
+ OUT EFI_HANDLE *FvProtocol OPTIONAL
+ )
+/*++
+
+Routine Description:
+ This routine produces a firmware volume block protocol on a given
+ buffer.
+
+Arguments:
+ BaseAddress - base address of the firmware volume image
+ Length - length of the firmware volume image
+ ParentHandle - handle of parent firmware volume, if this
+ image came from an FV image file in another
+ firmware volume (ala capsules)
+ FvProtocol - Firmware volume block protocol produced.
+
+Returns:
+ EFI_VOLUME_CORRUPTED - Volume corrupted.
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDev;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINTN BlockIndex;
+ UINTN BlockIndex2;
+ UINTN LinearOffset;
+ EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+ //
+ // Validate FV Header, if not as expected, return
+ //
+ if (FwVolHeader->Signature != EFI_FVH_SIGNATURE || FwVolHeader->FvLength > SANE_MAX_FW_VOL_SIZE) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ //
+ // Allocate EFI_FW_VOL_BLOCK_DEVICE
+ //
+ FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
+ if (FvbDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FvbDev->BaseAddress = BaseAddress;
+ FvbDev->FvbAttributes = FwVolHeader->Attributes;
+ FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;
+
+ //
+ // Init the block caching fields of the device
+ // First, count the number of blocks
+ //
+ FvbDev->NumBlocks = 0;
+ for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+ PtrBlockMapEntry->NumBlocks != 0;
+ PtrBlockMapEntry++) {
+ if(PtrBlockMapEntry->NumBlocks < SANE_MAX_FW_VOL_NO_BLOCKS - FvbDev->NumBlocks)
+ FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
+ else {
+ CoreFreePool (FvbDev);
+ return EFI_VOLUME_CORRUPTED;
+ }
+ }
+ //
+ // Second, allocate the cache
+ //
+ FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
+ if (FvbDev->LbaCache == NULL) {
+ CoreFreePool (FvbDev);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Last, fill in the cache with the linear address of the blocks
+ //
+ BlockIndex = 0;
+ LinearOffset = 0;
+ for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
+ PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
+ for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
+ FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
+ FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->BlockLength;
+ if(PtrBlockMapEntry->BlockLength <= FwVolHeader->FvLength - LinearOffset) {
+ LinearOffset += PtrBlockMapEntry->BlockLength;
+ BlockIndex++;
+ } else {
+ CoreFreePool (FvbDev->LbaCache);
+ CoreFreePool (FvbDev);
+ return EFI_VOLUME_CORRUPTED;
+ }
+ }
+ }
+
+ //
+ // Set up the devicepath
+ //
+ FvbDev->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
+ FvbDev->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;
+
+ //
+ //
+ // Attach FvVolBlock Protocol to new handle
+ //
+ Status = CoreInstallMultipleProtocolInterfaces (
+ &FvbDev->Handle,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDev->FwVolBlockInstance,
+ &gEfiDevicePathProtocolGuid, &FvbDev->DevicePath,
+ &gEfiFirmwareVolumeDispatchProtocolGuid, NULL,
+ NULL
+ );
+
+ //
+ // If they want the handle back, set it.
+ //
+ if (FvProtocol != NULL) {
+ *FvProtocol = FvbDev->Handle;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
+ produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+Returns:
+ EFI_SUCCESS - Successfully initialized firmware volume block driver.
+--*/
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_STATUS HobStatus;
+#if (PI_SPECIFICATION_VERSION >= 0x00010000)
+ EFI_GUID FileName;
+#endif
+ //
+ // First walk hobs and create appropriate FVs.
+ //
+ Status = CoreGetConfigTable (&gEfiHobListGuid, &HobList);
+ //
+ // Core Needs Firmware Volumes to function
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ BaseAddress = 0;
+ Length = 0;
+ HobStatus = GetNextFirmwareVolumeHob (
+ &HobList,
+ &BaseAddress,
+ &Length
+ );
+ while (!EFI_ERROR (HobStatus)) {
+ //
+ // Produce an FVB protocol for it
+ //
+ ProduceFVBProtocolOnBuffer (BaseAddress, Length, NULL, NULL);
+ HobStatus = GetNextFirmwareVolumeHob (
+ &HobList,
+ &BaseAddress,
+ &Length
+ );
+ }
+
+#if (PI_SPECIFICATION_VERSION >= 0x00010000)
+ //
+ // First walk hobs and create appropriate FVs.
+ //
+ Status = CoreGetConfigTable (&gEfiHobListGuid, &HobList);
+ //
+ // Core Needs Firmware Volumes to function
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ BaseAddress = 0;
+ Length = 0;
+
+ HobStatus = GetNextFirmwareVolume2Hob (
+ &HobList,
+ &BaseAddress,
+ &Length,
+ &FileName
+ );
+ while (!EFI_ERROR (HobStatus)) {
+ //
+ // Produce an FVB protocol for it
+ //
+ ProduceFVBProtocolOnBuffer (BaseAddress, Length, NULL, NULL);
+ HobStatus = GetNextFirmwareVolume2Hob (
+ &HobList,
+ &BaseAddress,
+ &Length,
+ &FileName
+ );
+ }
+#endif
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CoreProcessFirmwareVolume (
+ IN VOID *FvHeader,
+ IN UINTN Size,
+ OUT EFI_HANDLE *FVProtocolHandle
+ )
+/*++
+
+Routine Description:
+ This DXE service routine is used to process a firmware volume. In
+ particular, it can be called by BDS to process a single firmware
+ volume found in a capsule.
+
+Arguments:
+ FvHeader - pointer to a firmware volume header
+ Size - the size of the buffer pointed to by FvHeader
+ FVProtocolHandle - the handle on which a firmware volume protocol
+ was produced for the firmware volume passed in.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of
+ system resources
+ EFI_VOLUME_CORRUPTED - if the volume was corrupted
+ EFI_SUCCESS - a firmware volume protocol was produced for the
+ firmware volume
+
+--*/
+{
+ VOID *Ptr;
+ EFI_STATUS Status;
+
+ *FVProtocolHandle = NULL;
+ Status = ProduceFVBProtocolOnBuffer (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
+ (UINT64)Size,
+ NULL,
+ FVProtocolHandle
+ );
+ //
+ // Since in our implementation we use register-protocol-notify to put a
+ // FV protocol on the FVB protocol handle, we can't directly verify that
+ // the FV protocol was produced. Therefore here we will check the handle
+ // and make sure an FV protocol is on it. This indicates that all went
+ // well. Otherwise we have to assume that the volume was corrupted
+ // somehow.
+ //
+ if (!EFI_ERROR(Status)) {
+ Ptr = NULL;
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolumeProtocolGuid, &Ptr);
+ #else
+ Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, &Ptr);
+ #endif
+ if (EFI_ERROR(Status) || (Ptr == NULL)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
diff --git a/Core/CORE_DXE/FwVolBlock.h b/Core/CORE_DXE/FwVolBlock.h
new file mode 100644
index 0000000..b3f26b7
--- /dev/null
+++ b/Core/CORE_DXE/FwVolBlock.h
@@ -0,0 +1,314 @@
+/*++
+
+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:
+
+ FwVolBlock.h
+
+Abstract:
+
+ Firmware Volume Block protocol.. Consumes FV hobs and creates
+ appropriate block protocols.
+
+ Also consumes NT_NON_MM_FV envinronment variable and produces appropriate
+ block protocols fro them also... (this is TBD)
+
+--*/
+
+#ifndef _FWVOL_BLOCK_H_
+#define _FWVOL_BLOCK_H_
+
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include "Peihob.h"
+#include "EfiHobLib.h"
+#include "DxeCore.h"
+
+#include EFI_GUID_DEFINITION (Hob)
+
+
+
+#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32('_','F','V','B')
+
+typedef struct {
+ UINTN Base;
+ UINTN Length;
+} LBA_CACHE;
+
+typedef struct {
+ MEMMAP_DEVICE_PATH MemMapDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_DEVICE_PATH;
+
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ FV_DEVICE_PATH DevicePath;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
+ UINTN NumBlocks;
+ LBA_CACHE *LbaCache;
+ UINT32 FvbAttributes;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+#define FVB_DEVICE_FROM_THIS(a) \
+ CR(a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockDriverInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ This routine is the driver initialization entry point. It initializes the
+ libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
+ produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
+Arguments:
+ ImageHandle - The image handle.
+ SystemTable - The system table.
+Returns:
+ EFI_SUCCESS - Successfully initialized firmware volume block driver.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves Volume attributes. No polarity translations are done.
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockSetAttributes (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Modifies the current settings of the firmware volume according to the input parameter.
+
+Arguments:
+ This - Calling context
+ Attributes - input buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - The firmware volume attributes were returned.
+ EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as
+ declared in the firmware volume header.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockEraseBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+/*++
+
+Routine Description:
+ The EraseBlock() function erases one or more blocks as denoted by the
+variable argument list. The entire parameter list of blocks must be verified
+prior to erasing any blocks. If a block is requested that does not exist
+within the associated firmware volume (it has a larger index than the last
+block of the firmware volume), the EraseBlock() function must return
+EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+Arguments:
+ This - Calling context
+ ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate
+ the list.
+
+Returns:
+ EFI_SUCCESS - The erase request was successfully completed.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be
+ written. The firmware device may have been partially erased.
+ EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do
+ EFI_UNSUPPORTED - Not supported.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockReadBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Read the specified number of bytes from the block to the input buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to read.
+ Offset - Offset into the block at which to begin reading.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually read.
+ Buffer - Pinter to a caller-allocated buffer that contains the destine
+ for the read.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was read successfully.
+ EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary.
+ EFI_ACCESS_DENIED - Access denied.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockWriteBlock (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+ Writes the specified number of bytes from the input buffer to the block.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - The starting logical block index to write to.
+ Offset - Offset into the block at which to begin writing.
+ NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the
+ total size of the buffer. At exit, *NumBytes contains the
+ total number of bytes actually written.
+ Buffer - Pinter to a caller-allocated buffer that contains the source
+ for the write.
+
+Returns:
+ EFI_SUCCESS - The firmware volume was written successfully.
+ EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output,
+ NumBytes contains the total number of bytes actually written.
+ EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state.
+ EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetPhysicalAddress (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+/*++
+
+Routine Description:
+ Get Fvb's base address.
+
+Arguments:
+ This - Indicates the calling context.
+ Address - Fvb device base address.
+
+Returns:
+ EFI_SUCCESS - Successfully got Fvb's base address.
+ EFI_UNSUPPORTED - Not supported.
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FwVolBlockGetBlockSize (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+ Retrieves the size in bytes of a specific block within a firmware volume.
+
+Arguments:
+ This - Indicates the calling context.
+ Lba - Indicates the block for which to return the size.
+ BlockSize - Pointer to a caller-allocated UINTN in which the size of the
+ block is returned.
+ NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of
+ consecutive blocks starting with Lba is returned. All blocks
+ in this range have a size of BlockSize.
+Returns:
+ EFI_SUCCESS - The firmware volume base address is returned.
+ EFI_INVALID_PARAMETER - The requested LBA is out of range.
+--*/
+;
+
+EFI_STATUS
+ProduceFVBProtocolOnBuffer (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_HANDLE ParentHandle,
+ OUT EFI_HANDLE *FvProtocolHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+ This routine produces a firmware volume block protocol on a given
+ buffer.
+
+Arguments:
+ BaseAddress - base address of the firmware volume image
+ Length - length of the firmware volume image
+ ParentHandle - handle of parent firmware volume, if this
+ image came from an FV image file in another
+ firmware volume (ala capsules)
+ FvProtocolHandle - Firmware volume block protocol produced.
+
+Returns:
+ EFI_VOLUME_CORRUPTED - Volume corrupted.
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Successfully produced a FVB protocol on given buffer.
+
+--*/
+;
+
+#endif
diff --git a/Core/CORE_DXE/FwVolDriver.h b/Core/CORE_DXE/FwVolDriver.h
new file mode 100644
index 0000000..6404e3b
--- /dev/null
+++ b/Core/CORE_DXE/FwVolDriver.h
@@ -0,0 +1,772 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ FwVolDriver.h
+
+Abstract:
+
+ Firmware File System protocol. Layers on top of Firmware
+ Block protocol to produce a file abstraction of FV based files.
+
+--*/
+
+#ifndef __FWVOL_H
+#define __FWVOL_H
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiFirmwareFileSystem.h"
+#include "EfiFirmwareVolumeHeader.h"
+
+//
+// Consumed protocol
+//
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)
+#include EFI_PROTOCOL_DEFINITION (SectionExtraction)
+
+//
+// Consumed GUID & Produced protocol
+//
+#include EFI_GUID_DEFINITION (FirmwareFileSystem)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume)
+#include EFI_GUID_DEFINITION (FirmwareFileSystem2)
+#include EFI_PROTOCOL_DEFINITION (FirmwareVolume2)
+
+
+//
+// Used to track all non-deleted files
+//
+typedef struct {
+ EFI_LIST_ENTRY Link;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINTN StreamHandle;
+ EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
+} FFS_FILE_LIST_ENTRY;
+
+typedef struct {
+ UINTN Signature;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
+ EFI_HANDLE Handle;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL Fv;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL Fv;
+#endif
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ UINT8 *CachedFv;
+ UINT8 *EndOfCachedFv;
+
+ FFS_FILE_LIST_ENTRY *LastKey;
+
+ EFI_LIST_ENTRY FfsFileListHeader;
+
+ UINT8 ErasePolarity;
+} FV_DEVICE;
+
+#define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE)
+
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+;
+
+#else
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Retrieves attributes, insures positive polarity of attribute bits, returns
+ resulting attributes in output parameter
+
+Arguments:
+ This - Calling context
+ Attributes - output buffer which contains attributes
+
+Returns:
+ EFI_SUCCESS - Successfully got volume attributes
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN OUT EFI_FV_ATTRIBUTES *Attributes
+ )
+/*++
+
+Routine Description:
+ Sets current attributes for volume
+
+Arguments:
+ This - Calling context
+ Attributes - At input, contains attributes to be set. At output contains
+ new value of FV
+
+Returns:
+ EFI_UNSUPPORTED - Could not be set.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FvGetVolumeInfo (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Return information of type InformationType for the requested firmware
+ volume.
+
+Arguments:
+ This - Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
+ InformationType - InformationType for requested.
+ BufferSize - On input, size of Buffer.On output, the amount of
+ data returned in Buffer.
+ Buffer - A poniter to the data buffer to return.
+Returns:
+ EFI_SUCCESS - Successfully got volume Information.
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+FvSetVolumeInfo (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN CONST VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Set information of type InformationType for the requested firmware
+ volume.
+
+Arguments:
+ This - Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
+ InformationType - InformationType for requested.
+ BufferSize - On input, size of Buffer.On output, the amount of
+ data returned in Buffer.
+ Buffer - A poniter to the data buffer to return.
+Returns:
+ EFI_SUCCESS - Successfully set volume Information.
+
+--*/
+;
+
+
+#endif
+
+
+//
+//Internal functions
+//
+typedef enum {
+ EfiCheckSumUint8 = 0,
+ EfiCheckSumUint16 = 1,
+ EfiCheckSumUint32 = 2,
+ EfiCheckSumUint64 = 3,
+ EfiCheckSumMaximum = 4
+} EFI_CHECKSUM_TYPE;
+
+
+BOOLEAN
+IsBufferErased (
+ IN UINT8 ErasePolarity,
+ IN VOID *Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+ Check if a block of buffer is erased
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ Buffer - The buffer to be checked
+ BufferSize - Size of the buffer in bytes
+
+Returns:
+ TRUE - The block of buffer is erased
+ FALSE - The block of buffer is not erased
+
+--*/
+;
+
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Get the FFS file state by checking the highest bit set in the header's state field
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ FFS File state
+
+--*/
+;
+
+VOID
+SetFileState (
+ IN UINT8 State,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Set the FFS file state.
+
+Arguments:
+ State - The state to be set.
+ FfsHeader - Points to the FFS file header
+
+Returns:
+ None.
+
+--*/
+;
+
+BOOLEAN
+VerifyFvHeaderChecksum (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+ Verify checksum of the firmware volume header
+
+Arguments:
+ FvHeader - Points to the firmware volume header to be checked
+
+Returns:
+ TRUE - Checksum verification passed
+ FALSE - Checksum verification failed
+
+--*/
+;
+
+BOOLEAN
+IsValidFfsHeader (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT EFI_FFS_FILE_STATE *FileState
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file header
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file header to be checked
+ FileState - FFS file state to be returned
+
+Returns:
+ TRUE - Valid FFS file header
+ FALSE - Invalid FFS file header
+
+--*/
+;
+
+BOOLEAN
+IsValidFfsFile (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+ Check if it's a valid FFS file.
+ Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
+
+Arguments:
+ ErasePolarity - Erase polarity attribute of the firmware volume
+ FfsHeader - Points to the FFS file to be checked
+
+Returns:
+ TRUE - Valid FFS file
+ FALSE - Invalid FFS file
+
+--*/
+;
+
+EFI_STATUS
+GetFwVolHeader (
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
+ )
+/*++
+
+Routine Description:
+ given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
+ copy the volume header into it.
+
+Arguments:
+ Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
+ header
+ FwVolHeader - Pointer to pointer to allocated buffer in which the volume
+ header is returned.
+
+Returns:
+ Status code.
+
+--*/
+;
+
+
+EFI_STATUS
+FvCheck (
+ IN OUT FV_DEVICE *FvDevice
+ )
+/*++
+
+Routine Description:
+ Check if a FV is consistent and allocate cache
+
+Arguments:
+ FvDevice - pointer to the FvDevice to be checked.
+
+Returns:
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_SUCCESS - FV is consistent and cache is allocated.
+ EFI_VOLUME_CORRUPTED - File system is corrupted.
+
+--*/
+;
+
+#endif
diff --git a/Core/CORE_DXE/FwVolRead.c b/Core/CORE_DXE/FwVolRead.c
new file mode 100644
index 0000000..dced47f
--- /dev/null
+++ b/Core/CORE_DXE/FwVolRead.c
@@ -0,0 +1,993 @@
+/*++
+
+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:
+
+ FwVolRead.c
+
+Abstract:
+
+ Implements read firmware file
+
+--*/
+
+#include "FwVolDriver.h"
+#include "DxeCore.h"
+
+/*++
+
+Required Alignment Alignment Value in FFS Alignment Value in
+(bytes) Attributes Field Firmware Volume Interfaces
+1 0 0
+2 0 1
+4 0 2
+8 0 3
+16 1 4
+128 2 7
+512 3 9
+1 KB 4 10
+4 KB 5 12
+32 KB 6 15
+64 KB 7 16
+
+--*/
+
+UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
+
+
+STATIC
+EFI_FV_FILE_ATTRIBUTES
+FfsAttributes2FvFileAttributes (
+ IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
+ )
+/*++
+
+ Routine Description:
+ Convert the FFS File Attributes to FV File Attributes
+
+ Arguments:
+ FfsAttributes - The attributes of UINT8 type.
+
+ Returns:
+ The attributes of EFI_FV_FILE_ATTRIBUTES
+
+--*/
+{
+ FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
+ ASSERT (FfsAttributes < 8);
+
+ return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];
+}
+
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_ATTRIBUTES FvAttributes;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINTN *KeyValue;
+ EFI_LIST_ENTRY *Link;
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ UINTN FileLength;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ Status = FvGetVolumeAttributes (This, &FvAttributes);
+ if (EFI_ERROR (Status)){
+ return Status;
+ }
+
+ //
+ // Check if read operation is enabled
+ //
+ if ((FvAttributes & EFI_FV_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+ if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
+#else
+ if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+ //
+ // File type needs to be in 0 - 0x0B
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ KeyValue = (UINTN *)Key;
+ for (;;) {
+ if (*KeyValue == 0) {
+ //
+ // Search for 1st matching file
+ //
+ Link = &FvDevice->FfsFileListHeader;
+ } else {
+ //
+ // Key is pointer to FFsFileEntry, so get next one
+ //
+ Link = (EFI_LIST_ENTRY *)(*KeyValue);
+ }
+
+ if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
+ //
+ // Next is end of list so we did not find data
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
+
+ //
+ // remember the key
+ //
+ *KeyValue = (UINTN)FfsFileEntry;
+
+ if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
+ //
+ // we ignore pad files
+ //
+ continue;
+ }
+
+ if (*FileType == 0) {
+ //
+ // Process all file types so we have a match
+ //
+ break;
+ }
+
+ if (*FileType == FfsFileHeader->Type) {
+ //
+ // Found a matching file type
+ //
+ break;
+ }
+
+ }
+
+ //
+ // Return FileType, NameGuid, and Attributes
+ //
+ *FileType = FfsFileHeader->Type;
+ EfiCommonLibCopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID));
+ *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
+
+ //
+ // Read four bytes out of the 3 byte array and throw out extra data
+ //
+ FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;
+
+ //
+ // we need to substract the header size
+ //
+ *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);
+
+ if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // If tail is present substract it's size;
+ //
+ *Size -= sizeof(EFI_FFS_FILE_TAIL);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_GUID SearchNameGuid;
+ EFI_FV_FILETYPE LocalFoundType;
+ EFI_FV_FILE_ATTRIBUTES LocalAttributes;
+ UINTN FileSize;
+ UINT8 *SrcPtr;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINTN InputBufferSize;
+
+ if (NULL == NameGuid) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+
+ //
+ // Keep looking until we find the matching NameGuid.
+ // The Key is really an FfsFileEntry
+ //
+ FvDevice->LastKey = 0;
+ do {
+ LocalFoundType = 0;
+ Status = FvGetNextFile (
+ This,
+ &FvDevice->LastKey,
+ &LocalFoundType,
+ &SearchNameGuid,
+ &LocalAttributes,
+ &FileSize
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ } while (!EfiCompareGuid (&SearchNameGuid, NameGuid));
+
+ //
+ // Get a pointer to the header
+ //
+ FfsHeader = FvDevice->LastKey->FfsHeader;
+
+ //
+ // Remember callers buffer size
+ //
+ InputBufferSize = *BufferSize;
+
+ //
+ // Calculate return values
+ //
+ *FoundType = FfsHeader->Type;
+ *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
+ *AuthenticationStatus = 0;
+ *BufferSize = FileSize;
+
+ if (Buffer == NULL) {
+ //
+ // If Buffer is NULL, we only want to get the information colected so far
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip over file header
+ //
+ SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
+
+ Status = EFI_SUCCESS;
+ if (*Buffer == NULL) {
+ //
+ // Caller passed in a pointer so allocate buffer for them
+ //
+ *Buffer = CoreAllocateBootServicesPool (FileSize);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else if (FileSize > InputBufferSize) {
+ //
+ // Callers buffer was not big enough
+ //
+ Status = EFI_WARN_BUFFER_TOO_SMALL;
+ FileSize = InputBufferSize;
+ }
+
+ //
+ // Copy data into callers buffer
+ //
+ EfiCommonLibCopyMem (*Buffer, SrcPtr, FileSize);
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINTN FileSize;
+ UINT8 *FileBuffer;
+ EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
+ FFS_FILE_LIST_ENTRY *FfsEntry;
+
+ if (NULL == NameGuid || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ //
+ // Read the whole file into buffer
+ //
+ FileBuffer = NULL;
+ Status = FvReadFile (
+ This,
+ NameGuid,
+ &FileBuffer,
+ &FileSize,
+ &FileType,
+ &FileAttributes,
+ AuthenticationStatus
+ );
+ //
+ // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
+ //
+ FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey;
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check to see that the file actually HAS sections before we go any further.
+ //
+ if (FileType == EFI_FV_FILETYPE_RAW) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Use FfsEntry to cache Section Extraction Protocol Inforomation
+ //
+ if (FfsEntry->StreamHandle == 0) {
+ //
+ // Located the protocol
+ //
+ Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, &Sep);
+ //
+ // Section Extraction Protocol is part of Dxe Core so this should never fail
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Sep->OpenSectionStream (
+ Sep,
+ FileSize,
+ FileBuffer,
+ &FfsEntry->StreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ FfsEntry->Sep = Sep;
+ } else {
+ //
+ // Get cached copy of Sep
+ //
+ Sep = FfsEntry->Sep;
+ }
+
+ //
+ // If SectionType == 0 We need the whole section stream
+ //
+ Status = Sep->GetSection (
+ Sep,
+ FfsEntry->StreamHandle,
+ (SectionType == 0) ? NULL : &SectionType,
+ NULL,
+ (SectionType == 0) ? 0 : SectionInstance,
+ Buffer,
+ BufferSize,
+ AuthenticationStatus
+ );
+
+ //
+ // Close of stream defered to close of FfsHeader list to allow SEP to cache data
+ //
+
+Done:
+ CoreFreePool (FileBuffer);
+
+ return Status;
+}
+
+#else
+
+EFI_STATUS
+EFIAPI
+FvGetNextFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN OUT VOID *Key,
+ IN OUT EFI_FV_FILETYPE *FileType,
+ OUT EFI_GUID *NameGuid,
+ OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+ Given the input key, search for the next matching file in the volume.
+
+Arguments:
+ This - Indicates the calling context.
+ FileType - FileType is a pointer to a caller allocated
+ EFI_FV_FILETYPE. The GetNextFile() API can filter it's
+ search for files based on the value of *FileType input.
+ A *FileType input of 0 causes GetNextFile() to search for
+ files of all types. If a file is found, the file's type
+ is returned in *FileType. *FileType is not modified if
+ no file is found.
+ Key - Key is a pointer to a caller allocated buffer that
+ contains implementation specific data that is used to
+ track where to begin the search for the next file.
+ The size of the buffer must be at least This->KeySize
+ bytes long. To reinitialize the search and begin from
+ the beginning of the firmware volume, the entire buffer
+ must be cleared to zero. Other than clearing the buffer
+ to initiate a new search, the caller must not modify the
+ data in the buffer between calls to GetNextFile().
+ NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
+ If a file is found, the file's name is returned in
+ *NameGuid. *NameGuid is not modified if no file is
+ found.
+ Attributes - Attributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
+ attributes are returned in *Attributes. *Attributes is
+ not modified if no file is found.
+ Size - Size is a pointer to a caller allocated UINTN.
+ If a file is found, the file's size is returned in *Size.
+ *Size is not modified if no file is found.
+
+Returns:
+ EFI_SUCCESS - Successfully find the file.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Fv could not read.
+ EFI_NOT_FOUND - No matching file found.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_ATTRIBUTES FvAttributes;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINTN *KeyValue;
+ EFI_LIST_ENTRY *Link;
+ FFS_FILE_LIST_ENTRY *FfsFileEntry;
+ UINTN FileLength;
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ Status = FvGetVolumeAttributes (This, &FvAttributes);
+ if (EFI_ERROR (Status)){
+ return Status;
+ }
+
+ //
+ // Check if read operation is enabled
+ //
+ if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x0001000A
+ if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
+#else
+ if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+ //
+ // File type needs to be in 0 - 0x0B
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ KeyValue = (UINTN *)Key;
+ for (;;) {
+ if (*KeyValue == 0) {
+ //
+ // Search for 1st matching file
+ //
+ Link = &FvDevice->FfsFileListHeader;
+ } else {
+ //
+ // Key is pointer to FFsFileEntry, so get next one
+ //
+ Link = (EFI_LIST_ENTRY *)(*KeyValue);
+ }
+
+ if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
+ //
+ // Next is end of list so we did not find data
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
+
+ //
+ // remember the key
+ //
+ *KeyValue = (UINTN)FfsFileEntry;
+
+ if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
+ //
+ // we ignore pad files
+ //
+ continue;
+ }
+
+ if (*FileType == 0) {
+ //
+ // Process all file types so we have a match
+ //
+ break;
+ }
+
+ if (*FileType == FfsFileHeader->Type) {
+ //
+ // Found a matching file type
+ //
+ break;
+ }
+
+ }
+
+ //
+ // Return FileType, NameGuid, and Attributes
+ //
+ *FileType = FfsFileHeader->Type;
+ EfiCommonLibCopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID));
+ *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
+
+ //
+ // Read four bytes out of the 3 byte array and throw out extra data
+ //
+ FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF;
+
+ //
+ // we need to substract the header size
+ //
+ *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER);
+
+//*** AMI PORTING BEGIN ***//
+//Bug fix: FFS_ATTRIB_TAIL_PRESENT attribute dies not exist in PI Specification.
+#if PI_SPECIFICATION_VERSION < 0x00010000
+//*** AMI PORTING END *****//
+ if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // If tail is present substract it's size;
+ //
+ *Size -= sizeof(EFI_FFS_FILE_TAIL);
+ }
+//*** AMI PORTING BEGIN ***//
+//see comments above
+#endif //#if PI_SPECIFICATION_VERSION < 0x00010000
+//*** AMI PORTING END *****//
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+FvReadFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *NameGuid,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FV_FILETYPE *FoundType,
+ OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+ Locates a file in the firmware volume and
+ copies it to the supplied buffer.
+
+Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ Buffer - Buffer is a pointer to pointer to a buffer in
+ which the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated
+ UINTN. On input *BufferSize indicates the size
+ in bytes of the memory region pointed to by
+ Buffer. On output, *BufferSize contains the number
+ of bytes required to read the file.
+ FoundType - FoundType is a pointer to a caller allocated
+ EFI_FV_FILETYPE that on successful return from Read()
+ contains the type of file read. This output reflects
+ the file type irrespective of the value of the
+ SectionType input.
+ FileAttributes - FileAttributes is a pointer to a caller allocated
+ EFI_FV_FILE_ATTRIBUTES. On successful return from
+ Read(), *FileAttributes contains the attributes of
+ the file read.
+ AuthenticationStatus - AuthenticationStatus is a pointer to a caller
+ allocated UINTN in which the authentication status
+ is returned.
+Returns:
+ EFI_SUCCESS - Successfully read to memory buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_GUID SearchNameGuid;
+ EFI_FV_FILETYPE LocalFoundType;
+ EFI_FV_FILE_ATTRIBUTES LocalAttributes;
+ UINTN FileSize;
+ UINT8 *SrcPtr;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ UINTN InputBufferSize;
+
+ if (NULL == NameGuid) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+
+ //
+ // Keep looking until we find the matching NameGuid.
+ // The Key is really an FfsFileEntry
+ //
+ FvDevice->LastKey = 0;
+ do {
+ LocalFoundType = 0;
+ Status = FvGetNextFile (
+ This,
+ &FvDevice->LastKey,
+ &LocalFoundType,
+ &SearchNameGuid,
+ &LocalAttributes,
+ &FileSize
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ } while (!EfiCompareGuid (&SearchNameGuid, (EFI_GUID*)NameGuid));
+
+ //
+ // Get a pointer to the header
+ //
+ FfsHeader = FvDevice->LastKey->FfsHeader;
+
+ //
+ // Remember callers buffer size
+ //
+ InputBufferSize = *BufferSize;
+
+ //
+ // Calculate return values
+ //
+ *FoundType = FfsHeader->Type;
+ *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
+ *AuthenticationStatus = 0;
+ *BufferSize = FileSize;
+
+ if (Buffer == NULL) {
+ //
+ // If Buffer is NULL, we only want to get the information colected so far
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip over file header
+ //
+ SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
+
+ Status = EFI_SUCCESS;
+ if (*Buffer == NULL) {
+ //
+ // Caller passed in a pointer so allocate buffer for them
+ //
+ *Buffer = CoreAllocateBootServicesPool (FileSize);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else if (FileSize > InputBufferSize) {
+ //
+ // Callers buffer was not big enough
+ //
+ Status = EFI_WARN_BUFFER_TOO_SMALL;
+ FileSize = InputBufferSize;
+ }
+
+ //
+ // Copy data into callers buffer
+ //
+ EfiCommonLibCopyMem (*Buffer, SrcPtr, FileSize);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FvReadFileSection (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN CONST EFI_GUID *NameGuid,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN SectionInstance,
+ IN OUT VOID **Buffer,
+ IN OUT UINTN *BufferSize,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+ Routine Description:
+ Locates a section in a given FFS File and
+ copies it to the supplied buffer (not including section header).
+
+ Arguments:
+ This - Indicates the calling context.
+ NameGuid - Pointer to an EFI_GUID, which is the filename.
+ SectionType - Indicates the section type to return.
+ SectionInstance - Indicates which instance of sections with a type of
+ SectionType to return.
+ Buffer - Buffer is a pointer to pointer to a buffer in which
+ the file or section contents or are returned.
+ BufferSize - BufferSize is a pointer to caller allocated UINTN.
+ AuthenticationStatus -AuthenticationStatus is a pointer to a caller
+ allocated UINT32 in which the authentication status
+ is returned.
+
+ Returns:
+ EFI_SUCCESS - Successfully read the file section into buffer.
+ EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
+ EFI_NOT_FOUND - Section not found.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_ACCESS_DENIED - Could not read.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+{
+ EFI_STATUS Status;
+ FV_DEVICE *FvDevice;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINTN FileSize;
+ UINT8 *FileBuffer;
+ EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
+ FFS_FILE_LIST_ENTRY *FfsEntry;
+
+ if (NULL == NameGuid || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvDevice = FV_DEVICE_FROM_THIS (This);
+
+ //
+ // Read the whole file into buffer
+ //
+ FileBuffer = NULL;
+ Status = FvReadFile (
+ This,
+ NameGuid,
+ &FileBuffer,
+ &FileSize,
+ &FileType,
+ &FileAttributes,
+ AuthenticationStatus
+ );
+ //
+ // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
+ //
+ FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey;
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check to see that the file actually HAS sections before we go any further.
+ //
+ if (FileType == EFI_FV_FILETYPE_RAW) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Use FfsEntry to cache Section Extraction Protocol Inforomation
+ //
+ if (FfsEntry->StreamHandle == 0) {
+ //
+ // Located the protocol
+ //
+ Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, &Sep);
+ //
+ // Section Extraction Protocol is part of Dxe Core so this should never fail
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Sep->OpenSectionStream (
+ Sep,
+ FileSize,
+ FileBuffer,
+ &FfsEntry->StreamHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ FfsEntry->Sep = Sep;
+ } else {
+ //
+ // Get cached copy of Sep
+ //
+ Sep = FfsEntry->Sep;
+ }
+
+ //
+ // If SectionType == 0 We need the whole section stream
+ //
+ Status = Sep->GetSection (
+ Sep,
+ FfsEntry->StreamHandle,
+ (SectionType == 0) ? NULL : &SectionType,
+ NULL,
+ (SectionType == 0) ? 0 : SectionInstance,
+ Buffer,
+ BufferSize,
+ AuthenticationStatus
+ );
+
+ //
+ // Close of stream defered to close of FfsHeader list to allow SEP to cache data
+ //
+
+Done:
+ CoreFreePool (FileBuffer);
+
+ return Status;
+}
+
+
+#endif
+
diff --git a/Core/CORE_DXE/FwVolWrite.c b/Core/CORE_DXE/FwVolWrite.c
new file mode 100644
index 0000000..3822f1e
--- /dev/null
+++ b/Core/CORE_DXE/FwVolWrite.c
@@ -0,0 +1,102 @@
+/*++
+
+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:
+
+ FwVolWrite.c
+
+Abstract:
+
+ Implements write firmware file
+
+--*/
+
+#include "FwVolDriver.h"
+
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN EFI_FIRMWARE_VOLUME_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ NumberOfFiles - Number of files.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+#else
+
+EFI_STATUS
+EFIAPI
+FvWriteFile (
+ IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
+ IN UINT32 NumberOfFiles,
+ IN EFI_FV_WRITE_POLICY WritePolicy,
+ IN EFI_FV_WRITE_FILE_DATA *FileData
+ )
+/*++
+
+ Routine Description:
+ Writes one or more files to the firmware volume.
+
+ Arguments:
+ This - Indicates the calling context.
+ NumberOfFiles - Number of files.
+ WritePolicy - WritePolicy indicates the level of reliability for
+ the write in the event of a power failure or other
+ system failure during the write operation.
+ FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA.
+ Each element of FileData[] represents a file to be written.
+
+ Returns:
+ EFI_SUCCESS - Files successfully written to firmware volume
+ EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
+ EFI_DEVICE_ERROR - Device error.
+ EFI_WRITE_PROTECTED - Write protected.
+ EFI_NOT_FOUND - Not found.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_UNSUPPORTED - This function not supported.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+#endif
+
diff --git a/Core/CORE_DXE/GC.c b/Core/CORE_DXE/GC.c
new file mode 100644
index 0000000..c045bda
--- /dev/null
+++ b/Core/CORE_DXE/GC.c
@@ -0,0 +1,2249 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/GC.c 1 11/21/12 4:07a Wesleychen $
+//
+// $Revision: 1 $
+//
+// $Date: 11/21/12 4:07a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/GC.c $
+//
+// 1 11/21/12 4:07a Wesleychen
+// Update rev.45 for EIP105534.
+//
+// 45 11/14/12 5:57p Artems
+// [TAG] EIP105534
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] system hangs during SCT execution
+// [RootCause] Incorrect handling of FORM_FEED escape character in
+// StringToImage function
+// [Solution] Graphics console - added flag to ignore line breaks
+// HiiFont - fixed multiline drawing logic
+// [Files] Gc.c HiiFont.c HiiFontEx.c
+//
+// 44 7/06/12 11:19a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Removed unnecessary traces
+// [Files] Gc.c
+//
+// 43 7/06/12 11:11a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Support for monitor native resolution
+// [Files] GC.c, ConSplit.c, Out.c, Core_Dxe.sdl
+//
+// 42 6/19/12 3:43p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] GC.c file gives build error
+// [RootCause] incorrect pointer used
+// [Solution] changed pointer
+// [Files] gc.c
+//
+// 41 6/19/12 10:36a Artems
+// [TAG] EIP89430
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Cursor position wasn't 0:0 after call to SetMode
+// [RootCause] When console SetMode involved changing of screen
+// resolution
+// screen was cleared by graphics driver, however cursol position wasn't
+// reset
+// [Solution] Added code to resent cursor position when changing screen
+// resolution
+// [Files] Gc.c
+//
+// 40 5/21/12 10:46a Artems
+// [TAG] EIP N/A
+// [Category] New Feature
+// [Description] Added text mode for full screen in native resolution
+// [Files] GC.c
+//
+// 39 4/30/12 3:55p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Modified GraphicsConsole driver to output whole string
+// instead of symbol-by-symbol output
+// [Files] Gc.c, AmiDxeLib.h, EfiLib.c, UefiHiiUtils.c
+//
+// 38 8/12/11 12:22p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 37 8/12/11 11:54a Artems
+// Bug fix: avoid using uninitialized data fields of GC_DATA structure
+//
+// 36 4/12/10 3:25p Artems
+// Fixed bug of drawing cursor when window position is undefined
+//
+// 35 12/17/09 10:22a Artems
+// EIP 29311 added automatic discovering of graphics mode for text mode 0
+//
+// 34 12/03/09 3:13p Felixp
+// TestString is implemented for UEFI 2.1 case.
+//
+// 33 10/09/09 6:06p Felixp
+// UEFI 2.1 - related changes (suppot Framework and UEFI HII).
+//
+// 32 8/28/09 10:25a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 31 7/10/09 6:26p Felixp
+//
+// 30 7/08/09 5:01p Artems
+// Added missing function headers
+//
+// 29 5/22/09 7:27p Felixp
+//
+// 27 10/19/07 9:19a Felixp
+// - Graphic Console driver is updated to support different graphical
+// resolutions (used to be only 800 by 600).
+// - SDL tokens are added in CORE_DXE.sdl to customize list of text
+// modes.
+// - SDL tokens are added in CORE_DXE.sdl to customize color values(EIP:
+// 9854).
+//
+// 26 4/13/07 2:45p Robert
+// Updates for Coding Standard
+//
+// 25 3/30/07 6:13p Felixp
+//
+// 24 3/29/07 10:22a Felixp
+//
+// 23 3/28/07 5:39p Artems
+// Fixed errors reported by SCT test
+//
+// 22 3/13/07 1:48p Artems
+// Fixed bug in 100 x 31 mode
+//
+// 21 3/13/07 10:42a Artems
+//
+// 20 3/09/07 1:40p Artems
+// Clear screen function changed to clear only affected part of screen,
+// not
+// entire screen
+//
+// 19 1/04/07 6:19p Artems
+//
+// 18 12/20/06 10:38a Felixp
+// Graphics Output Protocol support added
+//
+// 17 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 16 8/04/06 4:07p Robert
+//
+// 15 3/13/06 10:07a Felixp
+//
+// 14 9/29/05 2:52p Robert
+// Initialization of Global Variables
+//
+// 13 7/22/05 11:29a Felixp
+// enable cursor in reset function
+//
+// 12 7/20/05 6:50p Felixp
+//
+// 11 7/20/05 6:24p Robert
+// Added check for trying to print a wide character at position 79. This
+// should produce a line feed instead
+//
+// 10 7/20/05 5:31p Robert
+// Data structure for temporary storage of cursor position was only big
+// enough for narrow glyph not for wide glyph
+//
+// 7 3/03/05 12:16p Felixp
+// HII New protocol is default now
+//
+// 6 2/25/05 11:27a Robert
+// Cleared current p[osition buffer before clearing the screen and moving
+// the cursor
+//
+// 5 2/25/05 10:52a Robert
+// Clear screen procedure would leave a block on the screen where the
+// cursor was.
+// We changed the order of the operation so that the cursor moved first
+// and the screen was cleared afterward
+//
+// 4 2/24/05 5:27p Felixp
+// bug fix in DriverBindingStop (Cursor blinking timer was not getting
+// stopped)
+//
+// 3 2/07/05 4:04p Yakovlevs
+//
+// 2 2/04/05 1:47p Felixp
+// warning fixed
+//
+// 1 1/28/05 12:45p Felixp
+//
+// 3 1/06/05 11:22a Robert
+//
+// 2 1/06/05 10:09a Robert
+// Added Blinking Cursor support
+//
+// 1 12/22/04 6:19p Admin
+//
+// 1 12/22/04 6:18p Admin
+//
+// 9 12/16/04 3:40p Felixp
+//
+// 8 12/16/04 2:14p Robert
+// Added TempBlt Buffer init for printing of default string. was
+// forgetting to re-init
+// buffer pointer when doing a carriage return line feed
+//
+// 7 12/16/04 11:39a Robert
+// code optimization for color selection
+//
+// 6 12/15/04 4:02p Robert
+// added checks for memory allocation
+//
+// 5 12/14/04 6:02p Robert
+// added component name support
+//
+// 4 12/14/04 5:28p Robert
+//
+// 3 12/14/04 4:28p Robert
+//
+// 2 11/11/04 5:09p Robert
+//
+// 1 11/11/04 3:28p Robert
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: GC.h
+//
+// Description: Graphics console driver that produces the Simple Text Out
+// interface
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//-----------------------------------------------------------------------------
+
+#include <AmiDxeLib.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/SimpleTextOut.h >
+#include <Protocol/DevicePath.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/EdidActive.h>
+#include <Token.h>
+
+//-----------------------------------------------------------------------------
+
+#define GLYPH_HEIGHT 19
+#define NARROW_GLYPH_WIDTH 8
+#define WIDE_GLYPH_WIDTH 16
+
+#define MODE_ZERO_MIN_HOR_RES NARROW_GLYPH_WIDTH * 80
+#define MODE_ZERO_MIN_VER_RES GLYPH_HEIGHT * 25
+
+#define CURSOR_THICKNESS 3
+#define CURSOR_OFFSET 15 //base line of simple narrow font
+
+#define NULL_CHAR 0x0000
+#define BACKSPACE 0x0008
+#define LINE_FEED 0x000A
+#define FORM_FEED 0x000C
+#define CARRIAGE_RETURN 0x000D
+
+//-----------------------------------------------------------------------------
+// Data Structures
+
+#pragma pack(1)
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: TEXT_MODE
+//
+// Description:
+// This structure represents text mode internal information structure
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// ModeNum INT32 Mode number
+// Col INT32 Max number of columns
+// Row INT32 Max number of rows
+// VideoCol UINT32 Horizontal screen resolution
+// VideoRow UINT32 Vertical screen resolution
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _TEXT_MODE {
+ INT32 ModeNum;
+ INT32 Col;
+ INT32 Row;
+ UINT32 VideoCol; // horizontal pixels
+ UINT32 VideoRow; // vertical pixels
+} TEXT_MODE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: GC_TEXT_MODE
+//
+// Description:
+// This structure represents text mode extended internal information structure
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// ModeNum INT32 Mode number
+// Col INT32 Max number of columns
+// Row INT32 Max number of rows
+// VideoCol UINT32 Horizontal screen resolution
+// VideoRow UINT32 Vertical screen resolution
+// Supported BOOLEAN Flag if this mode supported
+// GraphicsMode UINT32 Correspondent graphics mode
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _GC_TEXT_MODE {
+ INT32 ModeNum;
+ INT32 Col;
+ INT32 Row;
+ UINT32 VideoCol; // horizontal pixels
+ UINT32 VideoRow; // vertical pixels
+ BOOLEAN Supported;
+ UINT32 GraphicsMode;
+} GC_TEXT_MODE;
+
+typedef struct _GC_DATA GC_DATA;
+
+typedef VOID (* AGC_UPDATE_BLT_BUFFER ) (
+ IN GC_DATA *This,
+ IN UINT32 Width,
+ IN UINT32 Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ );
+
+typedef VOID (* AGC_CLEAR_SCREEN) (
+ IN OUT GC_DATA *This
+ );
+
+typedef VOID (* AGC_SCROLL_UP) (
+ IN GC_DATA *This
+ );
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: GC_DATA
+//
+// Description:
+// This structure represents internal information structure for Graphics console
+// driver
+//
+// Fields: Name Type Description
+//----------------------------------------------------------------------------
+// SimpleTextOut EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL Protocol structure
+// Signature UINT32 Unique signature
+// GraphicsOutput EFI_GRAPHICS_OUTPUT_PROTOCOL* Pointer to Gop driver
+// Hii EFI_HII_PROTOCOL* Pointer to HII driver
+// SupportedModes GC_TEXT_MODE* Pointer to supported modes array
+// MaxRows UINT32 Max rows in current mode
+// MaxColumns UINT32 Max columns in current mode
+// DeltaX UINT32 Horizontal indent of text window on screen in pixels
+// DeltaY UINT32 Vertical indent of text window on screen in pixels
+// Cursor EFI_GRAPHICS_OUTPUT_BLT_PIXEL Array for saving cursor image
+// BlinkVisible BOOLEAN Current state of cursor in blinking mode
+// CursorEvent EFI_EVENT Event generated to blink cursor
+// OemUpdateBltBuffer AGC_UPDATE_BLT_BUFFER Custom porting hook
+// OemClearScreen AGC_CLEAR_SCREEN Custom porting hook
+// OemScrollUp AGC_SCROLL_UP Custom porting hook
+//
+// Notes:
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+struct _GC_DATA{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut;
+ UINT32 Signature; //signature (must be 0x54445348 ('GRCS') )
+ UINT32 Version;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_HII_FONT_PROTOCOL *HiiFont;
+ GC_TEXT_MODE *SupportedModes;
+ UINT32 MaxRows; //max number of rows in current mode
+ UINT32 MaxColumns; //max number of columns in current mode
+ UINT32 DeltaX; //horizontal offset in pixels for current text mode
+ UINT32 DeltaY; //vertical offset in pixels for current text mode
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Cursor[NARROW_GLYPH_WIDTH * 3]; //Save cursor image
+ BOOLEAN BlinkVisible; //if true cursor is visible, otherwise - invisible
+ EFI_EVENT CursorEvent;
+ AGC_UPDATE_BLT_BUFFER OemUpdateBltBuffer; //pointer to custom hook
+ AGC_CLEAR_SCREEN OemClearScreen; //pointer to custom hook
+ AGC_SCROLL_UP OemScrollUp; //pointer to custom hook
+};
+#pragma pack()
+
+//-----------------------------------------------------------------------------
+// Function Prototypes
+
+EFI_STATUS DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+EFI_STATUS DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+EFI_STATUS DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer);
+
+//******************** Simple Text Output protocol functions prototypes ***********
+
+EFI_STATUS GCReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification);
+
+EFI_STATUS GCOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String);
+
+EFI_STATUS GCTestString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String);
+
+EFI_STATUS GCQueryMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT UINTN *Col,
+ OUT UINTN *Row);
+
+EFI_STATUS GCSetMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum);
+
+EFI_STATUS GCSetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute);
+
+EFI_STATUS GCClearScreen(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This);
+
+EFI_STATUS GCSetCursorPosition(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row);
+
+EFI_STATUS GCEnableCursor(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible);
+
+//******************** Service functions prototypes ********************************
+
+EFI_STATUS GetColorFromAttribute(
+ IN UINT32 Attribute,
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background);
+
+EFI_STATUS GetGraphicsModeNumber (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
+ IN UINT32 HorRes,
+ IN UINT32 VerRes,
+ OUT UINT32 *ModeNum,
+ IN BOOLEAN ExactMatch,
+ OUT UINT32 *ActualHorRes OPTIONAL,
+ OUT UINT32 *ActualVerRes OPTIONAL );
+
+EFI_STATUS SetupGraphicsDevice(
+ IN GC_DATA *GcData);
+
+VOID EFIAPI BlinkCursorEvent ( IN EFI_EVENT Event, IN VOID *Context );
+
+VOID DrawCursor(
+ IN GC_DATA *GcData,
+ IN BOOLEAN Visible);
+
+VOID ScrollUp(
+ IN GC_DATA *GcData);
+
+VOID SaveCursorImage(
+ IN GC_DATA *GcData);
+
+VOID ShiftCursor(
+ IN GC_DATA *GcData,
+ IN UINT16 Step);
+
+VOID AddChar(
+ IN GC_DATA *GcData,
+ IN CHAR16 Char,
+ IN UINT16 Width
+);
+
+VOID FlushString(
+ IN GC_DATA *GcData
+);
+
+//********************** Hooks prototypes ******************************************
+
+VOID GcUpdateBltBuffer (
+ IN GC_DATA *This, //pointer to internal structure
+ IN UINT32 Width, //width of the buffer in pixels
+ IN UINT32 Height, //height of the buffer in pixels
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer //pointer to BLT buffer to update
+ );
+
+VOID GcInternalClearScreen (
+ IN OUT GC_DATA *This
+ );
+
+//-----------------------------------------------------------------------------
+// Globals
+extern const TEXT_MODE TextModeArray[];
+extern const MaxTextMode;
+extern const EFI_GRAPHICS_OUTPUT_BLT_PIXEL ColorArray[];
+static CHAR16 *TextBuffer = NULL;
+static UINT32 TextBufferSize;
+static UINT32 Position;
+static UINT32 StringWidth;
+static EFI_HANDLE GopHandle;
+
+//-----------------------------------------------------------------------------
+// Protocol implementation
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mGCProtocol =
+ {
+ GCReset,
+ GCOutputString,
+ GCTestString,
+ GCQueryMode,
+ GCSetMode,
+ GCSetAttribute,
+ GCClearScreen,
+ GCSetCursorPosition,
+ GCEnableCursor,
+ NULL
+ };
+
+
+//-----------------------------------------------------------------------------
+// Driver Binding Protocol
+
+EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBindingProtocol = {
+ DriverBindingSupported,
+ DriverBindingStart,
+ DriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+ };
+
+
+//-----------------------------------------------------------------------------
+// Function Definitions
+#ifdef EFI_DEBUG
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+//Driver Name
+static UINT16 *gDriverName=L"AMI Graphic Console Driver";
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: GraphicsConsoleGetControllerName
+//
+// Description:
+// EFI_COMPONENT_NAME_PROTOCOL GetControllerName function
+//
+// Input:
+// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance
+// IN EFI_HANDLE Controller - controller handle
+// IN EFI_HANDLE ChildHandle - child handle
+// IN CHAR8* Language - pointer to language description
+// OUT CHAR16** ControllerName - pointer to store pointer to controller name
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - controller name returned
+// EFI_INVALID_PARAMETER - language undefined
+// EFI_UNSUPPORTED - given language not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS GraphicsConsoleGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Name: GraphicsConsoleGetDriverName
+//
+// Description:
+// EFI_COMPONENT_NAME_PROTOCOL GetDriverName function
+//
+// Input:
+// IN EFI_COMPONENT_NAME_PROTOCOL* This - pointer to protocol instance
+// IN CHAR8* Language - pointer to language description
+// OUT CHAR16** DriverName - pointer to store pointer to driver name
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver name returned
+// EFI_INVALID_PARAMETER - language undefined
+// EFI_UNSUPPORTED - given language not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS GraphicsConsoleGetDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+)
+{
+ //Supports only English
+ if(!Language || !DriverName)
+ return EFI_INVALID_PARAMETER;
+
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH))
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName=gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+//Component Name Protocol
+static EFI_COMPONENT_NAME2_PROTOCOL gGraphicsConsole = {
+ GraphicsConsoleGetDriverName,
+ GraphicsConsoleGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+#endif
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCEntryPoint
+//
+// Description:
+// Installs gGraphicsConsoleDriverBindingProtocol protocol
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - driver image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Driver binding protocol was installed
+//
+// Modified:
+//
+// Referrals: InitAmiLib InstallMultipleProtocolInterfaces
+//
+// Notes:
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ // initiaize the ImageHandle and DriverBindingHandle
+ gGraphicsConsoleDriverBindingProtocol.DriverBindingHandle = NULL;
+ gGraphicsConsoleDriverBindingProtocol.ImageHandle = ImageHandle;
+
+ // Install driver binding protocol here
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &gGraphicsConsoleDriverBindingProtocol.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid, &gGraphicsConsoleDriverBindingProtocol,
+#ifdef EFI_DEBUG
+ &gEfiComponentName2ProtocolGuid, &gGraphicsConsole,
+#endif
+ NULL);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: DriverBindingSupported
+//
+// Description:
+// Checks to see if this driver can be used
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to protocol instance
+// IN EFI_HANDLE Controller - handle of controller to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - Driver supports the Device
+// EFI_NOT_SUPPORTED - Driver cannot support the Device
+//
+// Notes:
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
+ EFI_HII_FONT_PROTOCOL *HiiFont;
+
+ Status = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &GraphicsOutput,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR(Status))
+ return Status;
+ else
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+
+ Status = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ Status = pBS->LocateProtocol ( &gEfiHiiFontProtocolGuid, NULL, &HiiFont);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: DriverBindingStart
+//
+// Description:
+// This function grabs needed protocols and initializes the supported text modes
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to protocol instance
+// IN EFI_HANDLE Controller - handle of controller to install driver on
+// IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - pointer to device path
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - SimpleTextOut Protocol installed
+// EFI_NOT_SUPPORTED - SimpleTextOut Protocol not installed
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_STATUS Status;
+ INT32 StartMode;
+
+#if (CURSOR_BLINK_ENABLE != 0)
+ EFI_STATUS EventStatus;
+#endif
+ GC_DATA *GcData = NULL;
+
+ // Create private data structure and fill with proper data
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GC_DATA), &GcData);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ pBS->CopyMem( &(GcData->SimpleTextOut),
+ &mGCProtocol,
+ sizeof(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL) );
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(SIMPLE_TEXT_OUTPUT_MODE),
+ &(GcData->SimpleTextOut.Mode));
+ if(EFI_ERROR(Status))
+ {
+ pBS->FreePool(GcData);
+ return Status;
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(GC_TEXT_MODE) * MaxTextMode,
+ &(GcData->SupportedModes));
+ if(EFI_ERROR(Status))
+ {
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+ return Status;
+ }
+
+ Status = pBS->OpenProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &(GcData->GraphicsOutput),
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(GcData->SupportedModes);
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+ return Status;
+ }
+
+ // Find the Hii Protocol and attach it to the datastructure
+ Status = pBS->LocateProtocol ( &gEfiHiiFontProtocolGuid, NULL, &(GcData->HiiFont));
+
+ if (EFI_ERROR(Status))
+ {
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+ pBS->FreePool(GcData->SupportedModes);
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+ return EFI_UNSUPPORTED;
+ }
+
+ GopHandle = ControllerHandle;
+ Status = SetupGraphicsDevice(GcData);
+ if(EFI_ERROR(Status))
+ {
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+ pBS->FreePool(GcData->SupportedModes);
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+ return EFI_UNSUPPORTED;
+ }
+
+ //initialize porting hooks and signature
+ GcData->Signature = 0x54445348;
+ GcData->Version = 1;
+ GcData->OemUpdateBltBuffer = GcUpdateBltBuffer;
+ GcData->OemClearScreen = GcInternalClearScreen;
+ GcData->OemScrollUp = NULL;
+ GcData->DeltaX = 0;
+ GcData->DeltaY = 0;
+ GcData->MaxColumns = 0;
+ GcData->MaxRows = 0;
+
+ // Default the cursor blink to the show cursor state
+ GcData->BlinkVisible = TRUE;
+
+
+ (GcData->SimpleTextOut.Mode)->CursorVisible = FALSE; //since initial position of window is undefined we cannot draw cursor yet
+ Status = GCSetAttribute(&(GcData->SimpleTextOut), EFI_BACKGROUND_BLACK | EFI_WHITE); //set default attributes
+ StartMode = ((GcData->SimpleTextOut.Mode)->MaxMode > 3 && START_IN_NATIVE_RESOLUTION) ? 3 : 0;
+ Status = GCSetMode(&(GcData->SimpleTextOut), StartMode);
+ Status = GCEnableCursor(&(GcData->SimpleTextOut), TRUE); //enable cursor
+
+ // install the simple text out protocol
+ Status = pBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &GcData->SimpleTextOut,
+ NULL);
+
+ if (EFI_ERROR(Status))
+ {
+ // close protocols and free allocated memory
+ pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+
+ pBS->FreePool(GcData->SupportedModes);
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+ return EFI_UNSUPPORTED;
+ }
+
+#if (CURSOR_BLINK_ENABLE != 0)
+ EventStatus = pBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ BlinkCursorEvent,
+ &(GcData->SimpleTextOut),
+ &(GcData->CursorEvent)
+ );
+ if (!EFI_ERROR(EventStatus))
+ {
+ pBS->SetTimer(GcData->CursorEvent, TimerPeriodic, 5000000);
+ }
+#endif
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: DriverBindingStop
+//
+// Description:
+// Uninstalls the driver from given ControllerHandle
+//
+// Input:
+// IN EFI_DRIVER_BINDING_PROTOCOL *This - pointer to protocol instance
+// IN EFI_HANDLE ControllerHandle - controller handle to uninstall driver from
+// IN UINTN NumberOfChildren - number of children supported by this driver
+// IN EFI_HANDLE *ChildHandleBuffer - pointer to child handles buffer
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - driver uninstalled from controller
+// EFI_NOT_STARTED - driver was not started
+//
+// Notes:
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+)
+{
+ EFI_STATUS Status;
+ GC_DATA *GcData = NULL;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut = NULL;
+
+ Status = pBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &SimpleTextOut,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status))
+ return EFI_NOT_STARTED;
+
+ Status = pBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+
+ GcData = (GC_DATA *) SimpleTextOut;
+
+ // uninstall the simple text out protocol
+ Status = pBS->UninstallMultipleProtocolInterfaces (
+ ControllerHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &GcData->SimpleTextOut,
+ NULL);
+ if (EFI_ERROR (Status))
+ return Status;
+
+#if (CURSOR_BLINK_ENABLE != 0)
+ pBS->SetTimer(GcData->CursorEvent, TimerCancel, 0);
+ pBS->CloseEvent(GcData->CursorEvent);
+#endif
+
+ Status = pBS->CloseProtocol(
+ ControllerHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+
+ pBS->FreePool(GcData->SupportedModes);
+ pBS->FreePool(GcData->SimpleTextOut.Mode);
+ pBS->FreePool(GcData);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCReset
+//
+// Description:
+// Resets the text output device
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN BOOLEAN ExtendedVerification - indicates that the driver should preform more
+// exhausted verification of the device during reset
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device reset properly
+// EFI_DEVICE_ERROR - Device is not functioning properly
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+)
+{
+ // Set mode clears the screen and sets the cursor back to (0,0) So before
+ // we do that, set the Attribute colors to default
+ This->SetAttribute(This, EFI_BACKGROUND_BLACK | EFI_WHITE);
+// This->SetMode(This, 0);
+ This->ClearScreen(This);
+ This->EnableCursor(This, TRUE);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCOutputString
+//
+// Description:
+// Writes a string to the output device and advances the cursor
+// as necessary.
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN CHAR16 *String - pointer to string to be displayed to the screen
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device reset properly
+// EFI_DEVICE_ERROR - Device reported an Error while outputting a string
+// EFI_UNSUPPORTED - The output device's mode is not currently in a defined state
+// EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the
+// characters in the unicode string could not be rendered and were skipped
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+)
+{
+ EFI_STATUS Status;
+ GC_DATA *GcData;
+ BOOLEAN UnknownGlyph = FALSE;
+ BOOLEAN CursorVisible;
+ EFI_FONT_DISPLAY_INFO FontInfo;
+ EFI_IMAGE_OUTPUT *Glyph = NULL;
+ UINT16 GlyphWidth;
+
+ // find private data structure
+ GcData = (GC_DATA *) This;
+
+ CursorVisible = (GcData->SimpleTextOut.Mode)->CursorVisible;
+ if (CursorVisible)
+ This->EnableCursor(This, FALSE);
+
+ // now loop through the string and display it to the output device
+ while (*String != 0)
+ {
+ switch (*String)
+ {
+ case CARRIAGE_RETURN:
+ FlushString(GcData);
+ This->SetCursorPosition(
+ This,
+ 0,
+ (GcData->SimpleTextOut.Mode)->CursorRow);
+ break;
+
+ case LINE_FEED:
+ case FORM_FEED:
+ FlushString(GcData);
+ if((GcData->SimpleTextOut.Mode)->CursorRow == (GcData->MaxRows - 1))
+ {
+ ScrollUp(GcData);
+ //cursor position not changed, but image under it does - save new image
+ SaveCursorImage(GcData);
+ }
+ else
+ This->SetCursorPosition(
+ This,
+ (GcData->SimpleTextOut.Mode)->CursorColumn,
+ (GcData->SimpleTextOut.Mode)->CursorRow + 1);
+ break;
+
+ case BACKSPACE:
+ FlushString(GcData);
+ if((GcData->SimpleTextOut.Mode)->CursorColumn != 0)
+ This->SetCursorPosition(
+ This,
+ (GcData->SimpleTextOut.Mode)->CursorColumn - 1,
+ (GcData->SimpleTextOut.Mode)->CursorRow);
+ break;
+
+ default:
+ Status = HiiLibGetGlyphWidth(*String, &GlyphWidth);
+ if(Status == EFI_UNSUPPORTED) {
+ Status = GcData->HiiFont->GetGlyph(
+ GcData->HiiFont,
+ *String,
+ &FontInfo,
+ &Glyph,
+ 0);
+ if(EFI_ERROR(Status))
+ return Status;
+ GlyphWidth = Glyph->Width;
+ }
+
+ if(Status == EFI_WARN_UNKNOWN_GLYPH)
+ UnknownGlyph = TRUE;
+
+ AddChar(GcData, *String, GlyphWidth / 8);
+
+ if(Glyph != NULL) {
+ pBS->FreePool(Glyph->Image.Bitmap);
+ pBS->FreePool(Glyph);
+ Glyph = NULL;
+ }
+
+ break; // end of default case
+ }
+
+ String++;
+ }
+ FlushString(GcData);
+ if (CursorVisible)
+ This->EnableCursor(This, TRUE);
+
+ return (UnknownGlyph) ? EFI_WARN_UNKNOWN_GLYPH : EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCTestString
+//
+// Description:
+// Tests to see if the String has the glyphs that correspond to
+// each character in the string
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN CHAR16 *String - pointer to a string that needs to be tested
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - all characters can be drawn
+// EFI_UNSUPPORTED - there are characters that cannot be drawn
+//
+// Notes:
+// Uses the HII function TestString
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCTestString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+)
+{
+ GC_DATA *GcData;
+ EFI_STATUS Status;
+ EFI_IMAGE_OUTPUT *Glyph = NULL;
+
+ // find private data structure
+ GcData = (GC_DATA *) This;
+
+ // now loop through the string and display it to the output device
+ while (*String != 0)
+ {
+ switch (*String)
+ {
+ case CARRIAGE_RETURN: case LINE_FEED: case BACKSPACE:
+ break;
+ default:
+ Status = GcData->HiiFont->GetGlyph(
+ GcData->HiiFont,
+ *String,
+ NULL,
+ &Glyph,
+ 0);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ pBS->FreePool(Glyph->Image.Bitmap);
+ pBS->FreePool(Glyph);
+ if(Status == EFI_WARN_UNKNOWN_GLYPH)
+ return EFI_UNSUPPORTED;
+ Glyph = NULL;
+ break;
+ }
+ String++;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCQueryMode
+//
+// Description:
+// Returns information for an available text mode that the output
+// device supports
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN UINTN ModeNum - The mode to return information on
+// OUT UINTN *Col - the number of columns supported
+// OUT UINTN *Row - the number of rows supported
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - device reset properly
+// EFI_DEVICE_ERROR - Device reported an Error while outputting a string
+// EFI_UNSUPPORTED - The ModeNumber is not supported
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCQueryMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum,
+ OUT UINTN *Col,
+ OUT UINTN *Row
+)
+{
+ GC_DATA *GcData;
+ UINT32 i = 0;
+
+ GcData = (GC_DATA *) This;
+
+ if(ModeNum >= (UINTN)(GcData->SimpleTextOut.Mode)->MaxMode)
+ return EFI_UNSUPPORTED;
+
+ while(GcData->SupportedModes[i].ModeNum != ModeNum)
+ i++;
+
+ if(!GcData->SupportedModes[i].Supported)
+ return EFI_UNSUPPORTED;
+
+ // if the mode is a valid mode, return the data from the array of
+ // for the height and width
+ *Col = GcData->SupportedModes[i].Col;
+ *Row = GcData->SupportedModes[i].Row;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCSetMode
+//
+// Description:
+// Sets the text mode to the requested mode. It checks to see if
+// it is a valid mode
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN UINTN ModeNum - mode number to change to
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - the new mode is valid and has been set
+// EFI_UNSUPPORTED - the new mode is not valid
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GCSetMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNum
+)
+{
+ EFI_STATUS Status;
+ GC_DATA *GcData;
+ BOOLEAN CursorVisible;
+ UINT32 i = 0;
+ UINT32 DeltaX, DeltaY;
+ UINT32 SaveX, SaveY;
+
+ GcData = (GC_DATA *) This;
+
+ if(ModeNum >= (UINTN)(GcData->SimpleTextOut.Mode)->MaxMode)
+ return EFI_UNSUPPORTED;
+
+ while(GcData->SupportedModes[i].ModeNum != ModeNum)
+ i++;
+
+ if(!GcData->SupportedModes[i].Supported)
+ return EFI_UNSUPPORTED;
+
+ SaveX = GcData->DeltaX;
+ SaveY = GcData->DeltaY;
+
+ DeltaX = (GcData->SupportedModes[i].VideoCol -
+ GcData->SupportedModes[i].Col * NARROW_GLYPH_WIDTH) / 2;
+ DeltaY = (GcData->SupportedModes[i].VideoRow -
+ GcData->SupportedModes[i].Row * GLYPH_HEIGHT) / 2;
+
+ //save cursor status and hide it if nesessary
+ CursorVisible = (GcData->SimpleTextOut.Mode)->CursorVisible;
+ if (CursorVisible)
+ This->EnableCursor(This, FALSE);
+
+ if(GcData->GraphicsOutput->Mode->Mode != GcData->SupportedModes[i].GraphicsMode)
+ {
+ Status = GcData->GraphicsOutput->SetMode(GcData->GraphicsOutput,
+ GcData->SupportedModes[i].GraphicsMode);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if(GcData->OemClearScreen != GcInternalClearScreen) { //we have porting hook installed - call it
+ This->ClearScreen(This);
+ } else {
+ /* the screen is cleared by graphics driver when changed graphics mode
+ we just need to reset cursor position */
+ This->Mode->CursorColumn = 0;
+ This->Mode->CursorRow = 0;
+ }
+ }
+ else
+ This->ClearScreen(This); //call clear screen with old values
+
+ if(GcData->DeltaX == SaveX && GcData->DeltaY == SaveY)
+ { //initial position was not changed by porting hook inside C
+ //ClearScreen function
+ GcData->DeltaX = DeltaX;
+ GcData->DeltaY = DeltaY;
+ }
+
+ GcData->MaxColumns = GcData->SupportedModes[i].Col;
+ GcData->MaxRows = GcData->SupportedModes[i].Row;
+ (GcData->SimpleTextOut.Mode)->Mode = GcData->SupportedModes[i].ModeNum;
+
+ // restore cursor at new position
+ if (CursorVisible)
+ This->EnableCursor(This, TRUE);
+
+ if(TextBuffer == NULL || TextBufferSize < GcData->MaxColumns) {
+ if(TextBuffer)
+ pBS->FreePool(TextBuffer);
+
+ Status = pBS->AllocatePool(EfiBootServicesData, (GcData->MaxColumns + 1) * sizeof(CHAR16), &TextBuffer);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ TextBufferSize = GcData->MaxColumns + 1; //additional space for null-terminator
+ Position = 0;
+ StringWidth = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCSetAttribute
+//
+// Description:
+// Sets the foreground color and background color for the screen
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN UINTN Attribute - the attributes to set
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - the attribute was changed successfully
+// EFI_DEVICE_ERROR - The device had an error
+// EFI_UNSUPPORTED - The attribute is not supported
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCSetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+)
+{
+ GC_DATA *GcData;
+
+ GcData = (GC_DATA *) This;
+
+ (GcData->SimpleTextOut.Mode)->Attribute = (INT32) Attribute;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCClearScreen
+//
+// Description:
+// Clears the text screen
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - the screen was cleared
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCClearScreen(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+)
+{
+ GC_DATA *GcData;
+
+ GcData = (GC_DATA *) This;
+
+ GcData->OemClearScreen(GcData);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCSetCursorPosition
+//
+// Description:
+// This function sets the position of the cursor
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN UINTN Column - the new column
+// IN UINTN Row - The new row
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - the cursor position was changed
+// EFI_DEVICE_ERROR - The device had an error
+// EFI_UNSUPPORTED - The device is not in a valid text mode or the
+// cursor position is not valid
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GCSetCursorPosition(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+)
+{
+ GC_DATA *GcData;
+ BOOLEAN CursorVisible;
+
+ GcData = (GC_DATA *) This;
+
+ // check for a valid text mode and check for a valid position
+ // on the screen
+
+ if ( ((UINT32)Column >= GcData->MaxColumns) ||
+ ((UINT32)Row >= GcData->MaxRows) )
+ return EFI_UNSUPPORTED;
+
+
+ //save cursor status and hide it if nesessary
+ CursorVisible = (GcData->SimpleTextOut.Mode)->CursorVisible;
+ if (CursorVisible)
+ This->EnableCursor(This, FALSE);
+
+ (GcData->SimpleTextOut.Mode)->CursorColumn = (INT32)Column;
+ (GcData->SimpleTextOut.Mode)->CursorRow = (INT32)Row;
+
+
+ // restore cursor at new position
+ if (CursorVisible)
+ This->EnableCursor(This, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GCEnableCursor
+//
+// Description:
+// Makes cursor invisible or visible
+//
+// Input:
+// IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This - pointer to the protocol instance
+// IN BOOLEAN Visible - a boolean that if TRUE the cursor will be visible
+// if FALSE the cursor will be invisible
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - the cursor visibility was set correctly
+// EFI_DEVICE_ERROR - The device had an error
+// EFI_UNSUPPORTED - The device does not support visibilty control
+// for the cursor
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GCEnableCursor(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+)
+{
+ GC_DATA *GcData;
+
+ GcData = (GC_DATA *) This;
+
+ // check to see if the we are already set to the same cursor visibility mode
+ if (Visible != (GcData->SimpleTextOut.Mode)->CursorVisible)
+ {
+ (GcData->SimpleTextOut.Mode)->CursorVisible = Visible;
+//if we put cursor back we have to update image under it in order it contains older data
+ if(Visible)
+ SaveCursorImage(GcData);
+
+ DrawCursor(GcData, Visible);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GetColorFromAttribute
+//
+// Description:
+// Turns color attributes into Pixel values
+//
+// Input:
+// IN UINT32 Attribute - The color to set
+// OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground - foreground color
+// OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background - background color
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - valid colors returned
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetColorFromAttribute(
+ IN UINT32 Attribute,
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background
+)
+{
+ UINT8 IndexF;
+ UINT8 IndexB;
+
+ if ((Attribute & 0x80) != 0)
+ return EFI_UNSUPPORTED;
+
+ IndexF = (UINT8)(Attribute & 0x0f);
+ IndexB = (UINT8)((Attribute >> 4) & 0x0f);
+
+ *Foreground = ColorArray[IndexF];
+ *Background = ColorArray[IndexB];
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: DrawCursor
+//
+// Description:
+// This function draws /hides the cursor in the current cursor position
+//
+// Input:
+// IN GC_DATA * GcData - Private data structure for SimpleTextOut interface
+// IN BOOLEAN Visible - if TRUE - draws cursor, if FALSE - hides cursor
+//
+// Output:
+// VOID
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID DrawCursor(
+ IN GC_DATA *GcData,
+ IN BOOLEAN Visible
+)
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
+
+ if(Visible)
+ {
+ Fill = ColorArray[((GcData->SimpleTextOut.Mode)->Attribute & 0x0f)]; //get foreground color
+ GcData->GraphicsOutput->Blt(
+ GcData->GraphicsOutput,
+ &Fill,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ GcData->DeltaX + (GcData->SimpleTextOut.Mode)->CursorColumn * NARROW_GLYPH_WIDTH,
+ GcData->DeltaY + (GcData->SimpleTextOut.Mode)->CursorRow * GLYPH_HEIGHT + CURSOR_OFFSET,
+ NARROW_GLYPH_WIDTH,
+ CURSOR_THICKNESS,
+ 0);
+ }
+ else
+ {
+ GcData->GraphicsOutput->Blt(
+ GcData->GraphicsOutput,
+ GcData->Cursor,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ GcData->DeltaX + (GcData->SimpleTextOut.Mode)->CursorColumn * NARROW_GLYPH_WIDTH,
+ GcData->DeltaY + (GcData->SimpleTextOut.Mode)->CursorRow * GLYPH_HEIGHT + CURSOR_OFFSET,
+ NARROW_GLYPH_WIDTH,
+ CURSOR_THICKNESS,
+ NARROW_GLYPH_WIDTH * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ }
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: BlinkCursorEvent
+//
+// Description:
+// This is the function that makes the cursor blink. A timer event
+// is created that will cause this function to be called
+//
+// Input:
+// IN EFI_EVENT Event - event that was triggered
+// IN VOID *Context - pointer to the event context
+//
+// Output:
+// VOID
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID EFIAPI BlinkCursorEvent(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+)
+{
+ GC_DATA *GcData;
+
+ GcData = (GC_DATA *) Context;
+
+ if (!(GcData->SimpleTextOut.Mode)->CursorVisible)
+ return;
+
+ if (GcData->BlinkVisible)
+ {
+ // remove the cursor from the screen
+ DrawCursor(GcData, FALSE);
+ GcData->BlinkVisible = FALSE;
+ }
+ else
+ {
+ // put cursor back
+ DrawCursor(GcData, TRUE);
+ GcData->BlinkVisible = TRUE;
+ }
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GetGraphicsModeNumber
+//
+// Description:
+// This function returns graphics mode number, correspondend with given
+// horizontal and vertical resolution
+//
+// Input:
+// IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput - pointer to Gop driver
+// IN UINT32 HorRes - required horizontal resolution
+// IN UINT32 VerRes - required vertical resolution
+// OUT UINT32 *ModeNum - returned graphics mode number
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - correct mode number returned
+// EFI_NOT_FOUND - mode number not found for given resolution
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS GetGraphicsModeNumber (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
+ IN UINT32 HorRes,
+ IN UINT32 VerRes,
+ OUT UINT32 *ModeNum,
+ IN BOOLEAN ExactMatch,
+ OUT UINT32 *ActualHorRes OPTIONAL,
+ OUT UINT32 *ActualVerRes OPTIONAL
+)
+{
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Info;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *pInfo = &Info;
+ EFI_STATUS Status;
+ UINTN SizeOfInfo;
+ UINT32 i;
+
+ for(i = 0; i < GraphicsOutput->Mode->MaxMode; i++) {
+ Status = GraphicsOutput->QueryMode(GraphicsOutput, i, &SizeOfInfo, &pInfo);
+
+ if (!EFI_ERROR(Status)) {
+ if (ExactMatch && pInfo->HorizontalResolution == HorRes && pInfo->VerticalResolution == VerRes ) {
+ *ModeNum = i;
+ return Status;
+ }
+ if(!ExactMatch && pInfo->HorizontalResolution >= HorRes && pInfo->VerticalResolution >= VerRes ) {
+ *ModeNum = i;
+ *ActualHorRes = pInfo->HorizontalResolution;
+ *ActualVerRes = pInfo->VerticalResolution;
+ return Status;
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS GetNativeResolution (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
+ OUT UINT32 *ModeNum,
+ OUT UINT32 *ActualHorRes,
+ OUT UINT32 *ActualVerRes
+)
+{
+ EFI_STATUS Status;
+ EFI_EDID_ACTIVE_PROTOCOL *EdidActive;
+ UINT32 HorRes;
+ UINT32 VerRes;
+
+ Status = pBS->HandleProtocol(GopHandle, &gEfiEdidActiveProtocolGuid, &EdidActive);
+ if(EFI_ERROR(Status) || EdidActive->SizeOfEdid == 0)
+ return EFI_UNSUPPORTED;
+
+ if(!((EdidActive->Edid)[24] & BIT01))
+ /* native resolution not supported */
+ return EFI_UNSUPPORTED;
+
+ HorRes = ((((EdidActive->Edid)[0x36 + 4]) & 0xF0) << 4) + (EdidActive->Edid)[0x36 + 2];
+ VerRes = ((((EdidActive->Edid)[0x36 + 7]) & 0xF0) << 4) + (EdidActive->Edid)[0x36 + 5];
+
+ Status = GetGraphicsModeNumber(GraphicsOutput, HorRes, VerRes, ModeNum, TRUE, NULL, NULL);
+ if(!EFI_ERROR(Status)) {
+ *ActualHorRes = HorRes;
+ *ActualVerRes = VerRes;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: SetupGraphicsDevice
+//
+// Description:
+// This function fills array of supported text modes
+//
+// Input:
+// IN GC_DATA *Data - pointer to private protocol data structure
+//
+// Output:
+// EFI_STATUS
+// EFI_SUCCESS - function executed successfully
+// EFI_UNSUPPORTED - no supported modes found
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS SetupGraphicsDevice(
+ IN GC_DATA *GcData
+)
+{
+ EFI_STATUS Status;
+ INT32 i;
+ UINT32 GraphicsModeNumber;
+ INT32 MaxSupportedModes = 1;
+ BOOLEAN DefaultModeNotSupported = FALSE;
+ INT32 ModeZeroIndex;
+ UINT32 HorRes;
+ UINT32 VerRes;
+
+ for(i = 0; i < MaxTextMode; i++) {
+ HorRes = TextModeArray[i].VideoCol;
+ VerRes = TextModeArray[i].VideoRow;
+ if(HorRes == 0 && VerRes == 0) {
+ Status = GetNativeResolution(GcData->GraphicsOutput, &GraphicsModeNumber, &HorRes, &VerRes);
+ } else {
+ /* get mode number with exact resolution */
+ Status = GetGraphicsModeNumber(GcData->GraphicsOutput,
+ HorRes,
+ VerRes,
+ &GraphicsModeNumber,
+ TRUE, NULL, NULL);
+ }
+
+ if(!EFI_ERROR(Status)) {
+ GcData->SupportedModes[i].Supported = TRUE;
+ GcData->SupportedModes[i].GraphicsMode = GraphicsModeNumber;
+ GcData->SupportedModes[i].ModeNum = TextModeArray[i].ModeNum;
+
+ if(TextModeArray[i].Col == 0)
+ GcData->SupportedModes[i].Col = HorRes / NARROW_GLYPH_WIDTH;
+ else
+ GcData->SupportedModes[i].Col = TextModeArray[i].Col;
+
+ if(TextModeArray[i].Row == 0)
+ GcData->SupportedModes[i].Row = VerRes / GLYPH_HEIGHT;
+ else
+ GcData->SupportedModes[i].Row = TextModeArray[i].Row;
+
+ GcData->SupportedModes[i].VideoCol = HorRes;
+ GcData->SupportedModes[i].VideoRow = VerRes;
+
+ MaxSupportedModes = (TextModeArray[i].ModeNum >= MaxSupportedModes) ?
+ TextModeArray[i].ModeNum + 1 : MaxSupportedModes;
+ } else {
+ GcData->SupportedModes[i].Supported = FALSE;
+ GcData->SupportedModes[i].ModeNum = TextModeArray[i].ModeNum;
+
+ if(TextModeArray[i].ModeNum == 0) {
+ ModeZeroIndex = i;
+ DefaultModeNotSupported = TRUE;
+ }
+ }
+ }
+
+ if(DefaultModeNotSupported) {
+ Status = GetGraphicsModeNumber(GcData->GraphicsOutput,
+ MODE_ZERO_MIN_HOR_RES,
+ MODE_ZERO_MIN_VER_RES,
+ &GraphicsModeNumber,
+ FALSE,
+ &(GcData->SupportedModes[ModeZeroIndex].VideoCol),
+ &(GcData->SupportedModes[ModeZeroIndex].VideoRow));
+ if(EFI_ERROR(Status)) {
+ (GcData->SimpleTextOut.Mode)->MaxMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ GcData->SupportedModes[ModeZeroIndex].Supported = TRUE;
+ GcData->SupportedModes[ModeZeroIndex].GraphicsMode = GraphicsModeNumber;
+ GcData->SupportedModes[ModeZeroIndex].Row = 25;
+ GcData->SupportedModes[ModeZeroIndex].Col = 80;
+ }
+
+ (GcData->SimpleTextOut.Mode)->MaxMode = MaxSupportedModes;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: ScrollUp
+//
+// Description:
+// This function scrolls screen one row up and clears bottom row
+//
+// Input:
+// IN GC_DATA *GcData - pointer to private protocol data structure
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ScrollUp(
+ IN GC_DATA *GcData
+)
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
+
+ GcData->GraphicsOutput->Blt(GcData->GraphicsOutput,
+ &Fill,
+ EfiBltVideoToVideo,
+ GcData->DeltaX,
+ GcData->DeltaY + GLYPH_HEIGHT,
+ GcData->DeltaX,
+ GcData->DeltaY,
+ GcData->MaxColumns * NARROW_GLYPH_WIDTH,
+ (GcData->MaxRows - 1) * GLYPH_HEIGHT,
+ 0);
+//clear bottom line
+ Fill = ColorArray[(((GcData->SimpleTextOut.Mode)->Attribute >> 4) & 0xf)];
+ GcData->GraphicsOutput->Blt(GcData->GraphicsOutput,
+ &Fill,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ GcData->DeltaX,
+ GcData->DeltaY + (GcData->MaxRows - 1) * GLYPH_HEIGHT,
+ GcData->MaxColumns * NARROW_GLYPH_WIDTH,
+ GLYPH_HEIGHT,
+ 0);
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: SaveCursorImage
+//
+// Description:
+// This function saves image under cursor to restore, when cursor moves
+//
+// Input:
+// IN GC_DATA *GcData - pointer to private protocol data structure
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID SaveCursorImage(
+ IN GC_DATA *GcData
+)
+{
+ GcData->GraphicsOutput->Blt(
+ GcData->GraphicsOutput,
+ GcData->Cursor,
+ EfiBltVideoToBltBuffer,
+ GcData->DeltaX + (GcData->SimpleTextOut.Mode)->CursorColumn * NARROW_GLYPH_WIDTH,
+ GcData->DeltaY + (GcData->SimpleTextOut.Mode)->CursorRow * GLYPH_HEIGHT + CURSOR_OFFSET,
+ 0,
+ 0,
+ NARROW_GLYPH_WIDTH,
+ CURSOR_THICKNESS,
+ NARROW_GLYPH_WIDTH * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: ShiftCursor
+//
+// Description:
+// This function shifts cursor right to number of columns defined in Step
+// If cursor reaches right edge of the screen it moves one line down, scrolling screen
+// if nesessary
+//
+// Input:
+// IN GC_DATA *GcData - pointer to private protocol data structure
+// IN UINT16 Step - number of columns to shift cursor right
+//
+// Output:
+// VOID
+//
+// Notes:
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ShiftCursor(
+ IN GC_DATA *GcData,
+ IN UINT16 Step
+)
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)GcData;
+
+ if(((GcData->SimpleTextOut.Mode)->CursorColumn + Step) >= (INT32)GcData->MaxColumns)
+ {
+ if((GcData->SimpleTextOut.Mode)->CursorRow == GcData->MaxRows - 1)
+ {
+ ScrollUp(GcData);
+ This->SetCursorPosition(
+ This,
+ 0,
+ (GcData->SimpleTextOut.Mode)->CursorRow);
+ }
+ else
+ {
+ This->SetCursorPosition(
+ This,
+ 0,
+ (GcData->SimpleTextOut.Mode)->CursorRow + 1);
+ }
+ }
+ else
+ {
+ This->SetCursorPosition(
+ This,
+ (GcData->SimpleTextOut.Mode)->CursorColumn + Step,
+ (GcData->SimpleTextOut.Mode)->CursorRow);
+ }
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GcUpdateBltBuffer
+//
+// Description:
+// This function is a porting hook to implement specific action on
+// Blt buffer before put it on screen
+//
+// Input:
+// IN GC_DATA *GcData - pointer to internal structure
+// IN UINT32 Width - width of passed buffer in pixels
+// IN UINT32 Height - height of passed buffer in pixels
+// IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer - pointer to Blt buffer
+// to perform action upon
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID GcUpdateBltBuffer (
+ IN GC_DATA *This,
+ IN UINT32 Width,
+ IN UINT32 Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+)
+{
+ return;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: GcInternalClearScreen
+//
+// Description:
+// This function is a porting hook to implement specific action when
+// clear screen operation is needed
+//
+// Input:
+// IN GC_DATA *This - pointer to private protocol data structure
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID GcInternalClearScreen (
+ IN OUT GC_DATA *This
+)
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
+ EFI_STATUS Status;
+ UINT32 StartX;
+ UINT32 StartY;
+ UINT32 SizeX;
+ UINT32 SizeY;
+
+ if(This->MaxColumns == 0 || This->MaxRows == 0) { //this is the first invocation
+ StartX = 0;
+ StartY = 0;
+ SizeX = This->GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeY = This->GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ StartX = This->DeltaX;
+ StartY = This->DeltaY;
+ SizeX = This->MaxColumns * NARROW_GLYPH_WIDTH;
+ SizeY = This->MaxRows * GLYPH_HEIGHT;
+ }
+
+ Fill = ColorArray[(((This->SimpleTextOut.Mode)->Attribute >> 4) & 0xf)];
+ This->GraphicsOutput->Blt(This->GraphicsOutput,
+ &Fill,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ StartX,
+ StartY,
+ SizeX,
+ SizeY,
+ 0);
+
+ Status = This->SimpleTextOut.SetCursorPosition(&(This->SimpleTextOut), 0, 0);
+ if(EFI_ERROR(Status)) { //on first invocation this failed because MaxRows = MaxCols = 0
+ (This->SimpleTextOut.Mode)->CursorColumn = 0;
+ (This->SimpleTextOut.Mode)->CursorRow = 0;
+ }
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: AddChar
+//
+// Description:
+// This function adds character to internal buffer of ready-to-print string
+//
+// Input:
+// IN GC_DATA *This - pointer to private protocol data structure
+// IN CHAR16 Char - character to add
+// IN UINT16 Width - character width in system font symbols
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AddChar(
+ IN GC_DATA *GcData,
+ IN CHAR16 Char,
+ IN UINT16 Width
+)
+{
+ UINT32 CurrentWidth;
+
+ CurrentWidth = (GcData->SimpleTextOut.Mode)->CursorColumn + StringWidth;
+ if((CurrentWidth + Width) > GcData->MaxColumns) {
+ FlushString(GcData);
+
+ if(Width == 2)
+ ShiftCursor(GcData, 1);
+ }
+
+ TextBuffer[Position] = Char;
+ Position++;
+ StringWidth += Width;
+}
+
+//<AMI_PHDR_START>
+//-----------------------------------------------------------------------------
+// Name: FlushString
+//
+// Description:
+// This function flushes string from internal buffer to screen
+//
+// Input:
+// IN GC_DATA *This - pointer to private protocol data structure
+//
+// Output:
+// VOID
+//
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID FlushString(
+ IN GC_DATA *GcData
+)
+{
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO FontInfo;
+ EFI_IMAGE_OUTPUT *Image = NULL;
+
+ if(Position == 0)
+ return;
+
+//retreive colors
+ GetColorFromAttribute(
+ (GcData->SimpleTextOut.Mode)->Attribute,
+ &FontInfo.ForegroundColor,
+ &FontInfo.BackgroundColor);
+//use system font
+ FontInfo.FontInfoMask = EFI_FONT_INFO_SYS_FONT
+ | EFI_FONT_INFO_SYS_SIZE
+ | EFI_FONT_INFO_SYS_STYLE;
+
+/* put NULL-terminator */
+ TextBuffer[Position] = 0;
+
+ Status = GcData->HiiFont->StringToImage(GcData->HiiFont,
+ EFI_HII_IGNORE_LINE_BREAK,
+ TextBuffer,
+ &FontInfo,
+ &Image,
+ 0, 0, NULL, NULL, NULL);
+
+ GcData->OemUpdateBltBuffer(GcData, Image->Width, Image->Height, Image->Image.Bitmap);
+
+ GcData->GraphicsOutput->Blt(
+ GcData->GraphicsOutput,
+ Image->Image.Bitmap,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ GcData->DeltaX + (GcData->SimpleTextOut.Mode)->CursorColumn * NARROW_GLYPH_WIDTH,
+ GcData->DeltaY + (GcData->SimpleTextOut.Mode)->CursorRow * GLYPH_HEIGHT,
+ Image->Width,
+ Image->Height,
+ Image->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ ShiftCursor(GcData, (Image->Width / 8));
+
+ pBS->FreePool(Image->Image.Bitmap);
+ pBS->FreePool(Image);
+
+ Position = 0;
+ StringWidth = 0;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/GenericSio.c b/Core/CORE_DXE/GenericSio.c
new file mode 100644
index 0000000..af2c433
--- /dev/null
+++ b/Core/CORE_DXE/GenericSio.c
@@ -0,0 +1,3645 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/GenericSio.c 1 7/15/14 9:53p Chienhsieh $
+//
+// $Revision: 1 $Date: 4/04/05 4:37p $
+//
+//*****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/GenericSio.c $
+//
+// 1 7/15/14 9:53p Chienhsieh
+// Update rev.83 for EIP172950, Core updates for UEFI Variable Technical
+// Advisory implement.
+//
+// 83 6/26/14 6:27p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Removed Runtime-Access attribute from internal SIO
+// variables
+// [Files] GenericSio.c
+//
+// 82 2/13/13 5:29p Yakovlevs
+// [TAG] EIP109638
+// [Category] Improvement
+// [Description] Unpexetced behavior in AmiSioStart().
+// Keep calling InitSio instead of breking the execution.
+// [Files] GenericSio.c
+//
+// 81 7/20/12 2:42p Yakovlevs
+// Fixing Reconnect issue in case of multiple SIO.
+//
+// 80 2/09/12 12:40p Yakovlevs
+// [TAG] EIP82016
+// [Category] Bug Fix
+// [RootCause] incorrect _ALG handling in ApplyIoRes() function.
+// [Solution] Change expression in "if" statement to correctly reflect
+// _ALG operation.
+// [Files] GenericSio.c
+//
+// 79 11/08/11 11:15a Yakovlevs
+// [TAG] EIP72716
+// [Category] Improvement
+// [Description] Added Messages, Fixed issues in proposed by AMI China
+// solution.
+// [Files] GenericSio.c
+//
+// 78 10/28/11 6:18p Yakovlevs
+// [TAG] EIP72716
+// [Category] Improvement
+// [Description] Improvement for GenericSio.c
+// [Files] GenericSio.c
+//
+// 77 8/12/11 12:20p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 76 5/06/11 5:08p Yakovlevs
+// Made depencency on PI_SPECIFICATIO_VERSION tolen
+//
+// 75 5/04/11 6:03p Yakovlevs
+// [TAG] EIP 56527
+// [Category] New Feature
+// [Description] AMI_SIO_PROTOCOL was the source for PI 1.2 spec
+// proposal. Will require some minor modification of the interface plus
+// adding EFI_SIO_PROTOCOL Modify() function.
+// [Files] GenericSio.h; GenericSio.c.
+//
+// 74 4/20/11 4:38p Yakovlevs
+// Fixed potential issue in Stop function
+//
+// 73 2/25/11 3:17p Artems
+// EIP 54041: Renamed function AmiSioEntryPoint to GenericSioEntryPoint
+// to avoid dependency from SIO module
+//
+// 72 2/05/11 4:13p Artems
+// Fixed bug with ellow exclamation mark in Windows when keyboard not
+// present
+//
+// 71 2/02/11 12:09p Yakovlevs
+// [TAG] EIPNA
+// [Category] Improvement
+// [Description] Removed printing Remaining Device Path since it can
+// hung the system
+//
+// 67 8/23/10 3:35p Felixp
+// Enhancement(EIP 29307): Part of Runtime Trace support.
+// Code is updated to disable serial port 0 based on valueo f the
+// HideComPort variable.
+//
+// 66 2/04/10 11:51a Oleksiyy
+// Minor Fix
+//
+// 65 1/26/10 11:17a Yakovlevs
+// Bug fix EIP 32086: can't share IRQ when SIO logical devices' IRQ are in
+// share mode.
+//
+// 64 11/09/09 11:10a Krishnakumarg
+// EIP#30571: CloseEvent funtion should be used to kill events in callback
+// function.
+//
+// 63 10/09/09 5:28p Yakovlevs
+// Added Check for NULL pointer returned.
+//
+// 62 10/06/09 6:33p Yakovlevs
+// 1.Fixed some minor issues with the Status returned when Starting
+// Devices.
+// 2. Added Debug Messages Printing Remaining Device Path.
+//
+// 61 8/28/09 10:25a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 60 8/25/09 6:35p Yakovlevs
+// Fixed issue when NONE AUTO IRQ allocation method was used same IRQ may
+// be assigned to the different devices.
+//
+// 59 12/01/08 10:37a Yakovlevs
+// Added isAfterBootScript support. Now SIO initialization routine could
+// save
+// Runtime registers using isAfterBootScript initialization Step.
+//
+// 58 10/31/08 6:11p Yakovlevs
+// Fixed AmiSioStop routine
+//
+// 57 10/13/08 4:50p Yakovlevs
+// Fixed EIP 16394: ACPI removal causes infinite loop in GenericSio.c
+//
+// 56 10/07/08 10:49a Yakovlevs
+// Fixed potential issue when GenericSio build with ACPI_SUPPORT == 0
+//
+// 55 7/03/08 6:34p Yakovlevs
+// Fixed issue when SIO don't have a config mode and Pointers in GSPIO
+// structure were initialized with NULLs, it might hung in infinite loop.
+//
+// 4 6/06/08 10:29a Yakovlevs
+// Take care if SIO_STATUS_VAR might be created by some other drivers
+// Don't break if resources used by SIO IDX/DATA reg can not be clamed.
+//
+// 54 3/25/08 6:10p Yakovlevs
+// Code that creates device's NVRAM variables was acidentally removed.
+// Restoring it.
+//
+// 53 3/12/08 12:44p Felixp
+// Progress/Error codes reporting added
+//
+// 52 2/15/08 5:24p Felixp
+//
+// 51 2/06/08 5:59p Yakovlevs
+//
+// 50 2/06/08 5:19p Yakovlevs
+// Added detection if SIO device is actualy present or not.
+//
+// 48 10/23/07 10:20a Felixp
+// Minor bug fix in AmiSioSupported routine.
+//
+// 47 8/16/07 5:48p Yakovlevs
+//
+// 46 8/16/07 4:50p Yakovlevs
+// Chenges to fix BUILD issues when ACPI_SUPPORT is disabled
+//
+// 45 6/12/07 12:07a Yakovlevs
+// Fixed issue with SIO device with n o resources.
+//
+// 44 5/14/07 7:04p Yakovlevs
+// Changes to support SIO Setup Data Override.
+// Usefull if SIO uses none standard Setup Screens and Data Storage.
+//
+// 42 3/28/07 7:43p Yakovlevs
+// Changes to make use of LibGetDsdt() function
+//
+// 41 1/29/07 4:57p Yakovlevs
+// Fixed bug with IRQ reservation. Devices with no IRQ requests were
+// wrongfully flaged as "Assigned"
+//
+// 40 12/28/06 7:18p Yakovlevs
+//
+// 39 12/26/06 3:16p Yakovlevs
+// Dynamic IRQ Assignment final fix.
+//
+// 38 12/22/06 9:42p Yakovlevs
+// Fixed Dynamic ISA IRQ Allocation
+//
+// 37 11/27/06 3:56a Yakovlevs
+// Set up Notification on VariableWrite protocol to update ISA_IRQ_MASK
+// variable
+//
+// 36 11/27/06 2:20a Yakovlevs
+//
+// 35 11/27/06 12:06a Yakovlevs
+// Changes to sinchronize ISA IRQ allocation here and in CSM
+// NOTE will require to change ISA_IRQ_MASK token HAVE free IRQs as 0
+//
+// 34 10/12/06 9:42a Felixp
+// UEFI2.0 compliance: use CreateReadyToBootEvent instead of CreateEvent
+//
+// 33 9/11/06 11:10a Yakovlevs
+//
+// 32 8/24/06 10:11a Felixp
+// x64 support: warning/error fixes
+//
+// 31 8/04/06 6:10p Yakovlevs
+// Another fix for x64 SioDevStatusVarAttributes changet to UINT32
+//
+// 30 8/04/06 4:06p Yakovlevs
+// Fixed data types for x64 from UINN to UINT32 where needed.
+//
+// 26 5/24/06 11:39a Yakovlevs
+// Fixes to handle shared resources
+//
+// 25 5/23/06 5:08a Felixp
+// converted to the latest ACPI type definitions
+//
+// 24 5/23/06 4:26a Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 23 4/13/06 7:25p Yakovlevs
+// ACPI Disable Support added
+//
+// 22 4/10/06 5:29p Yakovlevs
+// ACPI NO ACPI mode fix.
+// Added Setting LPT device _PRS in NONE ACPI mode based on current LPT
+// MODE (SPP/EPP/ECP) SetLptPrs function.
+// Made Set???Prs functions Public(declared in GenericSio.H).
+//
+// 21 4/10/06 10:47a Yakovlevs
+// Fixed "IsaVenDevId" and "IsaSubVenId" mask usage.
+//
+// 20 4/03/06 3:52p Felixp
+// Major changes in PCI and Super I/O:
+// PCI - Root Bridge Resource Allocation Sepcification support
+// Super I/O - multiple Super I/O support; SIO Setup page added;
+//
+// 19 3/13/06 10:07a Felixp
+//
+// 17 11/23/05 11:26a Felixp
+// dev_status renamed to DEV_STATUS.
+//
+// 16 11/18/05 4:27p Ambikas
+// Creates/modifies SioDevStatusVar (formerly IOST).
+// Dev->Assigned = TRUE/FALSE moved from AssignResources to
+// ApplyResources.
+//
+// 14 11/07/05 3:06p Felixp
+// Unused references to Setup are removed
+//
+// 13 11/07/05 11:54a Ambikas
+//
+// 12 10/26/05 5:00p Ambikas
+//
+// 11 9/29/05 2:51p Robert
+// Initialization of Global Variables
+//
+// 10 5/18/05 11:02a Yakovlevs
+// Changes to Support Generic IO ranges for SIO GPIO, PME and HHM
+//
+// 9 5/12/05 9:34a Yakovlevs
+//
+// 8 5/11/05 3:05p Yakovlevs
+//
+// 7 4/22/05 2:42p Markw
+// Only save boot script once.
+//
+// 6 4/13/05 6:22p Sivagarn
+// - Included proper file header
+// - Fixed the bug in programming SIO config space
+//
+//
+//*****************************************************************************
+
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: GenericSio.c
+//
+// Description: Generic Implementation of the AMI SIO Protocol.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+
+#if SIO_SUPPORT
+//==================================================================================
+
+#include <Efi.h>
+#include <pci.h>
+#include <Protocol\AmiSio.h>
+#include <Protocol\DevicePath.h>
+#include <Protocol\DriverBinding.h>
+#include <Protocol\ComponentName2.h>
+#include <Protocol\PciIo.h>
+#include <Protocol\BootScriptSave.h>
+#include <Protocol\VariableWrite.h>
+#include <Dxe.h>
+#include <AmiDxeLib.h>
+#include <GenericSio.h>
+#include <AcpiRes.h>
+
+#if ACPI_SUPPORT
+//include this if ACPI is Supported
+#include <Acpi20.h>
+#include <Protocol\AcpiSupport.h>
+
+//
+//Some variables we need if ACPI mode is SUPPORTED
+//
+ACPI_HDR *gPDsdt=NULL;
+EFI_EVENT mAcpiEvent=NULL;
+VOID *mAcpiReg;
+EFI_GUID gAcpiSupportGuid=EFI_ACPI_SUPPORT_GUID;
+
+#endif
+
+#define _AND_ &
+#define SIO_MAX_REG 0xFF
+
+//==================================================================================
+//Global Variables
+//==================================================================================
+//extern SPIO_LIST_ITEM SIO_DEVICE_LIST EndOfList; // (EIP7580)-
+//SPIO_LIST_ITEM *gSpioList[] = {SIO_DEVICE_PTR_LIST NULL}; // (EIP7580)-
+BOOLEAN mVarWrite=FALSE;
+extern SPIO_LIST_ITEM *gSpioList[]; // (EIP7580)+
+extern const BOOLEAN HideComPort;
+UINTN gSpioCount=0;
+//global SPIO structure
+GSPIO *gSpio;
+EFI_EVENT mIsaEvent=NULL;
+VOID *mIsaReg;
+
+//--------------------------------------------------------
+
+static EFI_GUID gEfiAmiSioProtocolGuid = EFI_AMI_SIO_PROTOCOL_GUID;
+static EFI_GUID gDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static EFI_GUID gDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+static EFI_GUID gPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID;
+static EFI_GUID gEfiBootScriptSaveGuid = EFI_BOOT_SCRIPT_SAVE_GUID;
+static EFI_GUID gDxeSvcTblGuid = DXE_SERVICES_TABLE_GUID;
+static EFI_GUID gSioDevStatusVarGuid = SIO_DEV_STATUS_VAR_GUID;
+static EFI_GUID gVariableWriteProtocolGuid = EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID;
+
+//DxeServices table Pointer to get access to the GCD Services
+static DXE_SERVICES *gDxeSvcTbl=NULL;
+//Driver Name
+static UINT16 *gDriverName=L"AMI Generic LPC Super I/O Driver";
+//ISA IRQ Mask tells which interrupts we can use for SIO devices
+static UINT16 gAvailableIsaIrq=0;//=ISA_IRQ_MASK;
+// Global variable to report which IRQs are being used in the SIO
+static UINT16 gUsedSioIrq=0;
+// Global variable to report which IRQs are requested/reserved in the SIO
+static UINT16 gReservedIrq=0;
+//ISA DMA Chanal Mask tells which DMA Chanals we can use for SIO devices
+static UINT8 gAvailableDmaChnl=0;//=ISA_DMA_MASK;//0xEF;
+
+static EFI_EVENT gEvtReadyToBoot = NULL;
+
+//==================================================================================
+//Some Function Prototypes to place Entry point at the beginning of this file
+//==================================================================================
+#ifdef EFI_DEBUG
+EFI_STATUS DevicePathToStr(EFI_DEVICE_PATH_PROTOCOL *Path,CHAR8 **Str);
+#endif
+EFI_STATUS EnumerateAll(GSPIO *Spio);
+
+SPIO_DEV* NewDev(SPIO_DEV_LST *SioDevInfo, GSPIO *Owner);
+EFI_STATUS SioSetupData(SPIO_DEV *Dev, BOOLEAN Get);
+
+//==================================================================================
+//Function Prototypes for Driver Binding Protocol Interface
+//==================================================================================
+EFI_STATUS AmiSioSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath);
+
+EFI_STATUS AmiSioStart(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS AmiSioStop(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer);
+
+EFI_STATUS AmiSioComponentNameGetControllerName(IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName );
+
+EFI_STATUS AmiSioComponentNameGetDriverName(IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName);
+
+
+EFI_STATUS AmiSioRegister(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN BOOLEAN ExitCfgMode,
+ IN UINT8 Register,
+ IN OUT UINT8 *Value);
+
+
+EFI_STATUS AmiSioCRS(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Set,
+ IN OUT T_ITEM_LIST **Resources);
+
+EFI_STATUS AmiSioPRS(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Set,
+ IN OUT T_ITEM_LIST **Resources);
+
+EFI_STATUS ReserveIrq(SPIO_DEV *Dev, UINTN Index);
+
+static VOID CallbackReadyToBoot(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+);
+
+
+
+
+EFI_STATUS CreateSioDevStatusVar();
+EFI_STATUS DisableDevInSioDevStatusVar(SPIO_DEV *Dev);
+VOID SaveSioRegs(GSPIO *Sio, SPIO_DEV *Dev, UINT8* InclRegList, UINTN InclRegCount, UINT8 *Buffer);
+VOID DevSelect(SPIO_DEV *Dev);
+
+#if ACPI_SUPPORT
+VOID GetDsdt(IN EFI_EVENT Event, IN VOID *Context);
+#endif
+VOID UpdateIsaMask(IN EFI_EVENT Event, IN VOID *Context);
+//==================================================================================
+//Driver binding protocol instance for AmiSio Driver
+EFI_DRIVER_BINDING_PROTOCOL gAmiSioDriverBinding = {
+ AmiSioSupported, //Supported
+ AmiSioStart, //PciBusDrvStart,
+ AmiSioStop, //PciBusDrvStop,
+ 0x10, //Version,
+ NULL, //Image Handle,
+ NULL //DriverBindingHandle,
+};
+
+//==================================================================================
+//Component Name Protocol Instance
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+EFI_COMPONENT_NAME2_PROTOCOL gAmiSioComponentName = {
+ AmiSioComponentNameGetDriverName,
+ AmiSioComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+
+//==================================================================================
+//Ami SIO Protocol instance
+AMI_SIO_PROTOCOL gAmiSioProtocol = {
+ AmiSioRegister,
+ AmiSioCRS,
+ AmiSioPRS,
+};
+
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+//EFI_SUPERIO_PROTOCOL Functions Forward declaration.
+EFI_STATUS EfiSioRegisterAccess(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN BOOLEAN ExitCfgMode,
+ IN UINT8 Register,
+ IN OUT UINT8 *Value);
+
+
+EFI_STATUS EfiSioGetResourcces(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceList
+);
+
+EFI_STATUS EfiSioSetResources(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN ACPI_RESOURCE_HEADER_PTR ResourceList
+);
+
+EFI_STATUS EfiSioPossibleResources(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceCollection
+);
+
+EFI_STATUS EfiSioModify(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN CONST EFI_SIO_REGISTER_MODIFY *Command,
+ IN UINTN NumberOfCommands
+);
+
+
+EFI_SIO_PROTOCOL gEfiSioProtocol = {
+ EfiSioRegisterAccess,
+ EfiSioGetResourcces,
+ EfiSioSetResources,
+ EfiSioPossibleResources,
+ EfiSioModify,
+};
+#endif
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: UpdateIsaMask
+//
+// Description:
+// This function will update gAvailableIsaIrq &gAvailableDmaChnl value
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+VOID UpdateIsaMask(IN EFI_EVENT Event, IN VOID *Context){
+ EFI_STATUS Status;
+#if ACPI_SUPPORT
+ SPIO_DEV *dev;
+ UINTN j;
+#endif
+ UINTN i;
+//-------------------------
+
+ SIO_TRACE((TRACE_SIO,"GSIO: Variable Write Available!\n"));
+ Status = AmiIsaIrqMask(&gAvailableIsaIrq, TRUE);
+ if(Status==EFI_NOT_FOUND){
+ gAvailableIsaIrq=ISA_IRQ_MASK;
+ SIO_TRACE((TRACE_SIO,"GSIO: Get ISA_IRQ_MASK Status=%r Updating with DEFAULT %X\n",Status, gAvailableIsaIrq));
+ Status = AmiIsaIrqMask(&gAvailableIsaIrq, FALSE);
+ }
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO,"GSIO: ERROR Updating ISA_IRQ_MASK Status=%r\n",Status));
+ gAvailableIsaIrq=ISA_IRQ_MASK;
+ }
+
+ Status = AmiIsaDmaMask(&gAvailableDmaChnl, TRUE);
+ if(Status==EFI_NOT_FOUND){
+ gAvailableDmaChnl=ISA_DMA_MASK;
+ SIO_TRACE((TRACE_SIO,"GSIO: Get ISA_DMA_MASK Status=%r Updating with DEFAULT %X\n",Status, gAvailableDmaChnl));
+ Status=AmiIsaDmaMask(&gAvailableDmaChnl, FALSE);
+ }
+
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO,"GSIO: ERROR Updating ISA_DMA_MASK Status=%r\n",Status));
+ gAvailableDmaChnl=ISA_DMA_MASK;
+ }
+
+ mVarWrite=TRUE;
+
+ //ACPI Support was Installed Before VariableWrite Protocol
+ //So we have collected SIOs _PRS info but did not reserve IRQs yet!
+ SIO_TRACE((TRACE_SIO,"=================================================\n"));
+#if ACPI_SUPPORT
+ if(gPDsdt!=NULL){
+ for(i=0;i<gSpioCount;i++){
+ SIO_TRACE((TRACE_SIO,"GSIO: (ACPI Mode) Enumerate SIO Chip # %d >>>>> \n",i));
+ for(j=0; j<gSpio[i].DeviceCount; j++){
+ dev=gSpio[i].DeviceList[j];
+ if(dev->DeviceInfo->HasSetup) {
+ Status=SioSetupData(dev,TRUE);
+ SIO_TRACE((TRACE_SIO,"GSIO: Get SIO Setup Data. Status=%r\n",Status));
+ ASSERT_EFI_ERROR(Status);
+ }
+ //Taking care of issue 1 in EIP72716
+ if(!dev->DeviceInfo->Implemented) continue;
+ //For Irq reservation it might be a disabled by setup device that shares it's resources
+ //It appears to be a resource owner in such case it will have field Resource consumer filled.
+ if(!dev->NvData.DevEnable) if(dev->ResConsumer==NULL) continue;
+ Status=ReserveIrq(dev, j);
+ SIO_TRACE((TRACE_SIO,"GSIO: Reserve IRQ for SIO[%d].Device[%d] - Status=%r\n",i,j,Status));
+ }
+ SIO_TRACE((TRACE_SIO,"GSIO: (ACPI Mode) EnumerateAll for SIO Chip # %d -> Status=%r\n\n",i, Status));
+ }
+ }
+#else
+ //Set the Possible Resources for each implemented device
+ for(i=0;i<gSpioCount;i++){
+
+ SIO_TRACE((TRACE_SIO,"GSIO: (NO ACPI Mode) Enumerate SIO Chip # %d >>>>> \n",i));
+ Status=EnumerateAll(&gSpio[i]);
+ SIO_TRACE((TRACE_SIO,"GSIO: (NO ACPI Mode) EnumerateAll for SIO Chip # %d -> Status=%r\n\n",i, Status));
+ }
+ //install driver binding protocol here ....
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gAmiSioDriverBinding.DriverBindingHandle,
+ &gDriverBindingProtocolGuid,&gAmiSioDriverBinding,
+ &gEfiComponentName2ProtocolGuid, &gAmiSioComponentName,
+ NULL,NULL);
+
+#endif
+ if(Event) {
+ Status=pBS->CloseEvent(Event);
+ Event=NULL;
+ }
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: GenericSioEntryPoint
+//
+// Description:
+// This is Dxe init Entrypoint
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS AmiSioEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GenericSioEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable )
+{
+ EFI_STATUS Status=0;
+ UINTN i,j;
+ SPIO_DEV *ro=NULL, *dev;//resource owner
+ SPIO_LIST_ITEM *sioli;
+ GSPIO *gspio;
+//--------------------------------------------------------------------
+ InitAmiLib(ImageHandle, SystemTable);
+
+ gDxeSvcTbl=(DXE_SERVICES*)GetEfiConfigurationTable(SystemTable,&gDxeSvcTblGuid);
+
+ //Fill ImgHandle Field in Driver Binding Protocol Structure
+ gAmiSioDriverBinding.ImageHandle=ImageHandle;
+ gAmiSioDriverBinding.DriverBindingHandle=NULL;
+
+
+ //Here we try to find a Variable for IRQ and DMA mask
+ Status = AmiIsaIrqMask(&gAvailableIsaIrq, TRUE);
+ //if Variable does not exists we create one
+ if(EFI_ERROR(Status)){
+ if(Status==EFI_NOT_FOUND) {
+ gAvailableIsaIrq=ISA_IRQ_MASK;
+ Status=AmiIsaIrqMask(&gAvailableIsaIrq, FALSE);
+ if(EFI_ERROR(Status))SIO_TRACE((TRACE_SIO, "GSIO: Unexpected Error while creating Var ISA_IRQ_MASK. STATUS = %r\n", Status));
+ else mVarWrite=TRUE;
+ } else SIO_TRACE((TRACE_SIO, "GSIO: Unexpected Error while getting var ISA_IRQ_MASK. STATUS = %r\n", Status));
+ } else mVarWrite=TRUE;
+
+ Status = AmiIsaDmaMask(&gAvailableDmaChnl, TRUE);
+ //if Variable does not exists we create one
+ if(EFI_ERROR(Status)){
+ if(Status==EFI_NOT_FOUND) {
+ gAvailableDmaChnl=ISA_DMA_MASK;
+ Status=AmiIsaDmaMask(&gAvailableDmaChnl, FALSE);
+ if(EFI_ERROR(Status))SIO_TRACE((TRACE_SIO, "GSIO: Unexpected Error while creating Var ISA_DMA_MASK. STATUS = %r\n", Status));
+ } else SIO_TRACE((TRACE_SIO, "GSIO: Unexpected Error while getting var ISA_DMA_MASK. STATUS = %r\n", Status));
+ }
+
+ //count number of SPIO_LIST_ITEMs in the system
+ for(i=0; ;i++){
+ sioli=gSpioList[i];
+ if(!sioli)break;
+ gSpioCount++;
+ };
+
+
+ gSpio=MallocZ(sizeof(GSPIO)*gSpioCount);
+ ASSERT(gSpio);
+ if(!gSpio) return EFI_OUT_OF_RESOURCES;
+ //init basic GSPIO structure and collect information about spio devices
+ //gSpio.Indx=SIO_CONFIG_INDEX;
+ //gSpio.Data=SIO_CONFIG_DATA;
+ for(j=0; j<gSpioCount; j++){
+ sioli=gSpioList[j];
+ gspio=&gSpio[j];
+
+ //gspio->ImageHandle=ImageHandle;
+ gspio->InCfgMode=FALSE;
+ gspio->SpioInfo=sioli;
+
+ gspio->GlobalCfgDump=MallocZ(sioli->GlobalInclRegCount);
+ ASSERT(gspio->GlobalCfgDump);
+ if(!gspio->GlobalCfgDump) return EFI_OUT_OF_RESOURCES;
+
+ //Save Initial (PowerOn after PEI Init) state of SIO Global registers (reg 0.. 2F usually)
+ SaveSioRegs(gspio, NULL, gspio->SpioInfo->GlobalIncludeReg,sioli->GlobalInclRegCount,gspio->GlobalCfgDump);
+
+ gspio->DeviceList=MallocZ(sizeof(VOID*)*sioli->DevCount);
+ ASSERT(gspio->DeviceList);
+ if(!gspio->DeviceList)return EFI_OUT_OF_RESOURCES;
+
+ for(i=0;i<sioli->DevCount;i++){
+ dev=NewDev(&sioli->SioDevList[i],gspio);
+ ASSERT(dev);
+ if(!dev) return EFI_OUT_OF_RESOURCES;
+ gspio->DeviceList[i]=dev;
+
+ if(dev->DeviceInfo->Flags && ro){
+ dev->ResOwner=ro;
+ ro->ResConsumer=dev;
+ }
+ //very first device in a list can't be a device with shared resources
+ if(!i && dev->DeviceInfo->Flags) return EFI_INVALID_PARAMETER;
+ ro=dev;
+ }
+ }
+#if ACPI_SUPPORT
+ GetDsdt(NULL,NULL);
+ //if no ACPISupport Protocol Available yet - install Notify Event
+ if(!gPDsdt) {
+ Status=RegisterProtocolCallback(&gAcpiSupportGuid,GetDsdt,NULL,&mAcpiEvent,&mAcpiReg);
+ SIO_TRACE((TRACE_SIO,"GSIO: Locate ACPISupport FAILURE. Installing Callback (%r)\n", Status));
+ } else SIO_TRACE((TRACE_SIO,"GSIO: Locate ACPISupport SUCCESS \n"));
+
+#endif
+ //Set the Callback for Variable Write
+ if(!mVarWrite){
+ Status=RegisterProtocolCallback(&gVariableWriteProtocolGuid,UpdateIsaMask,NULL,&mIsaEvent,&mIsaReg);
+ SIO_TRACE((TRACE_SIO,"GSIO: Variable Write FAILURE. Installing Callback (%r)\n", Status));
+ }
+
+
+ //Create event for boot script
+ Status = CreateReadyToBootEvent(
+ TPL_NOTIFY,
+ CallbackReadyToBoot,
+ NULL,
+ &gEvtReadyToBoot
+ );
+ ASSERT_EFI_ERROR(Status);
+
+
+ //Here we can set up notification events if needed
+
+
+
+ //------------------------------------
+ return Status;
+
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: GetDsdt
+//
+// Description:
+// This function will get gPDsdt address
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+#if ACPI_SUPPORT
+VOID GetDsdt(IN EFI_EVENT Event, IN VOID *Context){
+ UINTN i;
+ EFI_STATUS Status=0;
+ EFI_PHYSICAL_ADDRESS dsdtaddr=0;
+//-----------------------------
+
+ Status=LibGetDsdt(&dsdtaddr,EFI_ACPI_TABLE_VERSION_ALL);
+ if(EFI_ERROR(Status)) return;
+ else gPDsdt=(ACPI_HDR*)dsdtaddr;
+
+ if(!gPDsdt) SIO_TRACE((TRACE_SIO,"GSIO: FAIL to locate DSDT Table -> %r\n", Status));
+ else {
+ for(i=0;i<gSpioCount;i++){
+ Status=EnumerateAll(&gSpio[i]);
+ SIO_TRACE((TRACE_SIO,"GSIO: EnumerateAll (ACPI Mode) for SIO Chip # %d returned %r\n",i, Status));
+ }
+ //install driver binding protocol here ....
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &gAmiSioDriverBinding.DriverBindingHandle,
+ &gDriverBindingProtocolGuid,&gAmiSioDriverBinding,
+ &gEfiComponentName2ProtocolGuid, &gAmiSioComponentName,
+ NULL,NULL);
+ }
+
+ if(Event) Status=pBS->CloseEvent(Event);
+}
+#endif
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: SioSetupData
+//
+// Description:
+//This Function will get NonVolatile SioDevice Setup Var if it is not present it will create it
+//or set Volatile SioDevice Setup Var parameter Get is the Action Selector
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS SioSetupData(SPIO_DEV *Dev, BOOLEAN Get){
+ EFI_STATUS Status=0,s2=0;
+ EFI_GUID ssg={0x560bf58a, 0x1e0d, 0x4d7e, 0x95, 0x3f, 0x29, 0x80, 0xa2, 0x61, 0xe0, 0x31};
+ UINT16 *vname;
+ UINTN vs;
+//---------------------------------
+ vname=MallocZ(sizeof(UINT16)*14);
+ ASSERT(vname);
+ if(!vname)return EFI_OUT_OF_RESOURCES;
+
+ if(Get){
+ //Get Non Volatile Variable for this Device
+ //the variable name is spels as "PNP"+Dev->PnpId+'_'+Dev_Uid"
+ Swprintf(&vname[0],L"PNP%04X_%X_NV",Dev->DeviceInfo->PnpId,Dev->DeviceInfo->UID);
+ vs=sizeof(SIO_DEV_NV_DATA);
+ Status = pRS->GetVariable(vname, &ssg, NULL, &vs, &Dev->NvData);
+ //upon creation Dev->NvData Dev->VlData was initialized with '0'
+ if(EFI_ERROR(Status)){
+ if(Status!=EFI_NOT_FOUND) return Status;
+ Dev->NvData.DevEnable=1; //Default is Enabled
+ }
+ //If SIO setup screens NOT using Generic SIO Setup Screens
+ //we need to get setup options from the global SETUP_DATA var.
+ if (Dev->DeviceInfo->InitRoutine!=NULL) Status=Dev->DeviceInfo->InitRoutine(&Dev->AmiSio,NULL,isGetSetupData);
+ } else {
+ //Set Volatile var
+ Swprintf(&vname[0],L"PNP%04X_%X_VV",Dev->DeviceInfo->PnpId,Dev->DeviceInfo->UID);
+ vs=sizeof(SIO_DEV_V_DATA);
+ s2 = pRS->SetVariable(vname, &ssg, EFI_VARIABLE_BOOTSERVICE_ACCESS, vs, &Dev->VlData);
+ //Set NonVolatile var
+ Swprintf(&vname[0],L"PNP%04X_%X_NV",Dev->DeviceInfo->PnpId,Dev->DeviceInfo->UID);
+ vs=sizeof(SIO_DEV_NV_DATA);
+ Status = pRS->SetVariable(vname, &ssg, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, vs, &Dev->NvData);
+ }
+ return (s2|Status);
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: NewDev
+//
+// Description:
+//Allocates memory for SPIO device Instance and init basic fields
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+SPIO_DEV* NewDev(SPIO_DEV_LST *SioDevInfo, GSPIO *Owner/*, UINTN BufferSize*/){
+ SPIO_DEV *dev;
+//---------------------------
+ dev=MallocZ(sizeof(SPIO_DEV));
+ if(!dev) return NULL;
+
+ //Fill out SPIO_DEV struct;
+ dev->Owner=Owner;
+ dev->DeviceInfo=SioDevInfo;
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+ dev->EfiSioData.Owner=dev;
+#endif
+
+ //dev->Type=SioDevInfo->Type;
+ //dev->LDN=SioDevInfo->LDN;
+ dev->EisaId.UID=SioDevInfo->UID;
+ dev->EisaId.HID=PNP_HID(SioDevInfo->PnpId);
+
+ //Get Device Setup Data Volatile and NonVolatile
+ //Can't use variable services now because it is NOT_AVAILABLE_YET
+ dev->VlData.DevImplemented=SioDevInfo->Implemented;
+ dev->NvData.DevEnable=SioDevInfo->Implemented;
+ //dev->Implemented=
+ //dev->Flags=SioDevInfo->Flags;
+ //dev->InitRoutine=SioDevInfo->InitRoutine;
+ dev->LocalCfgDump=MallocZ(Owner->SpioInfo->LocalInclRegCount);
+ if(!dev->LocalCfgDump){
+ pBS->FreePool(dev);
+ dev=NULL;
+ } else {
+ SaveSioRegs(Owner, dev, Owner->SpioInfo->LocalIncludeReg, Owner->SpioInfo->LocalInclRegCount, dev->LocalCfgDump);
+ Owner->DeviceCount++;
+ }
+ return dev;
+}
+
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: SioCfgMode
+//
+// Description:
+//Routine to transit Sio in/from Config Mode.
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+VOID SioCfgMode(GSPIO *Sio, BOOLEAN Enter)
+{
+ UINTN i;
+ SPIO_SCRIPT_LST *sl;
+//---------------------------------
+ if(Enter)sl=Sio->SpioInfo->EnterCfgMode;
+ else sl=Sio->SpioInfo->ExitCfgMode;
+
+ if(sl==NULL) return;
+
+ for (i=0; i<sl->InstrCount; i++){
+ switch (sl->OpType){
+ case cfgNone:
+ break;
+ case cfgByteSeq:
+ {
+ SPIO_SCRIPT *Instr = (SPIO_SCRIPT*) sl->Instruction[0];
+ SPIO_SCRIPT *cmd = &Instr[i];
+ UINT16 reg;
+ UINT8 dat;
+ //------------------------
+ if(cmd->IdxDat)reg=Sio->SpioInfo->SioIndex;
+ else reg=Sio->SpioInfo->SioData;
+
+ if (cmd->WrRd) IoWrite8(reg,cmd->Value);
+ else {
+ UINTN c=100000;
+ dat=IoRead8(reg);
+ while( c && dat!=cmd->Value ) {
+ dat=IoRead8(reg);
+ c--;
+ }
+ }
+ break;
+ }
+ case cfgRoutine:
+ {
+ SPIO_ROUTINE rt=(SPIO_ROUTINE)sl->Instruction[i];
+ rt;
+ }
+ break;
+ default: return;
+ }//switch
+ }//for
+ Sio->InCfgMode=Enter;
+ return;
+}
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: SaveSioRegs
+//
+// Description:
+//Save Sio reg contents in the buffer
+//if Dev is NULL it did not selects the device
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+VOID SaveSioRegs(GSPIO *Sio, SPIO_DEV *Dev, UINT8 *InclRegsList, UINTN InclRegCount, UINT8 *Buffer){
+ UINTN i;
+ UINT8 r;
+//------------------------
+ if(!Sio->InCfgMode) SioCfgMode(Sio, TRUE);
+ if(Dev)DevSelect(Dev);
+ for(i=0; i<InclRegCount; i++){
+ r=InclRegsList[i];
+ IoWrite8(Sio->SpioInfo->SioIndex,r);
+ Buffer[i]=IoRead8(Sio->SpioInfo->SioData);
+ }
+ SioCfgMode(Sio, FALSE);
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: GetPrsFromTable
+//
+// Description:
+//This function will get _PRS from mSpioDeviceList[] table
+//"Index" is the entry # in mSpioDeviceList[]
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS GetPrsFromTable(SPIO_DEV* Dev, UINTN Index){
+ SPIO_DEV_LST *de=Dev->DeviceInfo;//device entry
+ //IO1 IO2 IRQ1 IRQ2 DMA1 DMA2
+ VOID* *rl[6]= {NULL,NULL,NULL,NULL,NULL,NULL}; //resource list
+ UINT16 i=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+ SIO_TRACE((TRACE_SIO,"Dev[%d]: PRS Tbl=> \n", Index));
+
+ if (Dev->DeviceInfo->Flags==SIO_NO_RES){
+ SIO_TRACE((TRACE_SIO," Device NOT USING Resources FLAGS=0x%X\n", Dev->DeviceInfo->Flags));
+ return EFI_SUCCESS;
+ }
+
+ i = de->ResLen[0] | de->ResLen[1] | de->IrqMask[0] | de->IrqMask[1] | de->DmaMask[0] | de->DmaMask[1];
+ if(!i){
+ SIO_TRACE((TRACE_SIO,"Entry is Empty! Check 'YourSioName_DevLst' table.\n"));
+ return EFI_NOT_FOUND;
+ }
+ //Resource base and length 1
+ rl[0]=ASLM_FixedIO(de->ResBase[0],de->ResLen[0]);
+ if(!rl[0]) return EFI_OUT_OF_RESOURCES;
+ SIO_TRACE((TRACE_SIO,"IO1.B=%X; IO1.L=%X; ",de->ResBase[0],de->ResLen[0]));
+
+ //Resource base and length 2
+ rl[1]=ASLM_FixedIO(de->ResBase[1],de->ResLen[1]);
+ if(!rl[1]) return EFI_OUT_OF_RESOURCES;
+ SIO_TRACE((TRACE_SIO,"IO2.B=%X IO2.L=%X; ",de->ResBase[1],de->ResLen[1]));
+
+ //IRQ settings 1
+ rl[2]=ASLM_IRQNoFlags(1,0);
+ if(!rl[2]) return EFI_OUT_OF_RESOURCES;
+ ((ASLR_IRQNoFlags*)rl[2])->_INT=de->IrqMask[0];
+ SIO_TRACE((TRACE_SIO,"IRQ1=%X; ",de->IrqMask[0]));
+
+ //IRQ settings 2
+
+ rl[3]=ASLM_IRQNoFlags(1,0);
+ if(!rl[3]) return EFI_OUT_OF_RESOURCES;
+ ((ASLR_IRQNoFlags*)rl[3])->_INT=de->IrqMask[1];
+ SIO_TRACE((TRACE_SIO,"IRQ2=%X; ",de->IrqMask[1]));
+ //DMA settings 1
+ rl[4]=ASLM_DMA(1,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 0);
+ if(!rl[4]) return EFI_OUT_OF_RESOURCES;
+ ((ASLR_DMA*)rl[4])->_DMA=de->DmaMask[0];
+ SIO_TRACE((TRACE_SIO,"DMA1=%X; ",de->DmaMask[0]));
+ //DMA settings 2
+ rl[5]=ASLM_DMA(1,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 0);
+ if(!rl[5]) return EFI_OUT_OF_RESOURCES;
+ ((ASLR_DMA*)rl[5])->_DMA=de->DmaMask[1];
+ SIO_TRACE((TRACE_SIO,"DMA2=%X;",de->DmaMask[1]));
+
+ SIO_TRACE((TRACE_SIO,"\n"));
+
+ //Now Create _PRS Object for this device with best priorities
+ dl=ASLM_StartDependentFn(6,0,0,rl[0],rl[1],rl[2],rl[3],rl[4],rl[5]);
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+
+ SIO_TRACE((TRACE_SIO,"DepFn=%X,ItemCount=%d; ",(EFI_ASL_DepFn*)dl,((EFI_ASL_DepFn*)dl)->DepRes.ItemCount));
+ for(i=0;i<6;i++) {
+ SIO_TRACE((TRACE_SIO,"Item[%d]=%X ",i,((EFI_ASL_DepFn*)dl)->DepRes.Items[i]));
+ }
+ SIO_TRACE((TRACE_SIO,"\n <= Dev[%d]: PRS Tbl End \n",Index));
+ return AppendItemLst(&Dev->PRS, dl);
+}
+
+
+#if (! ACPI_SUPPORT)
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: Set***Prs
+//
+// Description:
+//These functions will collect _PRS from legacy concept,it is not support ACPI
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+//Create Possible Resource Settings Buffer for FDC
+EFI_STATUS SetFdcPrs(SPIO_DEV *Dev)
+{
+ EFI_STATUS Status;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+// StartDependentFn(0, 0) {
+// IO(Decode16, 0x3F0, 0x3F0, 1, 8)
+// IRQNoFlags() {6}
+// DMA(Compatibility, NotBusMaster, Transfer8) {2}
+// } //Same as
+// sdc_cnt,pComp,pPerf
+ dl=ASLM_StartDependentFn(4, 0, 0,
+ ASLM_FixedIO(0x3F0, 6), //0x3F6 port reserved for Legacy IDE
+ ASLM_FixedIO(0x3F7, 1),
+ ASLM_IRQNoFlags(1,6),
+ ASLM_DMA(1,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 2)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+// StartDependentFnNoPri() {
+// IO(Decode16, 0x3F0, 0x3F0, 1, 6)
+// IRQNoFlags() {3,4,5,6,7,10,11,12}
+// DMA(Compatibility, NotBusMaster, Transfer8) {0,1,2,3}
+// } same as
+ dl=ASLM_StartDependentFnNoPri(4,
+ ASLM_FixedIO(0x3F0,6), //0x3F6 port reserved for Legacy IDE
+ ASLM_FixedIO(0x3F7,1),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12),
+ ASLM_DMA(4,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8,0,1,2,3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri( 3,
+ ASLM_FixedIO(0x370, 6), //0x376 port reserved for Legacy IDE
+ ASLM_FixedIO(0x377, 1),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12),
+ ASLM_DMA(4,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8,0,1,2,3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+
+ Status=AppendItemLst(&Dev->PRS, dl);
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: Set***Prs
+//
+// Description:
+//These functions will collect _PRS from legacy concept,it is not support ACPI
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+//Create Possible Resource Settings Buffer for PS2 Keyboard
+EFI_STATUS SetPs2kPrs(SPIO_DEV *Dev)
+{
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+ if(Dev->DeviceInfo->Type==dsPS2CM){
+ //Just in case overwrite porting settings
+ //Dev->DeviceInfo->Flags=SIO_SHR_ALL;
+ dl=ASLM_StartDependentFnNoPri( 4,
+ ASLM_FixedIO(0x60, 1),
+ ASLM_FixedIO(0x64, 1),
+ ASLM_IRQNoFlags(1, 1),
+ ASLM_IRQNoFlags(1, 12) );
+ } else {
+ Dev->DeviceInfo->Flags=SIO_SHR_IO;
+ dl=ASLM_StartDependentFnNoPri( 3,
+ ASLM_FixedIO(0x60, 1),
+ ASLM_FixedIO(0x64, 1),
+ ASLM_IRQNoFlags(1, 1) );
+ }
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+
+ Status=AppendItemLst(&Dev->PRS, dl);
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: Set***Prs
+//
+// Description:
+//These functions will collect _PRS from legacy concept,it is not support ACPI
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+//Create Possible Resource Settings Buffer for PS2 mouse
+EFI_STATUS SetPs2mPrs(SPIO_DEV *Dev)
+{
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+ if(Dev->DeviceInfo->Type==dsPS2CM){
+ //Just in case overwrite porting settings
+ //Dev->DeviceInfo->Flags=SIO_SHR_ALL;
+ dl=ASLM_StartDependentFnNoPri( 4,
+ ASLM_FixedIO(0x60, 1),
+ ASLM_FixedIO(0x64, 1),
+ ASLM_IRQNoFlags(1, 1),
+ ASLM_IRQNoFlags(1, 12) );
+ } else {
+ Dev->DeviceInfo->Flags=SIO_SHR_IO;
+ dl=ASLM_StartDependentFnNoPri( 3,
+ ASLM_FixedIO(0x60, 1),
+ ASLM_FixedIO(0x64, 1),
+ ASLM_IRQNoFlags(1, 12) );
+ }
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+
+ Status=AppendItemLst(&Dev->PRS, dl);
+ return Status;
+}
+
+EFI_STATUS SetUartPrs(SPIO_DEV *Dev){
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+ switch(Dev->EisaId.UID){
+ case 0 : //priority for Com 1;
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x3F8, 8),
+ ASLM_IRQNoFlags(1,4)
+ );
+ break;
+ case 1 : //priority for Com 2;
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x2F8, 8),
+ ASLM_IRQNoFlags(1,3)
+ );
+ break;
+ case 2 : //priority for Com 3;
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x3E8, 8),
+ ASLM_IRQNoFlags(1,11)
+ );
+ break;
+
+ case 3 : //priority for Com 4;
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x2E8, 8),
+ ASLM_IRQNoFlags(1,10)
+ );
+ break;
+ }
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ //the rest of resource combinations will go with No Priority
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x3F8, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x2F8, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x3E8, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x2E8, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: Set***Prs
+//
+// Description:
+//These functions will collect _PRS from legacy concept,it is not support ACPI
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS SetLptPrs(SPIO_DEV *Dev, BOOLEAN UseDma){
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+
+ switch(Dev->EisaId.UID){
+ case 0 : //priority for LPT 1;
+ if(UseDma){
+ dl=ASLM_StartDependentFn(4, 0,0,
+ ASLM_FixedIO(0x378, 8),
+ ASLM_FixedIO(0x778, 8),
+ ASLM_IRQNoFlags(1,7),
+ ASLM_DMA(1,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 3)
+ );
+ } else {
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x378, 8),
+ ASLM_IRQNoFlags(1,7)
+ );
+ }
+ break;
+ case 1 : //priority for LPT 2;
+ if(UseDma){
+ dl=ASLM_StartDependentFn(4, 0,0,
+ ASLM_FixedIO(0x278, 8),
+ ASLM_FixedIO(0x678, 8),
+ ASLM_IRQNoFlags(1,5),
+ ASLM_DMA(1,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1)
+ );
+ } else {
+ dl=ASLM_StartDependentFn(2, 0,0,
+ ASLM_FixedIO(0x278, 8),
+ ASLM_IRQNoFlags(1,5)
+ );
+ }
+ break;
+ }
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ //the rest of resource combinations will go with No Priority
+ if(UseDma){
+ //IRQ
+ dl=ASLM_StartDependentFnNoPri(4,
+ ASLM_FixedIO(0x378, 8),
+ ASLM_FixedIO(0x778, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(4,
+ ASLM_FixedIO(0x278, 8),
+ ASLM_FixedIO(0x678, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(4,
+ ASLM_FixedIO(0x3BC, 4),
+ ASLM_FixedIO(0x7BC, 4),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+ //No IRQ
+ dl=ASLM_StartDependentFnNoPri(3,
+ ASLM_FixedIO(0x378, 8),
+ ASLM_FixedIO(0x778, 8),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(3,
+ ASLM_FixedIO(0x278, 8),
+ ASLM_FixedIO(0x678, 8),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(3,
+ ASLM_FixedIO(0x3BC, 4),
+ ASLM_FixedIO(0x7BC, 4),
+ ASLM_DMA(2,ASLV_Compatibility, ASLV_NotBusMaster, ASLV_Transfer8, 1, 3)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+
+ } else { //No DMA MODE
+ //IRQ
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x378, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x278, 8),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x3BC, 4),
+ ASLM_IRQNoFlags(7, 3,4,5,6,10,11,12)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+ //No IRQ
+ dl=ASLM_StartDependentFnNoPri(1,
+ ASLM_FixedIO(0x378, 8)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(1,
+ ASLM_FixedIO(0x278, 8)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(1,
+ ASLM_FixedIO(0x3BC, 4)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ }
+ return Status;
+}
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+// Procedure: Set***Prs
+//
+// Description:
+//These functions will collect _PRS from legacy concept,it is not support ACPI
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS SetGamePrs(SPIO_DEV *Dev){
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+
+ dl=ASLM_StartDependentFnNoPri(1,
+ ASLM_FixedIO(0x200, 8)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+
+ return Status;
+}
+
+EFI_STATUS SetMpu401Prs(SPIO_DEV *Dev){
+ EFI_STATUS Status=0;
+ T_ITEM_LIST *dl;
+//-----------------------------------
+
+
+ //the rest of resource combinations will go with No Priority
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x300, 2),
+ ASLM_IRQNoFlags(5, 5,7,9,10,11)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ if(EFI_ERROR(Status)) return Status;
+
+ dl=ASLM_StartDependentFnNoPri(2,
+ ASLM_FixedIO(0x330, 2),
+ ASLM_IRQNoFlags(5, 5,7,9,10,11)
+ );
+ if(!dl) return EFI_OUT_OF_RESOURCES;
+ Status=AppendItemLst(&Dev->PRS, dl);
+ return Status;
+}
+
+#else
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: GetPrsFromAml
+//
+// Description:
+//These function will collect _PRS from Aml code which support ACPI
+//"Index" is the entry # in mSpioDeviceList[]
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+EFI_STATUS GetPrsFromAml(SPIO_DEV* Dev, UINT8 *PrsName ,UINTN Index){
+ EFI_STATUS Status=0;
+ SPIO_DEV_LST *de=Dev->DeviceInfo;
+ ASL_OBJ_INFO obj={0}, prs={0};
+ UINT8 bc, *p, *prsb;
+ UINTN pl, bl;
+ ASLRF_S_HDR *rd;
+ EFI_ASL_DepFn *pdf=NULL;
+//---------------------------
+ if(de->AslName[0]==0) return GetPrsFromTable(Dev, Index);
+
+ Status=GetAslObj((UINT8*)gPDsdt+sizeof(ACPI_HDR),gPDsdt->Length-sizeof(ACPI_HDR)-1,&de->AslName[0],otDevice,&obj);
+ if(EFI_ERROR(Status)) {
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> Failed to Locate ASL Object %s in DSDT at %08X\n",Index,&de->AslName[0], gPDsdt));
+ return GetPrsFromTable(Dev, Index);
+ }
+
+ //it must be _PRS name Object there
+ if(!PrsName) Status = GetAslObj(obj.DataStart,obj.Length,"_PRS",otName,&prs);
+ else Status = GetAslObj(obj.DataStart,obj.Length,PrsName,otName,&prs);
+ if(EFI_ERROR(Status)) {
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> Failed to Locate _PRS Object in %s Object Scope at %08X\n",Index, &de->AslName[0], obj.Object));
+ return GetPrsFromTable(Dev, Index);
+ }
+
+ p=prs.DataStart;
+ if(*p==AML_OP_BUFFER){
+ pl=GetPackageLen((AML_PACKAGE_LBYTE*)(p+1),&bc);
+ //_PRS Name must be a "Buffer"
+ //DefBuffer := BufferOp PkgLength BufferSize ByteList
+ //BufferSize := TermArg=>Integer
+ //DataObject := (in our case ComputationalData) | DefPackage | DefVarPackage
+ p+=bc+2;
+ switch(*p){
+ case AML_PR_BYTE:
+ bl=*(p+1);
+ prsb=p+2;
+ break;
+ case AML_PR_WORD:
+ bl=*((UINT16*)(p+1));
+ prsb=p+3;
+ break;
+ case AML_PR_DWORD:
+ bl=*((UINT32*)(p+1));
+ prsb=p+5;
+ break;
+ default: return EFI_INVALID_PARAMETER;
+ }
+ //Now Copy _PRS Buffer into new location and fill SIO.PRS T_ITEM_LIST
+ p=Malloc(bl);
+ if(!p) return EFI_OUT_OF_RESOURCES;
+ MemCpy(p,prsb,bl);
+ //Parse AML _PRS Buffer
+ rd=(ASLRF_S_HDR*)p;
+ prsb=p;
+ while(rd->Name!=ASLV_SR_EndTag){
+ //------------------------------
+ if(rd->Name==ASLV_RT_StartDependentFn){
+ //Add this item to device PRS list
+ pdf=MallocZ(sizeof(EFI_ASL_DepFn));
+ if(!pdf) return EFI_OUT_OF_RESOURCES;
+ pdf->DepFn=rd;
+ Status=AppendItemLst(&Dev->PRS, (VOID*)pdf);
+ if(EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+ } else {
+ Status=AppendItemLst(&pdf->DepRes,rd);
+ if(EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+ }
+ //advance to the next descriptor in _PRS ResourceTemplate
+ p+=sizeof(ASLRF_S_HDR)+rd->Length; //rd->Length => Byte length excluding length of the header
+ //It could be only IO, FixedIO, IRQ and DMA types of resources so it is small resource descriptor type
+ if((prsb+bl)<p){ //check if we still inside _PRS buffer or went out..
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> Failed to Locate EndDepFn in _PRS buffer of %s Object at %08X\n",Index ,&de->AslName[0],prs.Object));
+ return GetPrsFromTable(Dev, Index);
+ }
+ rd=(ASLRF_S_HDR*)p;
+ if(rd->Name==ASLV_RT_EndDependentFn) break;
+ } //while
+ if(!Dev->PRS.ItemCount){
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> Failed to Locate StartDepFn in _PRS buffer of %s Object at %08X\n",Index,&de->AslName[0],prs.Object));
+ return GetPrsFromTable(Dev, Index);
+ }
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> Collected %d DepFunc Items of %s Object \n",Index,Dev->PRS.ItemCount,&de->AslName[0]));
+ } else {
+ SIO_TRACE((TRACE_SIO,"SIO[%d]: Aml=> _PRS Object of %s Object is not a Buffer Type at %08X\n",Index,&de->AslName[0],prs.Object));
+ return GetPrsFromTable(Dev, Index);
+ }
+ return Status;
+}
+
+#endif
+
+
+// <AMI_PHDR_START>
+//-------------------------------------------------------------------------
+//
+// Procedure: EnumerateAll
+//
+// Description:
+//This Routine fill PRS property of the Implemented devices
+//
+// Input:
+//
+// Output:
+//
+// Notes:
+//-------------------------------------------------------------------------
+// <AMI_PHDR_END>
+static EFI_STATUS EnumerateAll(GSPIO *Spio){
+ UINTN i;
+ SPIO_DEV *dev;
+ EFI_STATUS Status=0;
+//-------------------
+ for(i=0; i<Spio->DeviceCount; i++){
+ dev=Spio->DeviceList[i];
+ SIO_TRACE((TRACE_SIO,"=================================================\n"));
+ SIO_TRACE((TRACE_SIO,"+> SIO[%d]; Implemented=%d; FLAGS=%X;", i, dev->DeviceInfo->Implemented, dev->DeviceInfo->Flags));
+ //Taking care of issue 1 in EIP72716
+ if (!dev->DeviceInfo->Implemented){
+ SIO_TRACE((TRACE_SIO,"<-\n"));
+ continue;
+ }
+ if(dev->DeviceInfo->HasSetup)Status=SioSetupData(dev,TRUE);
+ //For Irq reservation it might be a disabled by setup device that shares it's resources
+ //It appears to be a resource owner in such case it will have field Resource consumer filled.
+ SIO_TRACE((TRACE_SIO," Enabled=%d; SHR_RES=%d. <-\n",dev->NvData.DevEnable, (dev->ResConsumer!=NULL)));
+ if(!dev->NvData.DevEnable) if(dev->ResConsumer==NULL) continue;
+//if we don't have any ACPI support we still have to prowide _PRS for SIO devices
+//#ifndef rather DEBUG
+#if (!ACPI_SUPPORT)
+ switch (dev->DeviceInfo->Type){
+ case dsFDC: Status=SetFdcPrs(dev);
+ break;
+ case dsPS2CK:
+ case dsPS2K: Status=SetPs2kPrs(dev);
+ break;
+ case dsPS2CM:
+ case dsPS2M: Status=SetPs2mPrs(dev);
+ break;
+ case dsUART: Status=SetUartPrs(dev);
+ break;
+ case dsLPT: Status=SetLptPrs(dev,FALSE);
+ break;
+ case dsGAME: Status=SetGamePrs(dev);
+ break;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ case dsSB16: //Status=SetSb16Prs(dev);
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ break;
+ case dsMPU401: Status=SetMpu401Prs(dev);
+ break;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ case dsFmSynth: //fill this
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ break;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ case dsCIR:
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ break;
+// case dsGPIO: Status=SetGpioPrs(dev);
+// break;
+// case dsHwMon: Status=SetHhmPrs(dev);
+// break;
+// case dsPME: Status=SetPmePrs(dev);
+// break;
+// case dsACPI:
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// break;
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+// Add to SIO_DEV_TYPE devices which may reside in SIO
+// Fill this switch with implementatio for missed SIO_DEV_TYPE
+//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO
+ default : Status=GetPrsFromTable(dev, i);
+ }//switch
+#else
+ Status=GetPrsFromAml(dev,NULL,i);
+#endif
+ //if ACPI Support was Installed after VariableWrite Protocol
+ //we will reserve ISA IRQs now!
+ //if not we will do it when VariableWrite Event signalled.
+ if(EFI_ERROR(Status)) {
+ //check if device has a custom routine to get PRS settings.
+ if(dev->DeviceInfo->InitRoutine){
+ Status=dev->DeviceInfo->InitRoutine(&dev->AmiSio,NULL,isPrsSelect);
+ SIO_TRACE((TRACE_SIO,"GSIO: DevInitRoutine(isPrsSelect) - Status=%r.\n", Status));
+ }
+ Status=EFI_SUCCESS;
+ }
+ if(mVarWrite){
+ Status=ReserveIrq(dev, i);
+ SIO_TRACE((TRACE_SIO,"GSIO: Reserve IRQ for SIO.Device[%d] - Status=%r\n",i,Status));
+ }
+ SIO_TRACE((TRACE_SIO,"-------------------------------------------------\n\n"));
+ }//for
+
+ return Status;
+}
+
+
+
+//==================================================================================
+//Functions for Driver Binding Protocol Interface
+//==================================================================================
+EFI_STATUS AmiSioComponentNameGetControllerName(IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS AmiSioComponentNameGetDriverName(IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName)
+{
+ //Supports only English
+ if(!Language || !DriverName) return EFI_INVALID_PARAMETER;
+
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH))
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName=gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+
+//==============================================================================
+EFI_STATUS CheckSioDevicePath(EFI_DEVICE_PATH_PROTOCOL *DevicePath)
+{
+ // Check if the RemainingDevicePath is valid
+ if (DevicePath->Type!=ACPI_DEVICE_PATH ||
+ DevicePath->SubType!= ACPI_DP ||
+ NODE_LENGTH(DevicePath) != ACPI_DEVICE_PATH_LENGTH )
+ return EFI_UNSUPPORTED;
+ else return EFI_SUCCESS;
+}
+
+
+//==================================================================================
+//Functions for Driver Binding Protocol Interface
+//==================================================================================
+EFI_STATUS AmiSioSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ UINT8 cc[4];
+ UINTN sn,bn,dn,fn,i;
+ UINT32 sid, id;
+ BOOLEAN AlreadyStarted = FALSE, m;
+ GSPIO *spio;
+//---------------------------------------------------------
+ //Check if it is valid Device Path
+ if(RemainingDevicePath){
+ Status=CheckSioDevicePath(RemainingDevicePath);
+ if(EFI_ERROR(Status))return Status;
+ }
+
+ //Check if it is real hardware or some virtual driver faking hardware
+ //the real hardware has to have DevPath Protocol on it's HAndle
+ Status=pBS->OpenProtocol( Controller, &gDevicePathProtocolGuid,
+ (VOID **)&ParentDevicePath, This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_BY_DRIVER );
+ if ( EFI_ERROR(Status) && Status!= EFI_ALREADY_STARTED) return Status;
+
+ pBS->CloseProtocol(Controller,&gDevicePathProtocolGuid,This->DriverBindingHandle, Controller);
+
+ //This is real hardware we are dealing with but it has to be PCI2LPC/ISA bridge
+ //So check if it has PCI IO Protocol on its Handle
+ Status=pBS->OpenProtocol( Controller,&gPciIoProtocolGuid,(VOID **)&PciIo,
+ This->DriverBindingHandle,Controller,EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ if(Status==EFI_ALREADY_STARTED){
+ AlreadyStarted = TRUE;
+ Status=pBS->OpenProtocol(Controller,&gPciIoProtocolGuid,(VOID **)&PciIo,
+ This->DriverBindingHandle,Controller,EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if(EFI_ERROR(Status))return Status;
+
+ //PciIo Protocol present.
+ //Read PCI Class Code Reg to find out which Device is that
+ Status=PciIo->Pci.Read(PciIo,EfiPciIoWidthUint32,PCI_REV_ID_OFFSET,1,&cc);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //VendorID DevId
+ Status=PciIo->Pci.Read(PciIo,EfiPciIoWidthUint32,0,1,&id);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //Subsystem VendorID
+ Status=PciIo->Pci.Read(PciIo,EfiPciIoWidthUint32,0x2c,1,&sid);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+ //Controller PCI Location
+ Status=PciIo->GetLocation(PciIo,&sn, &bn, &dn, &fn);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //try to select right SIO device bridge for this sio
+ Status=EFI_UNSUPPORTED;
+ for(i=0; i<gSpioCount; i++){
+ spio=&gSpio[i];
+
+ //if(spio->SpioInfo->IsaVenDevId==-1)m=TRUE;
+ //else
+ m=((spio->SpioInfo->IsaVenDevId & id) == id );
+ if(!m) continue;
+
+ //if(spio->SpioInfo->IsaSubVenId==-1)m=TRUE;
+ //else
+ m=((spio->SpioInfo->IsaSubVenId & sid) == sid);
+ if(!m) continue;
+
+ if(spio->SpioInfo->IsaBusNo==(UINT8)-1)m=TRUE;
+ else m=(spio->SpioInfo->IsaBusNo==bn);
+ if(!m) continue;
+
+ if(spio->SpioInfo->IsaDevNo==(UINT8)-1)m=TRUE;
+ else m=(spio->SpioInfo->IsaDevNo==dn);
+ if(!m) continue;
+
+ if(spio->SpioInfo->IsaFuncNo==(UINT8)-1)m=TRUE;
+ else m=(spio->SpioInfo->IsaFuncNo==fn);
+ if(!m) continue;
+
+ //if we are here: The controller PCi properties matched the SPIO_LIST ITEM table
+ spio->SupportedHandle=Controller;
+ Status=EFI_SUCCESS;
+ }
+ //Check it has to be LPC/ISA bridge who hosts SIO
+ //byte0=RevId;byte1=BaseClassCode;byte2=SubClassCode;byte3=ProgrInterface
+ if( Status && ( cc[3]==PCI_CL_BRIDGE && cc[2]==PCI_CL_BRIDGE_SCL_ISA && cc[1]==0 )) Status=EFI_SUCCESS;
+
+ if (!AlreadyStarted) pBS->CloseProtocol(Controller,&gPciIoProtocolGuid,This->DriverBindingHandle,Controller);
+
+ return Status;
+}
+
+
+//==============================================================================================
+//This Function Assumes SIO in Config Mode and LD has been selected
+VOID SioRegister(SPIO_DEV *Dev, BOOLEAN Write, UINT8 Reg, UINT8 *Val){
+ IoWrite8(Dev->Owner->SpioInfo->SioIndex,Reg);
+ if(Write)IoWrite8(Dev->Owner->SpioInfo->SioData,*Val);
+ else *Val=IoRead8(Dev->Owner->SpioInfo->SioData);
+}
+
+//==============================================================================================
+//this Function Assumes SIO is in Config Mode
+VOID DevSelect(SPIO_DEV *Dev){
+//----------------
+ IoWrite8(Dev->Owner->SpioInfo->SioIndex,Dev->Owner->SpioInfo->DevSel);
+ IoWrite8(Dev->Owner->SpioInfo->SioData,Dev->DeviceInfo->LDN);
+}
+
+
+//==============================================================================================
+//this function will probe SIO device if something "alive" there.
+//this Function Assumes SIO is in Config Mode
+EFI_STATUS CheckDevicePresent(SPIO_DEV *Dev){
+ UINT8 val;
+//---------------
+ DevSelect(Dev);
+ val=IoRead8(Dev->Owner->SpioInfo->SioData);
+ //it must read Device's LDN
+ if(Dev->DeviceInfo->LDN!=val) return EFI_NO_RESPONSE;
+ else return EFI_SUCCESS;
+}
+
+//==============================================================================================
+//this Function Assumes SIO is in Config Mode
+VOID DevEnable(SPIO_DEV *Dev, BOOLEAN Enable){
+ UINT8 v = Enable ? Dev->Owner->SpioInfo->ActivVal : Dev->Owner->SpioInfo->DeactVal;
+//----------------
+ DevSelect(Dev);
+ IoWrite8(Dev->Owner->SpioInfo->SioIndex,Dev->Owner->SpioInfo->Activate);
+ IoWrite8(Dev->Owner->SpioInfo->SioData,v);
+// Dev->Active=Enable;
+}
+
+
+//selects resource by number
+T_ITEM_LIST *GetNumResources(T_ITEM_LIST *DfLst, UINT8 *num ){
+// ASLRF_S_HDR *hdr;
+ EFI_ASL_DepFn *df=NULL;//*dfnp,*dfwp;
+//-------------------------------------
+
+ if(*num<DfLst->ItemCount){
+// hdr=(ASLRF_S_HDR*)DfLst->Items[*num];
+// if(hdr->Length==1) {
+// dfwp=(EFI_ASL_DepFn*)hdr;
+ df=(EFI_ASL_DepFn*)DfLst->Items[*num];
+ return &df->DepRes;
+// }
+// if(hdr->Length==0) {
+// dfnp=(EFI_ASL_DepFnNoPri*)hdr;
+// return &dfnp->DepRes;
+// }
+// *num=(UINT8)DfLst->ItemCount;
+// return NULL;
+ } else *num=(UINT8)DfLst->ItemCount;
+ return NULL;
+}
+
+
+//Selects Resources by Priotity settings.
+//UINT8 *num number of descriptors in Dependency list;
+T_ITEM_LIST *GetPriResources(T_ITEM_LIST *DfLst, UINT8 cmp, UINT8 prf){
+ UINTN i;
+ ASLRF_S_HDR *hdr;
+ EFI_ASL_DepFn *df;
+//-------------------------------------
+ for(i=0; i<DfLst->ItemCount; i++){
+ df=DfLst->Items[i];
+ hdr=(ASLRF_S_HDR*)df->DepFn;
+ if(hdr->Length==1) {
+ if(((ASLR_StartDependentFn*)df->DepFn)->_PRI._CMP==cmp ||
+ ((ASLR_StartDependentFn*)df->DepFn)->_PRI._PRF==prf)
+ return &df->DepRes;
+ }
+ }
+ return NULL;
+}
+
+
+//Implement Function which(like GCD) will controll DMA resource assignment
+BOOLEAN AssignDma(UINT8 ChNo, ASLRF_DFLAGS *Flags){
+ UINT16 dma;
+ UINTN sz=sizeof(gAvailableIsaIrq);
+ EFI_STATUS Status;
+//------------------------
+ Status=AmiIsaDmaMask(&gAvailableDmaChnl, TRUE);
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO, "Unexpected Error while refreshing Var ISA_DMA_MASK. STATUS = %r\n", Status));
+ return FALSE;
+ }
+
+ SIO_TRACE((TRACE_SIO, "Updating ISA_DMA_MASK = 0x%X", gAvailableIsaIrq));
+
+ dma=(1<<ChNo);
+ if((~gAvailableDmaChnl) & dma){
+ gAvailableDmaChnl |= dma;
+ Status=AmiIsaDmaMask(&gAvailableDmaChnl,FALSE);
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO, "Unexpected Error. STATUS = %r\n", Status));
+ return FALSE;
+ }
+ SIO_TRACE((TRACE_SIO, " with 0x%X for Chnl %d\n", dma, ChNo ));
+ return TRUE;
+ } else return FALSE;
+}
+
+//Implement Function which(like GCD) will controll IRQ resource assignment
+BOOLEAN AssignIrq(UINT8 IrqNo, ASLRF_IFLAGS *Flags){
+ UINT16 irq;
+ EFI_STATUS Status;
+//------------------------
+
+ Status=AmiIsaIrqMask(&gAvailableIsaIrq, TRUE);
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO, "Unexpected Error while refreshing Var ISA_IRQ_MASK. STATUS = %r\n", Status));
+ return FALSE;
+ }
+
+ SIO_TRACE((TRACE_SIO, "Updating ISA_IRQ_MASK = 0x%X", gAvailableIsaIrq));
+
+ irq=(1<<IrqNo);
+ if((~gAvailableIsaIrq) & irq){
+ gAvailableIsaIrq |= irq;
+ gReservedIrq |= irq;
+ Status=AmiIsaIrqMask(&gAvailableIsaIrq,FALSE);
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO, "Unexpected Error. STATUS = %r\n", Status));
+ return FALSE;
+ }
+ SIO_TRACE((TRACE_SIO, " with 0x%X for IRQ# %d ISA_IRQ_MASK=%X gReservedIrq=%X\n", irq, IrqNo,gAvailableIsaIrq, gReservedIrq));
+ return TRUE;
+ } else return FALSE;
+}
+
+BOOLEAN AssignIo(UINT16 *Base, UINT8 Len, UINT8 Aln){
+ EFI_PHYSICAL_ADDRESS addr=*Base;
+ EFI_STATUS Status;
+//------------------------------------
+
+ if(!gDxeSvcTbl) return FALSE;
+ Status=gDxeSvcTbl->AllocateIoSpace(EfiGcdAllocateAddress,//IN EFI_GCD_ALLOCATE_TYPE AllocateType,
+ EfiGcdIoTypeIo,//IN EFI_GCD_IO_TYPE GcdIoType,
+ Aln,//IN UINTN Alignment,
+ Len, //IN UINT64 Length,
+ &addr,//IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ gAmiSioDriverBinding.ImageHandle,// IN EFI_HANDLE ImageHandle,
+ NULL //IN EFI_HANDLE DeviceHandle OPTIONAL
+ );
+ SIO_TRACE((TRACE_SIO,"AssignIo Status=%r,*Base=%x, addr=%x, Len=%x, Aln=%x\n",Status,*Base,addr,Len,Aln));
+ if(EFI_ERROR(Status)||((*Base)!=(UINT16)addr))return FALSE;
+ *Base=(UINT16)addr;
+ return TRUE;
+}
+
+
+
+VOID *ApplyDmaRes(ASLRF_S_HDR* Hdr, SPIO_DEV* Dev,UINT8 ResNo ){
+ UINT8 dmac=0;
+ UINT8 i;
+ BOOLEAN a=FALSE;
+ ASLR_DMA *dmar=(ASLR_DMA*)Hdr, *rd=NULL;
+//--------------------------
+
+ rd=ASLM_DMA(1,dmar->Flags._TYP,dmar->Flags._BM, dmar->Flags._SIZ,0);
+ if(rd==NULL) return rd;
+
+ rd->_DMA=0;
+
+ //Don't need to run all this if we got an empty descriptor
+ if(!dmar->_DMA) return rd;
+
+ for(i=0; i<8; i++){
+ dmac=dmar->_DMA&(1<<i);
+ if(dmac){
+ if((Dev->DeviceInfo->Flags&SIO_SHR_DMA2) && ResNo ) a=TRUE;
+ else {
+ if((Dev->DeviceInfo->Flags&SIO_SHR_DMA1) && !ResNo) a=TRUE;
+ else a=AssignDma(i, &dmar->Flags);
+ }
+ if(a){
+ UINT8 r;
+ //---------------------
+ if(ResNo){
+ r=Dev->Owner->SpioInfo->Dma2;
+ Dev->VlData.DevDma2=i;
+ } else {
+ r=Dev->Owner->SpioInfo->Dma1;
+ Dev->VlData.DevDma1=i;
+ }
+ SioRegister(Dev,TRUE,r,&i);
+
+ rd->_DMA=i;
+ return rd;
+ }
+ }
+ } //for
+ if(rd)pBS->FreePool(rd);
+ return NULL;
+}
+
+
+
+VOID *ApplyIrqRes(ASLRF_S_HDR* Hdr, SPIO_DEV* Dev, UINT8 ResNo, BOOLEAN IrqReserve){
+ UINT16 irqm=0;
+ UINT8 i;
+ BOOLEAN a=FALSE;
+ ASLR_IRQ *irqr=(ASLR_IRQ*)Hdr, *rd=NULL;
+//--------------------------
+
+ SIO_TRACE((TRACE_SIO,"GSIO: Device's IRQ_MSK=%X; ",irqr->_INT));
+
+ //Create Irq resource descriptors based on request
+ if(!IrqReserve){
+ if(irqr->Hdr.Length==3) rd=ASLM_IRQ(1,irqr->Flags._LL,irqr->Flags._HE, irqr->Flags._SHR,0);
+ else rd=ASLM_IRQNoFlags(1,0);
+ rd->_INT=0;
+ }
+
+ //Don't need to run all this if we got an empty descriptor
+ if(!irqr->_INT) {
+ SIO_TRACE((TRACE_SIO," - Device's has empty IRQ descriptor.rd=NULL\n"));
+ return rd;
+ }
+
+
+ for(i=0; i<16; i++){
+ irqm=irqr->_INT&(1<<i);
+ if(irqm ){
+ //if we hit IRQ that was used already by some other SIO device, just skip it.
+ if((IrqReserve == FALSE) && ((irqm & gUsedSioIrq ) && (!(Dev->DeviceInfo->Flags & SIO_SHR_IRQ)) ) ) continue;
+
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IRQ2) && ResNo ) a=TRUE;
+ else {
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IRQ1) && !ResNo) a=TRUE;
+ else {
+ if(!Dev->IrqReserved) a=AssignIrq(i, &irqr->Flags);
+ else a=TRUE;
+ }
+ }
+ if(a){
+ UINT8 r;
+ //---------------------
+ if(IrqReserve) {
+ Dev->IrqReserved=TRUE;
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyIrq - IrqReserve=%d. Returning NULL!",IrqReserve));
+ return NULL;
+ }
+ //Special Case for PS2C (PS2K and PS2M in the same LD)
+ if(Dev->DeviceInfo->Type==dsPS2CM) ResNo=1;
+ if(ResNo){
+ r=Dev->Owner->SpioInfo->Irq2;
+ Dev->VlData.DevIrq2=i;
+ } else {
+ r=Dev->Owner->SpioInfo->Irq1;
+ Dev->VlData.DevIrq1=i;
+ }
+ gUsedSioIrq |= irqm;
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyIrq - dsPS2CM=%d; Register=0x%X; Value=0x%X; gUsedSioIrq=0x%X.",
+ (Dev->DeviceInfo->Type==dsPS2CM), r, i, gUsedSioIrq));
+ SioRegister(Dev,TRUE,r,&i);
+ rd->_INT=i;
+ return rd;
+ }
+ }
+ }
+ if(rd)pBS->FreePool(rd);
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyIrq - can't find resources. Returning NULL!"));
+ return NULL;
+}
+
+VOID *ApplyFixedIoRes(ASLRF_S_HDR* Hdr, SPIO_DEV* Dev, UINT8 ResNo){
+ BOOLEAN a=FALSE;
+ ASLR_FixedIO *iord=(ASLR_FixedIO*)Hdr, *rd=NULL;
+//--------------------------
+ rd=ASLM_FixedIO(iord->_BAS, iord->_LEN);
+
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyFixedIO BAS=%x, LEN=%x, rd=%x; ",iord->_BAS,iord->_LEN,rd));
+
+ //Don't need to run all this if we got an empty descriptor
+ if(!iord->_LEN) {
+ SIO_TRACE((TRACE_SIO,"Empty Descriptor\n"));
+ return rd;
+ }
+
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IO2) && ResNo ) a=TRUE;
+ else {
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IO1) && !ResNo) a=TRUE;
+ else a=AssignIo(&rd->_BAS, rd->_LEN, 0);
+ }
+
+ if(a){
+ UINT8 r, *b;
+ //---------------------
+ b=(UINT8*)&iord->_BAS;
+
+ if(ResNo){
+ r=Dev->Owner->SpioInfo->Base2Hi;
+ Dev->VlData.DevBase2=iord->_BAS;
+ } else {
+ r=Dev->Owner->SpioInfo->Base1Hi;
+ Dev->VlData.DevBase1=iord->_BAS;
+ }
+ SioRegister(Dev,TRUE,r,&b[1]);
+
+ if(ResNo)r=Dev->Owner->SpioInfo->Base2Lo;
+ else r=Dev->Owner->SpioInfo->Base1Lo;
+ SioRegister(Dev,TRUE,r,&b[0]);
+
+ SIO_TRACE((TRACE_SIO,"r=%x,b[0]=%x,b[1]=%x\n",r,b[0],b[1]));
+
+ return rd;
+ }
+ if(rd)pBS->FreePool(rd);
+ SIO_TRACE((TRACE_SIO,"returning NULL\n"));
+ return NULL;
+}
+
+VOID *ApplyIoRes(ASLRF_S_HDR* Hdr, SPIO_DEV* Dev, UINT8 ResNo){
+ BOOLEAN a=FALSE;
+ ASLR_IO *iord=(ASLR_IO*)Hdr,*rd;
+ UINT8 aln=0;
+//--------------------------
+ rd=ASLM_IO(iord->_DEC,iord->_MIN,iord->_MAX,iord->_ALN,iord->_LEN);
+
+ //Don't need to run all this if we got an empty descriptor
+ if(!iord->_LEN) return rd;
+
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IO2) && ResNo ) a=TRUE;
+ else {
+ if((Dev->DeviceInfo->Flags&SIO_SHR_IO1) && !ResNo) a=TRUE;
+ else {
+ if((rd->_ALN) != 0)aln=rd->_ALN-1;
+ a=AssignIo(&rd->_MIN, rd->_LEN,aln);
+ }
+ }
+
+ if(a){
+ UINT8 r, *b;
+ //---------------------
+ b=(UINT8*)&iord->_MIN;
+
+ //Special Case for FDC (second resource request 0x3F7 don't have a corresponded register)
+ if((Dev->DeviceInfo->Type==dsFDC) && (ResNo==1)) return rd;
+
+ if(ResNo){
+ r=Dev->Owner->SpioInfo->Base2Hi;
+ Dev->VlData.DevBase2=iord->_MIN;
+ } else {
+ r=Dev->Owner->SpioInfo->Base1Hi;
+ Dev->VlData.DevBase1=iord->_MIN;
+ }
+ SioRegister(Dev,TRUE,r,&b[1]);
+
+ if(ResNo)r=Dev->Owner->SpioInfo->Base2Lo;
+ else r=Dev->Owner->SpioInfo->Base1Lo;
+ SioRegister(Dev,TRUE,r,&b[0]);
+
+ return rd;
+ }
+ if(rd)pBS->FreePool(rd);
+ return NULL;
+}
+
+VOID FreeIrq(SPIO_DEV *dev, ASLR_IRQ *dsc)
+{
+ if ((gAvailableIsaIrq & dsc->_INT) == 0) {
+ gAvailableIsaIrq &= dsc->_INT;
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Irq1, 0);
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Irq2, 0);
+ }
+}
+
+VOID FreeDma(SPIO_DEV *dev, ASLR_DMA *dsc)
+{
+ if ((gAvailableDmaChnl & dsc->_DMA) == 0) {
+ gAvailableDmaChnl &= dsc->_DMA;
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Dma1, 0);
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Dma2, 0);
+ }
+}
+
+VOID FreeIo(SPIO_DEV *dev, ASLRF_S_HDR *dsc){
+
+ if(dsc->Name==ASLV_RT_FixedIO){
+ gDxeSvcTbl->FreeIoSpace( ((ASLR_FixedIO*)dsc)->_BAS, ((ASLR_FixedIO*)dsc)->_LEN);
+ } else {
+ gDxeSvcTbl->FreeIoSpace( ((ASLR_IO*)dsc)->_MIN, ((ASLR_IO*)dsc)->_LEN);
+ }
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Base1Hi, 0);
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Base1Lo, 0);
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Base2Hi, 0);
+ SioRegister(dev, TRUE, dev->Owner->SpioInfo->Base2Lo, 0);
+}
+
+//Free GCD resources if Tesource Tamplete Allocation failed
+VOID FreeResources(SPIO_DEV *dev, T_ITEM_LIST *Res){
+ UINTN i;
+ ASLRF_S_HDR *hdr;
+ UINTN bas,irq,dma;
+//---------------------
+ for(i=0, bas=0,irq=0,dma=0; i<Res->ItemCount; i++){
+ hdr=(ASLRF_S_HDR*)Res->Items[i];
+
+ switch(hdr->Name){
+
+ case ASLV_RT_IO:
+ case ASLV_RT_FixedIO:
+ bas++;
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_IO1)) && (bas==1))FreeIo(dev,hdr);
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_IO2)) && (bas==2))FreeIo(dev,hdr);
+ break;
+ case ASLV_RT_IRQ:
+ irq++;
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_IRQ1)) && (irq==1))FreeIrq(dev, (ASLR_IRQ*)hdr);
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_IRQ2)) && (irq==2))FreeIrq(dev, (ASLR_IRQ*)hdr);
+ break;
+
+ case ASLV_RT_DMA:
+ dma++;
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_DMA1)) && (dma==1))FreeDma(dev, (ASLR_DMA*)hdr);
+ if( (!(dev->DeviceInfo->Flags & SIO_SHR_DMA2)) && (dma==2))FreeDma(dev, (ASLR_DMA*)hdr);
+ break;
+ }
+ }
+ dev->Assigned=FALSE;
+}
+
+
+EFI_STATUS ApplyResources(SPIO_DEV *Dev, T_ITEM_LIST *ResLst, BOOLEAN IrqReserve){
+ UINTN i;
+ ASLRF_S_HDR *hdr;
+ EFI_STATUS Status = IrqReserve ? EFI_UNSUPPORTED : EFI_SUCCESS;
+ VOID *rd;
+ UINT8 irqc=0, basc=0, dmac=0;
+//--------------------------------
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyResources "));
+ //if device shares all resources we'll copy Resource Owner's CRS
+ if(Dev->Assigned){
+ SIO_TRACE((TRACE_SIO,"- Assigned Already\n"));
+ return EFI_SUCCESS;
+ }
+
+ if(Dev->DeviceInfo->Flags & SIO_NO_RES){
+ SIO_TRACE((TRACE_SIO,"- NO RSESOURCES USED\n"));
+ return EFI_SUCCESS;
+ }
+
+ if( (Dev->DeviceInfo->Flags & SIO_SHR_ALL )==SIO_SHR_ALL &&
+ Dev->ResOwner->DeviceInfo->LDN==Dev->DeviceInfo->LDN &&
+ (!IrqReserve))
+ {
+ SIO_TRACE((TRACE_SIO,"- Same LDN Share ALL Resources\n"));
+ Dev->CRS.ItemCount=Dev->ResOwner->CRS.ItemCount;
+ Dev->CRS.Items=Dev->ResOwner->CRS.Items;
+ Dev->Assigned=TRUE;
+ return EFI_SUCCESS;
+ }
+
+ for(i=0; i<ResLst->ItemCount; i++){
+ rd=NULL;
+ hdr=(ASLRF_S_HDR*)ResLst->Items[i];
+ if (hdr->Type==ASLV_SMALL_RES){ //SIO mast have only small resources types
+ //-------------------------
+ switch(hdr->Name){
+ case ASLV_RT_IRQ:
+ SIO_TRACE((TRACE_SIO,"- IRQ%d; IrqReserve=%d\n",irqc+1, IrqReserve));
+
+ rd=ApplyIrqRes(hdr,Dev,irqc,IrqReserve);
+ irqc++;
+ break;
+
+ case ASLV_RT_DMA:
+ if(!IrqReserve){
+ SIO_TRACE((TRACE_SIO,"- DMA%d >>",dmac+1));
+ rd=ApplyDmaRes(hdr, Dev, dmac);
+ dmac++;
+ } else continue;
+ break;
+
+ case ASLV_RT_IO:
+ if(!IrqReserve){
+ SIO_TRACE((TRACE_SIO," IO%d >>",basc+1));
+ rd=ApplyIoRes(hdr, Dev, basc);
+ basc++;
+ } else continue;
+ break;
+
+ case ASLV_RT_FixedIO:
+ if(!IrqReserve){
+ SIO_TRACE((TRACE_SIO,"Fixed IO%d >>",basc+1));
+ rd=ApplyFixedIoRes(hdr, Dev, basc);
+ basc++;
+ } else continue;
+ break;
+ }
+
+ if(IrqReserve) continue;
+
+ SIO_TRACE((TRACE_SIO,"rd=%x \n",rd));
+ if(rd) Status=AppendItemLst(&Dev->CRS, rd);
+ else Status=EFI_UNSUPPORTED;
+ } else Status=EFI_UNSUPPORTED; //the SIO - doesn't supports LARGE RESOURCES
+ if (EFI_ERROR(Status)) break;
+ }
+ SIO_TRACE((TRACE_SIO,"\n"));
+
+ //If Irq Reservation we no need to add any res descriptors yet
+ if(IrqReserve && (Status==EFI_UNSUPPORTED)){
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyResources(IrqReserve=%d) Status=EFI_SUCCESS\n",IrqReserve));
+ return EFI_SUCCESS;
+ }
+ //clear resource tamplete if we fail to assign one of the members of ResLst
+ if (EFI_ERROR(Status)){
+ FreeResources(Dev, &Dev->CRS);
+ ClearItemLst(&Dev->CRS, TRUE);
+ Dev->Assigned=FALSE;
+ } else Dev->Assigned=TRUE;
+ SIO_TRACE((TRACE_SIO,"GSIO: ApplyResources(IrqReserve=%d) Dev->CRS count=%d; Status=%r\n",IrqReserve, Dev->CRS.ItemCount, Status));
+ return Status;
+}
+
+EFI_STATUS AssignSharedResources(SPIO_DEV *Dev){
+ EFI_STATUS Status;
+ UINTN i, bas,irq,dma;
+ T_ITEM_LIST *crs=&Dev->ResOwner->CRS;
+ ASLRF_S_HDR *hdr;
+ BOOLEAN app;
+//----------------------------
+ for(i=0,bas=0,irq=0,dma=0,app=FALSE; i<crs->ItemCount; i++,app=FALSE){
+ hdr=crs->Items[i];
+ switch(hdr->Name){
+ //IO resource type
+ case ASLV_RT_FixedIO:
+ case ASLV_RT_IO:
+ bas++;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_IO1)&& (bas==1)) app=TRUE;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_IO2)&& (bas==2)) app=TRUE;
+ break;
+ //IRQ resource
+ case ASLV_RT_IRQ :
+ irq++;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_IRQ1)&& (irq==1)) app=TRUE;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_IRQ2)&& (irq==2)) app=TRUE;
+ break;
+ //DMA Resource
+ case ASLV_RT_DMA:
+ dma++;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_DMA1)&& (dma==1)) app=TRUE;
+ if( (Dev->DeviceInfo->Flags&SIO_SHR_DMA2)&& (dma==2)) app=TRUE;
+ break;
+ } //switch
+ if(app){
+ Status=AppendItemLst(&Dev->CRS,(VOID*)hdr);
+ if(EFI_ERROR(Status)) return Status;
+ }
+ }
+ return Status;
+}
+
+//this Function Assumes SIO is in Config Mode
+//and device has been selected in LDN reg
+EFI_STATUS AssignResources(SPIO_DEV *Dev){
+ T_ITEM_LIST *dl, *rl;
+ UINT8 p=0,c=0, n=0;
+ EFI_STATUS Status;
+//------------------------------------
+ SIO_TRACE((TRACE_SIO,"GSIO: AssignResources "));
+ if(gDxeSvcTbl==NULL) {
+ SIO_TRACE((TRACE_SIO,"- Dxe Sevice Table NOT_FOUND, returning EFI_UNSUPPORTED\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ if(Dev->Assigned) {
+ SIO_TRACE((TRACE_SIO,"- Device has Resourcs Assigned, returning EFI_SUCCESS\n"));
+ return EFI_SUCCESS;
+ }
+
+ //Take care about shared resources if any
+ if(Dev->DeviceInfo->Flags & SIO_SHR_ALL){
+ SIO_TRACE((TRACE_SIO,"- SHARED Flags=0x%X, Status=",Dev->DeviceInfo->Flags));
+ Status=AssignSharedResources(Dev);
+ if(Dev->DeviceInfo->Flags==SIO_SHR_ALL) {
+ Dev->Assigned=TRUE;
+ Status=EFI_SUCCESS;
+ SIO_TRACE((TRACE_SIO,"%r\n",Status));
+ return Status;
+ }
+ SIO_TRACE((TRACE_SIO,"%r\n",Status));
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ dl=&Dev->PRS;
+
+ if(Dev->NvData.DevPrsId){
+ n=Dev->NvData.DevPrsId-1;
+ if(n<dl->ItemCount){
+ rl=GetNumResources(dl,&n);
+ if(rl){
+ Status=ApplyResources(Dev,rl,FALSE);
+ SIO_TRACE((TRACE_SIO,"- By PrsId(%x),get DepFn(%X) Status=%r\n",Dev->NvData.DevPrsId,rl,Status));
+ if(!EFI_ERROR(Status)) return Status;
+ }
+ }
+ SIO_TRACE((TRACE_SIO,"GSIO: AssignResources Fail to reserve By PrsId,%d DepFn in Count %d is %X \n",n,dl->ItemCount,rl));
+ //if we can't apply selected resources reset it to "auto" again
+ Dev->NvData.DevPrsId=0;
+ }
+ //use Auto Resource settings
+ //try to get Prioritized resources
+ while( c < 3 || p < 3 ){
+ rl=GetPriResources(dl,c,p);
+ if(rl) {
+ Status=ApplyResources(Dev,rl,FALSE);
+ if(!Status) return EFI_SUCCESS;
+ }
+ c++; p++;
+ }
+ //Fail to get Dependent Function with Priority
+ //try by number
+ while( n < dl->ItemCount){
+ rl=GetNumResources(dl,&n);
+ if(rl) {
+ Status=ApplyResources(Dev,rl,FALSE);
+ SIO_TRACE((TRACE_SIO,"- By PRS Num(n=%d),get DepFn(%X) Status=%r\n",n,rl,Status));
+ if(!Status) return EFI_SUCCESS;
+ }
+ n++;
+ }
+ SIO_TRACE((TRACE_SIO,"\n"));
+ return EFI_NOT_FOUND;
+}
+
+////////////////////////////////////////////////////////////////////
+EFI_STATUS StartSioChildDevice(EFI_HANDLE CtrlHandle, SPIO_DEV *Dev){
+ EFI_STATUS Status=0;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+//----------------------------------
+ if(Dev->Started) return EFI_ALREADY_STARTED;
+ //Now Install All protocols
+ Status=pBS->InstallMultipleProtocolInterfaces(
+ &Dev->Handle,
+ &gEfiAmiSioProtocolGuid, &Dev->AmiSio,
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+
+ &gEfiSioProtocolGuid, &Dev->EfiSioData.EfiSio,
+#endif
+ &gDevicePathProtocolGuid, Dev->DevicePath, //DevPath GUID - I/F pare
+ NULL, NULL );
+
+ SIO_TRACE((TRACE_SIO,"InstallProt()=%r.", Status));
+
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status))return Status;
+
+ Dev->Started=TRUE;
+
+ //Open Protocol BY_CHILD_CONTROLLER to notify core we may produce CHILDS
+ Status=pBS->OpenProtocol( CtrlHandle, &gPciIoProtocolGuid, &PciIo,
+ gAmiSioDriverBinding.DriverBindingHandle, Dev->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+
+ SIO_TRACE((TRACE_SIO,"Open(PciIo)=%r\n", Status));
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+EFI_STATUS ReserveIrq(SPIO_DEV *Dev, UINTN Index){
+ EFI_STATUS Status;
+ T_ITEM_LIST *dl, *rl;
+ UINT8 p=0,c=0, n=0;
+//------------------------------------
+ if(gDxeSvcTbl==NULL) return EFI_UNSUPPORTED;
+
+ if(Dev->IrqReserved) return EFI_SUCCESS;
+
+ if(Dev->DeviceInfo->Flags & SIO_NO_RES){
+ SIO_TRACE((TRACE_SIO,"- NO RSESOURCES USED\n"));
+ return EFI_SUCCESS;
+ }
+
+
+ //Take care about shared resources if any
+ if((Dev->DeviceInfo->Flags & SIO_SHR_IRQ) == SIO_SHR_IRQ) return EFI_SUCCESS;
+
+ dl=&Dev->PRS;
+
+ if(Dev->NvData.DevPrsId){
+ n=Dev->NvData.DevPrsId-1; //Very first Option is AUTO Select
+ if(n<dl->ItemCount){
+ rl=GetNumResources(dl,&n);
+ if(rl){
+ Status=ApplyResources(Dev,rl,TRUE); //Reserve Interrupts
+ if(!EFI_ERROR(Status)) return Status;
+ }
+ }
+ //if we can't apply selected resources reset it to "auto" again
+ Dev->NvData.DevPrsId=0;
+ }
+ //use Auto Resource settings
+ //try to get Prioritized resources
+ while( c < 3 || p < 3 ){
+ rl=GetPriResources(dl,c,p);
+ if(rl) {
+ Status=ApplyResources(Dev,rl,TRUE);
+ SIO_TRACE((TRACE_SIO,"GSIO: ReserveIrq by PRI, Status=%r\n",Status));
+ if(!Status) return EFI_SUCCESS;
+ }
+ c++; p++;
+ }
+ //Fail to get Dependent Function with Priority
+ //try by number
+ while( n < dl->ItemCount){
+ rl=GetNumResources(dl,&n);
+ if(rl) {
+ Status=ApplyResources(Dev,rl,TRUE);
+ SIO_TRACE((TRACE_SIO,"GSIO: ReserveIrq PRS[%d], Status==%r\n",n,Status));
+ if(!Status) return EFI_SUCCESS;
+ }
+ n++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+EFI_STATUS InitSioDevice(SPIO_DEV *Dev){
+ EFI_STATUS Status=0;
+ BOOLEAN Dis_Flag=TRUE;
+// EFI_PCI_IO_PROTOCOL *PciIo;
+ //SPIO_DEV *ro=NULL;//rtesource owner in case of shared resources
+//-------------------------
+
+ if (Dev->Started||Dev->Initialized) {
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() Device was Started=%d Initialized=%d - returning EFI_SUCCESS\n",
+ Dev->Started, Dev->Initialized));
+ return EFI_SUCCESS;
+ }
+
+ if(!Dev->Owner->InCfgMode) SioCfgMode(Dev->Owner, TRUE);
+
+ //See if there actual SIO there or just empty space
+ Status=CheckDevicePresent(Dev);
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - CheckDevicePresent() Status=%r",Status));
+ if(Status==EFI_NO_RESPONSE) Dev->DeviceInfo->Implemented=FALSE;
+ SIO_TRACE((TRACE_SIO," Implemented=%d \n",Dev->DeviceInfo->Implemented));
+
+ if(!EFI_ERROR(Status)) {
+ if(Dev->DeviceInfo->Type == dsPS2CM) Dis_Flag=FALSE; //if ps2 mouse &ps2 keyboard in same logical device,not disable it
+ if(Dis_Flag){
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() Disabling Device\n"));
+ DevEnable(Dev,FALSE);//disable all devices before programing
+ }
+ }
+
+ if(Dev->DeviceInfo->Implemented && Dev->NvData.DevEnable){
+ //if we are Initializing device with shared resources
+ //make sure resource owner has it's resources Allocated!
+ if((Dev->DeviceInfo->Flags & SIO_SHR_ALL) && Dev->ResOwner){
+ //we don't care about the irq share case
+ if(!(Dev->DeviceInfo->Flags & SIO_SHR_IRQ)) {
+ DevSelect(Dev->ResOwner);
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() AssignResources(Dev->ResOwner) -"));
+ Status=AssignResources(Dev->ResOwner);
+ SIO_TRACE((TRACE_SIO," Status=%r; FLAGS=0x%X\n",Status, Dev->DeviceInfo->Flags));
+ if(EFI_ERROR(Status)) return Status;
+
+ }//if
+ }//if
+
+ DevSelect(Dev);
+ if(Dev->DeviceInfo->Flags & SIO_NO_RES) {
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Device has NO Resourcs\n"));
+ Dev->Assigned=TRUE;
+ }else{
+ SIO_TRACE((TRACE_SIO,"SIO InitSioDevice() AssignResources(Dev) -"));
+ Status=AssignResources(Dev); //Assigned Flag is changed inside AssignResources
+ SIO_TRACE((TRACE_SIO," Status=%r\n",Status));
+ }
+
+ if(!EFI_ERROR(Status)){
+ pBS->CopyMem(&Dev->AmiSio,&gAmiSioProtocol, sizeof(AMI_SIO_PROTOCOL));
+
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+ pBS->CopyMem(&Dev->EfiSioData.EfiSio, &gEfiSioProtocol, sizeof(EFI_SIO_PROTOCOL));
+#endif
+
+ if(!Dev->DevicePath){
+ ACPI_HID_DEVICE_PATH siodp;
+ //--------------------------
+ siodp.Header.Type=ACPI_DEVICE_PATH;
+ siodp.Header.SubType=ACPI_DP;
+ SET_NODE_LENGTH(&siodp.Header,ACPI_DEVICE_PATH_LENGTH);
+ siodp.HID=Dev->EisaId.HID;
+ siodp.UID=Dev->EisaId.UID;
+ Dev->DevicePath = DPAddNode(Dev->Owner->CntrDevPath,&siodp.Header);
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Set DevicePath=%X\n",Dev->DevicePath));
+ }
+ //Call Init BeforeActivate
+ //if device is not implemented it might be needed to do some initialization
+ // even for disabled devices if so here we are
+ if(Dev->DeviceInfo->InitRoutine){
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Device InitRoutine(isBeforeActivate)"));
+ Status=Dev->DeviceInfo->InitRoutine(&Dev->AmiSio,Dev->Owner->IsaBrgPciIo, isBeforeActivate);
+ SIO_TRACE((TRACE_SIO," Status=%r\n"));
+ if(EFI_ERROR(Status))return Status;
+
+ }
+ //In config routine we might exit config mode
+ if(!Dev->Owner->InCfgMode) SioCfgMode(Dev->Owner, TRUE);
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Enabling Device\n"));
+ DevEnable(Dev,TRUE);
+ //Call Init AfterActivate
+ if(Dev->DeviceInfo->InitRoutine){
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Calling InitRoutine(isAfterActivate)"));
+ Status=Dev->DeviceInfo->InitRoutine(&Dev->AmiSio,Dev->Owner->IsaBrgPciIo, isAfterActivate);
+ SIO_TRACE((TRACE_SIO," Status=%r\n", Status));
+ if(EFI_ERROR(Status)) return Status;
+
+ }
+ } else {
+ //Fail to assign device resource - so disable the device
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Fail to Assign Resources, Disable Device!\n"));
+ Dev->Started=TRUE;
+ Dev->Assigned=TRUE;
+ Dev->VlData.DevImplemented=FALSE;
+ }
+ } else { //if device was not Implemented on the board or was disabled by setup
+ //set Flags in not implemented devices to avoid creating handles on them
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Not Implemented or Disabled by Setup, Disable Device\n"));
+ Dev->Started=TRUE;
+ Dev->Assigned=TRUE;
+ }
+
+ Dev->Initialized=TRUE;
+
+ if(Dev->Owner->InCfgMode) SioCfgMode(Dev->Owner, FALSE);
+
+ if(Dev->DeviceInfo->HasSetup) Status=SioSetupData(Dev, FALSE);
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Set Device VlData(DevImplemented=%x,DevBase1=%x,DevBase2=%x,DevIrq1=%x,DevIrq2=%x,DevDma1=%x,DevDma2=%x);\n",Dev->VlData.DevImplemented,Dev->VlData.DevBase1,Dev->VlData.DevBase2,Dev->VlData.DevIrq1,Dev->VlData.DevIrq2,Dev->VlData.DevDma1,Dev->VlData.DevDma2));
+ SIO_TRACE((TRACE_SIO,"GSIO: InitSioDevice() - Set Device NvData(DevEnable=%x,DevPrsId=%x,DevMode=%x)\n",Dev->NvData.DevEnable,Dev->NvData.DevPrsId,Dev->NvData.DevMode));
+ return Status;
+}
+
+EFI_STATUS AmiSioStart(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status=EFI_SUCCESS,StatusRdp=EFI_SUCCESS;
+ INTN i;
+ UINTN j,k;
+ SPIO_DEV *dev;
+ ACPI_HID_DEVICE_PATH *dp=NULL;
+ GSPIO *spio;
+ BOOLEAN AllStarted=TRUE;
+ BOOLEAN GcdIndex=TRUE;
+ BOOLEAN Init_Flag=FALSE;
+#ifdef EFI_DEBUG
+ CHAR8 *DpString=NULL;
+#endif
+//--------------------------------
+#if ACPI_SUPPORT
+ if(!gPDsdt) return EFI_DEVICE_ERROR;
+#endif
+ PROGRESS_CODE(DXE_SIO_INIT);
+ SIO_TRACE((TRACE_SIO,"GSIO: AmiSioStart() - gSpio=%x,gSpioCount=%x\n",gSpio,gSpioCount));
+ for(j=0; j<gSpioCount; j++){
+ spio=&gSpio[j];
+ SIO_TRACE((TRACE_SIO,"\nSIO: AmiSioStart() - SIO[%d] SupportController=%X, This Controller=%X\n",j,spio->SupportedHandle,Controller));
+ if(spio->SupportedHandle!=Controller) continue;
+ if(!spio->CntrDevPath){
+ Status=pBS->OpenProtocol( Controller, &gDevicePathProtocolGuid,
+ (VOID **)&dp,This->DriverBindingHandle,
+ Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+ if(EFI_ERROR(Status) && Status!= EFI_ALREADY_STARTED) return Status;
+ spio->CntrDevPath=DPCopy((EFI_DEVICE_PATH_PROTOCOL*)dp);
+ pBS->CloseProtocol(Controller,&gDevicePathProtocolGuid,This->DriverBindingHandle, Controller);
+ spio->CntrHandle=Controller;
+ //To Create a chain of childs
+ Status=pBS->OpenProtocol( Controller,&gPciIoProtocolGuid,(VOID **)&PciIo,
+ This->DriverBindingHandle,Controller,EFI_OPEN_PROTOCOL_BY_DRIVER);
+ //if there are 2 or more SIO on the same LPC Bridge it should return something like that
+ if(EFI_ERROR(Status)) {
+ if(Status!=EFI_ALREADY_STARTED) return Status;
+ //Try to scan back and find opend PciIoProtocol for the previouse SIO
+ SIO_TRACE((TRACE_SIO,"GSIO: AmiSioStart() - The BindingDriver has been opened PciIo protocol for formor SIO chip=%X\n"));
+ for (i=j-1; i>=0; i--)if(gSpio[i].CntrHandle==Controller) spio->IsaBrgPciIo=gSpio[i].IsaBrgPciIo;
+ if(!spio->IsaBrgPciIo) return EFI_DEVICE_ERROR;
+ } else spio->IsaBrgPciIo=PciIo;
+ //Reserve SIO Index/Data port in GCD
+ SIO_TRACE((TRACE_SIO,"GSIO: AmiSioStart() - SIO[%d] =>Assign cfg Index=%X\n",j,spio->SpioInfo->SioIndex));
+ //it is not first sio index and it is different with former index.
+
+ if(j) {
+ for (i=j-1; i>=0; i--)
+ if( (gSpio[i].SpioInfo)->SioIndex==spio->SpioInfo->SioIndex ) {
+ GcdIndex=FALSE;
+ break;
+ }
+ }
+ //Reserve SIO Index/Data port in GCD when it is first io index or the index is different with other
+ if(GcdIndex) {
+ if(!AssignIo(&spio->SpioInfo->SioIndex, 1, 0)) continue;
+ if(!AssignIo(&spio->SpioInfo->SioData, 1, 0)) continue;
+ }
+ } //if(!spio->CntrDevPath)
+
+ dp=(ACPI_HID_DEVICE_PATH*)RemainingDevicePath;
+
+ SIO_TRACE((TRACE_SIO,"\nGSIO: Starting ... RDP= %X\n",(UINTN)RemainingDevicePath));
+
+ for(k=0;k<2;k++){
+ //Locate Right SIO Device
+ for (i=0; (UINTN)i<spio->DeviceCount; i++){
+ Status=EFI_SUCCESS;
+ dev=spio->DeviceList[i];
+ if((k==0)&&(dev->DeviceInfo->Type==dsUART)&&(dev->NvData.DevPrsId!=0)){
+ SIO_TRACE((TRACE_SIO,"\nSIO[%d]Dev[%d] InitSio Starting: first time=>\n",j,i));
+ Init_Flag=TRUE;
+ }
+ if((k==1)&&((dev->DeviceInfo->Type!=dsUART)||(dev->NvData.DevPrsId==0))){
+ SIO_TRACE((TRACE_SIO,"\nSIO[%d]Dev[%d] InitSio Starting: second time=>\n",j,i));
+ Init_Flag=TRUE;
+ }
+ if(Init_Flag) {
+ Status=InitSioDevice(dev);
+ Init_Flag=FALSE;
+ }
+ else continue;
+
+ SIO_TRACE((TRACE_SIO,"InitSioDevice()=%r;\n ", Status));
+ if(EFI_ERROR(Status)){
+ if (Status == EFI_NO_RESPONSE) {
+ SIO_TRACE((TRACE_SIO,"Device check EFI_NO_RESPONSE,Continue next device...\n",j,i));
+ continue;
+ }else {
+ SIO_TRACE((TRACE_SIO,"=>ERROR,Stop AmiSioStart...<=\n",j,i));
+ return Status;}
+ }
+
+ if(RemainingDevicePath==NULL){
+ SIO_TRACE((TRACE_SIO,"Start SIO[%d]Dev[%d] ChildDevice:",j,i));
+ Status=StartSioChildDevice(Controller,dev);
+ SIO_TRACE((TRACE_SIO,"StartSioDev()=%r; Hnd=%X;\n", Status, dev->Handle));
+
+ if(EFI_ERROR(Status)){
+ if(Status!=EFI_ALREADY_STARTED){
+ return Status;
+ } else Status=EFI_SUCCESS;
+ } else AllStarted=FALSE;
+ SIO_TRACE((TRACE_SIO,"AllStarted=%X;\n", AllStarted));
+ } else {
+ SIO_TRACE((TRACE_SIO,"RemainingDevicePath is not Null,HID(%x)_UID(%x)\n",dp->HID,dp->UID));
+ StatusRdp=EFI_NOT_FOUND;
+ if(dp->HID==dev->EisaId.HID && dp->UID==dev->EisaId.UID){
+ StatusRdp=StartSioChildDevice(Controller,dev);
+ SIO_TRACE((TRACE_SIO,"RDP; StartSioDev()=%r; Hnd=%X;\n", StatusRdp, dev->Handle));
+ //break; //return Status;
+ }
+ }
+ SIO_TRACE((TRACE_SIO,"\n"));
+ }//for i
+ }//for j
+ }// for k
+ //if(AllStarted && RemainingDevicePath==NULL) CreateSioDevStatusVar();
+ CreateSioDevStatusVar();
+
+ if(RemainingDevicePath!=NULL) {
+ SIO_TRACE((TRACE_SIO,"\nSIO: AmiSioStart() - returning RdpStatus = %r\n", StatusRdp));
+ return StatusRdp;
+ }
+
+ if(AllStarted) Status=EFI_ALREADY_STARTED;
+ else Status=EFI_SUCCESS;
+ SIO_TRACE((TRACE_SIO,"\nSIO: AmiSioStart() - AllStarted=%d, returning %r\n", AllStarted, Status));
+ return Status;
+
+}
+
+
+EFI_STATUS StopSioDevice(SPIO_DEV *Dev,EFI_HANDLE Controller)
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+//--------------------------------------------------------------------
+
+ if(Dev->DeviceInfo->Implemented==FALSE || Dev->VlData.DevImplemented==FALSE){
+ SIO_TRACE((TRACE_SIO,"GSIO: StopSioDevice - Device is NOT Implemented, returning EFI_SUCCESS\n"));
+ return Status;
+ }
+
+ if(Dev->Started==FALSE) return Status;
+
+ Status=pBS->CloseProtocol(Controller,&gPciIoProtocolGuid,
+ gAmiSioDriverBinding.DriverBindingHandle, Dev->Handle);
+
+
+ SIO_TRACE((TRACE_SIO,"GSIO: Closing(PciIo)=%r; ", Status));
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status))return Status;
+
+
+ Status=pBS->UninstallMultipleProtocolInterfaces(
+ Dev->Handle,
+ &gEfiAmiSioProtocolGuid,&Dev->AmiSio,
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+ &gEfiSioProtocolGuid, &Dev->EfiSioData.EfiSio,
+#endif
+ &gDevicePathProtocolGuid,Dev->DevicePath,
+ NULL, NULL );
+ SIO_TRACE((TRACE_SIO,"Uninstalling(AmiSio;"));
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+ SIO_TRACE((TRACE_SIO," EfiSio;"));
+#endif
+ SIO_TRACE((TRACE_SIO," DevPath)=%r;\n", Status));
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //don't need to free and clear the device path buffer of the device
+ //- it not going to change any way. Just care not to create it over again
+ //when Start function will be called
+ Dev->Handle=NULL;
+ Dev->Started=FALSE;
+ DevEnable(Dev, FALSE);
+
+ Status = DisableDevInSioDevStatusVar(Dev);
+
+ if(EFI_ERROR(Status))SIO_TRACE((TRACE_SIO,"GSIO: Stop=> %r - Update SioDevStatusVar.\n", Status));
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+
+EFI_STATUS AmiSioStop(IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer)
+{
+ EFI_STATUS Status;
+ UINTN i,j,k,cnt=0;
+ SPIO_DEV *dev;
+ GSPIO *spio;
+//------------------------
+ SIO_TRACE((TRACE_SIO,"\nGenericSIOStop: gSpioCount=%d, NumberOfChildren=0x%X, Controller=0x%X\n",
+ gSpioCount, NumberOfChildren, Controller));
+
+ for(k=0,j=0; k<gSpioCount; k++){
+ spio=&gSpio[k];
+ if(spio->CntrHandle!=Controller) continue;
+
+ if (!NumberOfChildren) {
+ for(i=0; i<spio->DeviceCount; i++){
+ SIO_TRACE((TRACE_SIO,"SIO[%d] Stopping: ", i));
+ dev=spio->DeviceList[i];
+ if(dev->Started) Status=StopSioDevice(spio->DeviceList[i], Controller);
+ SIO_TRACE((TRACE_SIO,"%r.\n", Status));
+ if(EFI_ERROR(Status)) return Status;
+ }
+ //If everything OK we should close PciIo Protocol that we opened BY_DRIVER
+ //In case of multiple SIO on the same LPC Bridge this code can cause ERROR_STATUS.
+ Status=pBS->CloseProtocol(Controller,&gPciIoProtocolGuid,This->DriverBindingHandle,Controller);
+ if(EFI_ERROR(Status)){
+ SIO_TRACE((TRACE_SIO, "\nAttempt to Close LpcBrg PCI_IO was UNSUCCESSFUL %r!\n", Status));
+ Status=EFI_SUCCESS;// clear error status Status.
+ }
+ } else {
+ for( ;j<NumberOfChildren; j++){
+
+ for(i=0; i<spio->DeviceCount; i++){
+ dev=spio->DeviceList[i];
+
+ if(dev->Handle==ChildHandleBuffer[j]){
+ SIO_TRACE((TRACE_SIO,"SIO[%d] Stopping: ", i));
+ Status=StopSioDevice(dev,Controller);
+ SIO_TRACE((TRACE_SIO,"%r.\n", Status));
+ if(EFI_ERROR(Status)) return Status;
+ cnt++;
+ break;
+ }
+ } //for i
+ } //for j
+ } //else
+ spio->CntrDevPath=NULL;
+ }//for k
+
+ if(NumberOfChildren && (!cnt)) Status=EFI_NOT_FOUND;
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+
+
+//AmiSIO Protocol Functions Implementation
+EFI_STATUS AmiSioRegister(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN BOOLEAN ExitCfgMode,
+ IN UINT8 Register,
+ IN OUT UINT8 *Value)
+{
+ SPIO_DEV *dev=(SPIO_DEV*)This;
+//-----------------------------------
+ if(!This || !Value || Register>SIO_MAX_REG ) return EFI_INVALID_PARAMETER;
+
+ if(!dev->Owner->InCfgMode) SioCfgMode(dev->Owner, TRUE);
+
+ DevSelect(dev);
+ SioRegister(dev, Write, Register, Value);
+
+ if(ExitCfgMode) {
+ if(dev->Owner->InCfgMode) SioCfgMode(dev->Owner, FALSE);
+ }
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS AmiSioCRS(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Set,
+ IN OUT T_ITEM_LIST **Resources)
+{
+ EFI_STATUS Status;
+ SPIO_DEV *dev=(SPIO_DEV*)This;
+//-----------------------------------
+ if (!This || !Resources) return EFI_INVALID_PARAMETER;
+
+ if (Set) {
+ FreeResources(dev, &dev->CRS);
+// ClearResLst(&dev->CRS);
+ ClearItemLst(&dev->CRS, TRUE);
+ Status = ApplyResources(dev, *Resources, FALSE);
+// ProgramResources(dev);
+ } else {
+ CopyItemLst(&dev->CRS, Resources);
+// *Resources=&dev->CRS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+#if ((defined PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010014))
+
+EFI_STATUS EfiSioRegisterAccess(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN BOOLEAN ExitCfgMode,
+ IN UINT8 Register,
+ IN OUT UINT8 *Value)
+{
+ EFI_SIO_DATA *EfiSioData=(EFI_SIO_DATA*)This;
+//---------------------
+ if(This==NULL) return EFI_INVALID_PARAMETER;
+
+ return AmiSioRegister(&EfiSioData->Owner->AmiSio,Write,ExitCfgMode,Register,Value);
+
+}
+
+EFI_STATUS EfiSioGetRes(T_ITEM_LIST *AmiResLst, ACPI_RESOURCE_HEADER_PTR *EfiResLst){
+ UINTN i, sz=0;
+ ASLRF_S_HDR *pRes;
+ VOID *EfiSioRes=NULL;
+ UINT8 *p8;
+//----------------
+ for(i=0; i<AmiResLst->ItemCount; i++){
+ pRes=(ASLRF_S_HDR*)AmiResLst->Items[i];
+ if(pRes->Type==ASLV_SMALL_RES) sz+=(UINTN)pRes->Length;
+ else sz+=((ASLRF_L_HDR*)pRes)->Length;
+ }
+
+ EfiSioRes=Malloc(sz+sizeof(ASLR_EndTag));
+ if(EfiSioRes==NULL) return EFI_OUT_OF_RESOURCES;
+
+ for(i=0,p8=EfiSioRes; i<AmiResLst->ItemCount; i++){
+ pRes=(ASLRF_S_HDR*)AmiResLst->Items[i];
+ if(pRes->Type==ASLV_SMALL_RES) sz=(UINTN)pRes->Length;
+ else sz=(UINTN)((ASLRF_L_HDR*)pRes)->Length;
+
+ MemCpy(p8,(VOID*)pRes, sz);
+ p8+=sz;
+ }
+
+ ((ASLR_EndTag*)p8)->Hdr.HDR=ASLV_END_TAG_HDR;
+ ((ASLR_EndTag*)p8)->Chsum=0;
+
+ EfiResLst->SmallHeader=EfiSioRes;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS EfiSioGetResourcces(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceList)
+{
+ EFI_STATUS Status;
+ EFI_SIO_DATA *EfiSioData=(EFI_SIO_DATA*)This;
+ T_ITEM_LIST *ResLst=NULL; //if NULL new Buffer will be allocated...
+ UINTN EfiSioBuffSize=0;
+//---------------------
+ if(This==NULL || ResourceList==NULL) return EFI_INVALID_PARAMETER;
+
+ //Get resources in AMI SIO format...
+ Status=AmiSioCRS(&EfiSioData->Owner->AmiSio, FALSE, &ResLst);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Convert it to EFI_SUPER_IO format.
+ Status=EfiSioGetRes(ResLst, ResourceList);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+
+EFI_STATUS EfiSioSetRes(T_ITEM_LIST *AmiResLst, ACPI_RESOURCE_HEADER_PTR EfiResLst){
+ UINTN sz=0;
+ UINT8 *p8;
+ EFI_STATUS Status;
+//----------------
+ p8=(UINT8*)EfiResLst.SmallHeader;
+
+ //Convert resources to AMI_SIO format.
+ while( ((ASLR_EndTag*)p8)->Hdr.HDR!=ASLV_END_TAG_HDR ){
+ if( ((ASLRF_S_HDR*)p8)->Type==ASLV_SMALL_RES )sz=(UINTN)((ASLRF_S_HDR*)p8)->Length;
+ else sz=(UINTN)((ASLRF_L_HDR*)p8)->Length;
+
+ Status=AppendItemLst(AmiResLst, p8);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ p8+=sz;
+ }
+ return Status;
+}
+
+EFI_STATUS EfiSioSetResources(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN ACPI_RESOURCE_HEADER_PTR ResourceList)
+{
+ EFI_STATUS Status;
+ EFI_SIO_DATA *EfiSioData=(EFI_SIO_DATA*)This;
+ T_ITEM_LIST *ResLst=NULL; //if NULL new Buffer will be allocated...
+ UINTN EfiSioBuffSize=0;
+//---------------------
+ if(This==NULL || ResourceList.SmallHeader==NULL) return EFI_INVALID_PARAMETER;
+
+ //Get Bubber for T_ITEM_LIST object...
+ ResLst=(T_ITEM_LIST*)MallocZ(sizeof(T_ITEM_LIST));
+ if(ResLst==NULL) return EFI_OUT_OF_RESOURCES;
+
+ //Convert resources to AMI_SIO format.
+ Status=EfiSioSetRes(ResLst, ResourceList);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Submit converted resources.
+ return AmiSioCRS(&EfiSioData->Owner->AmiSio, TRUE, &ResLst);
+}
+
+
+EFI_STATUS EfiSioPrs(T_ITEM_LIST *AmiPrsLst, ACPI_RESOURCE_HEADER_PTR *EfiResLst){
+ UINTN i,j, sz=0;
+ ASLRF_S_HDR *pRes;
+ EFI_ASL_DepFn *pPrs;
+ VOID *EfiSioPrs=NULL;
+ UINT8 *p8;
+//----------------
+ for(i=0; i<AmiPrsLst->ItemCount; i++){
+ pPrs=(EFI_ASL_DepFn*)AmiPrsLst->Items[i];
+ pRes=pPrs->DepFn;
+ sz+=pRes->Length;
+
+ for(j=0; j<pPrs->DepRes.ItemCount; j++){
+ pRes=(ASLRF_S_HDR*)pPrs->DepRes.Items[j];
+ if(pRes->Type==ASLV_SMALL_RES) sz+=(UINTN)pRes->Length;
+ else sz+=((ASLRF_L_HDR*)pRes)->Length;
+ }
+ }
+
+ //Allocate Buffer including EndDepFn object + Resource EndTag
+ EfiSioPrs=Malloc(sz+sizeof(ASLR_EndTag)+sizeof(ASLV_RT_EndDependentFn));
+ if(EfiSioPrs==NULL) return EFI_OUT_OF_RESOURCES;
+
+ //Dump everything in buffer.
+ for(i=0,p8=EfiSioPrs; i<AmiPrsLst->ItemCount; i++){
+ pPrs=(EFI_ASL_DepFn*)AmiPrsLst->Items[i];
+ //Copy StartDepFn Object...
+ pRes=pPrs->DepFn;
+ sz=pRes->Length;
+ MemCpy(p8,(VOID*)pRes, sz);
+ p8+=sz;
+
+ for(j=0; j<pPrs->DepRes.ItemCount; j++){
+ pRes=(ASLRF_S_HDR*)pPrs->DepRes.Items[j];
+
+ if(pRes->Type==ASLV_SMALL_RES) sz=(UINTN)pRes->Length;
+ else sz=(UINTN)((ASLRF_L_HDR*)pRes)->Length;
+
+ MemCpy(p8,(VOID*)pRes, sz);
+ p8+=sz;
+ }
+ }
+
+ ((ASLRF_S_HDR*)p8)->Name=ASLV_RT_EndDependentFn;
+ ((ASLRF_S_HDR*)p8)->Type=ASLV_SMALL_RES;
+ ((ASLRF_S_HDR*)p8)->Length=sizeof(ASLV_RT_EndDependentFn);
+ p8+=sizeof(ASLRF_S_HDR);
+
+ ((ASLR_EndTag*)p8)->Hdr.HDR=ASLV_END_TAG_HDR;
+ ((ASLR_EndTag*)p8)->Chsum=0;
+
+ EfiResLst->SmallHeader=EfiSioPrs;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS EfiSioPossibleResources(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ OUT ACPI_RESOURCE_HEADER_PTR *ResourceCollection)
+{
+ EFI_STATUS Status;
+ EFI_SIO_DATA *EfiSioData=(EFI_SIO_DATA*)This;
+ T_ITEM_LIST *ResLst=NULL; //if NULL new Buffer will be allocated...
+//----------------------------------
+ if(This==NULL || ResourceCollection==NULL) return EFI_INVALID_PARAMETER;
+
+ //Get PRS in AMI SIO format...
+ Status=AmiSioPRS(&EfiSioData->Owner->AmiSio, FALSE, &ResLst);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ //Convert it to EFI_SUPER_IO format.
+ Status=EfiSioPrs(ResLst, ResourceCollection);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+EFI_STATUS EfiSioModify(
+ IN CONST EFI_SIO_PROTOCOL *This,
+ IN CONST EFI_SIO_REGISTER_MODIFY *Command,
+ IN UINTN NumberOfCommands)
+{
+ EFI_STATUS Status;
+ EFI_SIO_DATA *EfiSioData=(EFI_SIO_DATA*)This;
+ UINTN i;
+ UINT8 val;
+ BOOLEAN ExitCfg;
+//----------------------------------
+ if(This==NULL || Command==NULL) return EFI_INVALID_PARAMETER;
+
+ if(NumberOfCommands==0) return EFI_SUCCESS;
+
+ for(i=0; i<NumberOfCommands; i++){
+ if(i<NumberOfCommands-1)ExitCfg=FALSE;
+ else ExitCfg=TRUE;
+
+ //Read Register
+ Status=AmiSioRegister(&EfiSioData->Owner->AmiSio, FALSE, ExitCfg,
+ Command->Register, &val);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ val&=Command->AndMask;
+ val|=Command->OrMask;
+
+ Status=AmiSioRegister(&EfiSioData->Owner->AmiSio, TRUE, ExitCfg,
+ Command->Register, &val);
+ ASSERT_EFI_ERROR(Status);
+ if(EFI_ERROR(Status)) return Status;
+
+ }
+ return Status;
+}
+#endif
+
+
+EFI_STATUS AmiSioPRS(IN AMI_SIO_PROTOCOL *This,
+ IN BOOLEAN Set,
+ IN OUT T_ITEM_LIST **Resources)
+{
+ SPIO_DEV *dev=(SPIO_DEV*)This;
+//---------------------------------------
+ if(Set) return EFI_UNSUPPORTED;
+ CopyItemLst(&dev->PRS, Resources);
+// *Resources=&dev->PRS;
+ return EFI_SUCCESS;
+}
+
+//Routine to transit Sio in/from Config Mode.
+static VOID BootScriptSioCfgMode(GSPIO *Sio, BOOLEAN Enter, EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave)
+{
+ UINTN i;
+ SPIO_SCRIPT_LST *sl;
+
+//---------------------------------
+ if(Enter)sl=Sio->SpioInfo->EnterCfgMode;
+ else sl=Sio->SpioInfo->ExitCfgMode;
+
+ if(sl==NULL) return;
+
+ for (i=0; i<sl->InstrCount; i++){
+ switch (sl->OpType){
+ case cfgNone:
+ break;
+ case cfgByteSeq:
+ {
+ SPIO_SCRIPT *Instr = (SPIO_SCRIPT*) sl->Instruction[0];
+ SPIO_SCRIPT *cmd = &Instr[i];
+ UINT16 reg;
+ //------------------------
+ if(cmd->IdxDat)reg=Sio->SpioInfo->SioIndex;
+ else reg=Sio->SpioInfo->SioData;
+
+ if (cmd->WrRd) {
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(BootScriptSave,
+ EfiBootScriptWidthUint8,
+ reg, 1, &cmd->Value
+ );
+ } else {
+ //This waits until SIO provides a specific value.
+ //This unsupported by boot script Io read/writes.
+
+ //<markw>I know of no SIO that needs this.
+ //If needed, SIO S3 resume must be implemented differently
+ // than the normal boot script.
+ SIO_TRACE((TRACE_SIO,"GSIO: Reading Index/Data SIO registers not supported entering/exit in for S3 resume.\n"));
+ ASSERT_EFI_ERROR(EFI_UNSUPPORTED);
+ }
+ break;
+ }
+ case cfgRoutine:
+ {
+ //Implementing a generic routine like this is difficult using boot scripts in this
+ //SIO implementation.
+ //Use cfgByteSeq.
+ SIO_TRACE((TRACE_SIO,"GSIO: cfgRoutine in SIO not supported for S3 resume. Use cfgByteSeq for enter/exit config space in IOx.c.\n"));
+ ASSERT_EFI_ERROR(EFI_UNSUPPORTED);
+ }
+ break;
+ default: return;
+ }//switch
+ }//for
+ Sio->InCfgMode=Enter;
+ return;
+}
+
+VOID BootScriptSioDevSelect(SPIO_DEV *Dev, EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave){
+
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(BootScriptSave,
+ EfiBootScriptWidthUint8,
+ Dev->Owner->SpioInfo->SioIndex, 1, &Dev->Owner->SpioInfo->DevSel);
+
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(BootScriptSave,
+ EfiBootScriptWidthUint8,
+ Dev->Owner->SpioInfo->SioData, 1, &Dev->DeviceInfo->LDN );
+}
+
+static VOID CallbackReadyToBoot(IN EFI_EVENT Event, IN VOID *Context)
+{
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL *bss;
+ EFI_STATUS Status;
+ UINTN i, j, s, ari;//, cnt1,cnt2;
+ UINT8 b,r;
+ BOOLEAN devsel, devact, cfgmod;
+ SPIO_DEV *dev;
+ GSPIO *spio;
+//----------------------------------
+
+ Status = pBS->LocateProtocol(&gEfiBootScriptSaveGuid,NULL,&bss);
+ if (EFI_ERROR(Status)) {
+ SIO_TRACE((TRACE_SIO,"GSIO: FAIL to locate EfiBootScriptSaveProtocol %r",Status));
+ return;
+ }
+
+ for(s=0;s<gSpioCount;s++){
+ cfgmod=FALSE;
+ spio=&gSpio[s];
+ if(!spio->InCfgMode) SioCfgMode(spio, TRUE);
+ spio->BootScript=bss;
+
+ //first Check if something changed in Global Config regs programming
+ for(i=0; i<spio->SpioInfo->GlobalInclRegCount; i++){
+ //if we got DevSel register just skip it
+ r=spio->SpioInfo->GlobalIncludeReg[i];
+ if((r==spio->SpioInfo->Activate)||(r==spio->SpioInfo->DevSel)) continue;
+ //select register
+ IoWrite8(spio->SpioInfo->SioIndex,r);
+ //read actual data
+ b=IoRead8(spio->SpioInfo->SioData);
+ //if nothing has changed just skip it
+ if(b==spio->GlobalCfgDump[i]) continue;
+
+ //enter config mode only if we really need it
+ if(!cfgmod){
+ BootScriptSioCfgMode(spio,TRUE,bss);
+ cfgmod=TRUE;
+ }
+ //if this reg was different before the initialization of SIO - record that into boot script
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioIndex, 1, &r);
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioData, 1, &b);
+ }
+
+ //Found out Activate register index in spio->SpioInfo->LocalIncludeReg[] buffer
+ //it must be in LocalIncludeReg[] Buffer
+ for(ari=0; ari<spio->SpioInfo->LocalInclRegCount; ari++)
+ if(spio->SpioInfo->LocalIncludeReg[ari]==spio->SpioInfo->Activate)break;
+
+ //Now check Local registers - unique for each device
+ for (j=0; j<spio->DeviceCount; j++) {
+
+ //---------------------
+ devsel=FALSE;
+ dev=spio->DeviceList[j];
+ //found out if device was active after PEI phase before DXE SIO Intialization
+ devact=(dev->LocalCfgDump[ari]==spio->SpioInfo->ActivVal);
+ DevSelect(dev);
+
+ //check current device active status
+ IoWrite8(spio->SpioInfo->SioIndex,spio->SpioInfo->Activate);
+ b=IoRead8(spio->SpioInfo->SioData);
+
+ //if device is NOT active now and was NOT active before just skip it
+ if( (b==spio->SpioInfo->DeactVal) && (dev->LocalCfgDump[ari]==spio->SpioInfo->DeactVal)) continue;
+
+ //if before and after device was ACTIVE that means - nothing has changed
+ //in Device Active Status. We need not to add this device in boot script
+ if((b==spio->SpioInfo->ActivVal)&&(dev->LocalCfgDump[ari]==spio->SpioInfo->ActivVal));
+ else{
+ //before and after SIO Init Activate register values does not mutch
+ //we need to enter config mode if not in config mode yet and select the device
+ if(!cfgmod){ //if still not in config mode
+ BootScriptSioCfgMode(spio,TRUE,bss);
+ cfgmod=TRUE;
+ }
+ if(!devsel){//device has not been selected
+ BootScriptSioDevSelect(dev, bss);
+ devsel=TRUE;
+ }
+ //Device was Active after PEI phase, but now it is NOT
+ if(devact){
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioIndex, 1, &spio->SpioInfo->Activate);
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioData, 1, &spio->SpioInfo->DeactVal);
+ devact=FALSE;
+ }
+ if(b==spio->SpioInfo->DeactVal)continue;
+ }
+
+ //if we are here that means - Device is active after DXE initialization
+ //and we must check if something gets changed in Generic register programming
+ for(i=0; i<spio->SpioInfo->LocalInclRegCount; i++) {
+ r=spio->SpioInfo->LocalIncludeReg[i];
+ //We took care about activate register erlier
+ if((r==spio->SpioInfo->Activate)||(r==spio->SpioInfo->DevSel)) continue;
+
+ //select register
+ IoWrite8(spio->SpioInfo->SioIndex,r);
+ //read actual data
+ b=IoRead8(spio->SpioInfo->SioData);
+ //if nothing has changed just skip it
+ if(b==dev->LocalCfgDump[i]) continue;
+
+ //enter config mode only if we really need it
+ if(!cfgmod){
+ BootScriptSioCfgMode(spio, TRUE, bss);
+ cfgmod=TRUE;
+ }
+ //device has not been selected
+ if(!devsel){
+ BootScriptSioDevSelect(dev, bss);
+ devsel=TRUE;
+ }
+ //Deactivate the device before changing registers
+ if(devact){
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioIndex, 1, &spio->SpioInfo->Activate);
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioData, 1, &spio->SpioInfo->DeactVal);
+ devact=FALSE;
+ }
+ //if this reg was different before the DXE initialization of SIO - record that into boot script
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioIndex, 1, &r);
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioData, 1, &b);
+
+ } //reg dump compare loop
+
+ //if we are here we have checked the device registers
+ if(!devact){ // we must Activate device now if we have deactivated it erlear
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioIndex, 1, &spio->SpioInfo->Activate);
+ BOOT_SCRIPT_S3_IO_WRITE_MACRO(bss,EfiBootScriptWidthUint8,spio->SpioInfo->SioData, 1, &spio->SpioInfo->ActivVal);
+ }
+
+ //Now if device has programmed some registers mapped through LD Decoded registers
+ //we need so save them aswell. We will not do this automatically, but call Porting function to do so...
+ if(dev->DeviceInfo->InitRoutine!=NULL)
+ Status=dev->DeviceInfo->InitRoutine(&dev->AmiSio,dev->Owner->IsaBrgPciIo,isAfterBootScript);
+
+ } //end device loop
+ if(cfgmod)BootScriptSioCfgMode(spio, FALSE, bss);
+ SioCfgMode(spio, FALSE);
+ }//for s
+
+ //
+ //Kill the Event
+ //
+ pBS->CloseEvent(Event);
+
+}
+
+
+EFI_STATUS CreateSioDevStatusVar()
+{
+ UINTN SioDevStatusVarSize = sizeof(SIO_DEV_STATUS);
+ UINT32 SioDevStatusVarAttributes = 0;
+ SIO_DEV_STATUS SioDevStatusVar;
+ UINTN i,j;
+ BOOLEAN Implemented;
+ UINT32 UID=0;
+ EFI_STATUS Status = EFI_SUCCESS;
+ GSPIO *spio;
+// SPIO_DEV *dev;
+//--------------------------------------
+ Status = pRS->GetVariable(SIO_DEV_STATUS_VAR_NAME, &gSioDevStatusVarGuid,
+ &SioDevStatusVarAttributes,
+ &SioDevStatusVarSize, &SioDevStatusVar.DEV_STATUS);
+ if (EFI_ERROR(Status)) {
+ SioDevStatusVar.DEV_STATUS = 0;
+ SioDevStatusVarAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ }
+
+ for (i = 0; i < gSpioCount; i++) {
+ spio=&gSpio[i];
+ for(j=0;j<spio->DeviceCount;j++){
+ Implemented = (spio->DeviceList[j]->DeviceInfo->Implemented && spio->DeviceList[j]->NvData.DevEnable);
+ UID = spio->DeviceList[j]->DeviceInfo->UID;
+ switch (spio->DeviceList[j]->DeviceInfo->Type){
+ case dsFDC: SioDevStatusVar.Fdd = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] FDC is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsPS2CK:
+ case dsPS2K: SioDevStatusVar.Key60_64 = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] PS2K is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsPS2CM:
+ case dsPS2M: SioDevStatusVar.Ps2Mouse = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] PS2M is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsUART:
+ if (UID == 0) SioDevStatusVar.SerialA = Implemented;
+ else
+ if (UID == 1) SioDevStatusVar.SerialB = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] UART(UID=%x) is Implemented=%d\n",i,j,UID,Implemented));
+ break;
+ case dsLPT: SioDevStatusVar.Lpt = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] LPT is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsGAME:
+ if (UID == 0)SioDevStatusVar.Game1 = Implemented;
+ else
+ if (UID == 1)SioDevStatusVar.Game2 = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] GAME(UID=%x) is Implemented=%d\n",i,j,UID,Implemented));
+ break;
+ case dsSB16: SioDevStatusVar.Sb16 = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] SB16 is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsFmSynth: SioDevStatusVar.FmSynth = Implemented;
+ SIO_TRACE((TRACE_SIO,"SIO[%d]Dev[%d] FmSynth is Implemented=%d\n",i,j,Implemented));
+ break;
+ case dsMPU401:
+ case dsCIR:
+ case dsGPIO:
+ case dsHwMon:
+ case dsPME:
+ case dsACPI:
+ break;
+ }//switch
+ } //for j
+ }//for i
+ Status = pRS->SetVariable(SIO_DEV_STATUS_VAR_NAME, &gSioDevStatusVarGuid,
+ SioDevStatusVarAttributes,
+ SioDevStatusVarSize, &SioDevStatusVar);
+ SIO_TRACE((TRACE_SIO,"GSIO: DevStatusVar=%X Status=%r\n",SioDevStatusVar.DEV_STATUS,Status));
+ return Status;
+}
+
+
+EFI_STATUS DisableDevInSioDevStatusVar(SPIO_DEV *Dev)
+{
+ UINTN SioDevStatusVarSize = sizeof(SIO_DEV_STATUS);
+ UINT32 SioDevStatusVarAttributes = 0;
+ SIO_DEV_STATUS SioDevStatusVar;
+ EFI_STATUS Status = EFI_SUCCESS;
+ SIO_DEV_TYPE Type = Dev->DeviceInfo->Type;
+ SIO_DEV_TYPE UID = Dev->EisaId.UID;
+//----------------------
+ Status = pRS->GetVariable(SIO_DEV_STATUS_VAR_NAME, &gSioDevStatusVarGuid,
+ &SioDevStatusVarAttributes,
+ &SioDevStatusVarSize, &SioDevStatusVar.DEV_STATUS);
+ if (!EFI_ERROR(Status)) {
+ switch (Type) {
+ case dsFDC: SioDevStatusVar.Fdd = 0;
+ break;
+ case dsPS2CK:
+ case dsPS2K: SioDevStatusVar.Key60_64 = 0;
+ break;
+ case dsPS2CM:
+ case dsPS2M: SioDevStatusVar.Ps2Mouse = 0;
+ break;
+ case dsUART: if (UID == 0) {
+ SioDevStatusVar.SerialA = 0;
+ } else if (UID == 1) {
+ SioDevStatusVar.SerialB = 0;
+ }
+ break;
+ case dsLPT: SioDevStatusVar.Lpt = 0;
+ break;
+ case dsGAME: if (UID == 0) {
+ SioDevStatusVar.Game1 = 0;
+ } else if (UID == 1) {
+ SioDevStatusVar.Game2 = 0;
+ }
+ break;
+ case dsSB16: SioDevStatusVar.Sb16 = 0;
+ break;
+ case dsFmSynth: SioDevStatusVar.FmSynth = 0;
+ break;
+ case dsMPU401: case dsCIR: case dsGPIO:
+ case dsHwMon: case dsPME: case dsACPI: break;
+
+ } //switch
+
+ Status = pRS->SetVariable(SIO_DEV_STATUS_VAR_NAME, &gSioDevStatusVarGuid,
+ SioDevStatusVarAttributes,
+ SioDevStatusVarSize, &SioDevStatusVar);
+ }
+ SIO_TRACE((TRACE_SIO,"GSIO: DevStatusVar=%X\n",SioDevStatusVar.DEV_STATUS));
+ return Status;
+}
+
+#endif //#if SIO_SUPPORT
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
diff --git a/Core/CORE_DXE/Image.c b/Core/CORE_DXE/Image.c
new file mode 100644
index 0000000..b98e31b
--- /dev/null
+++ b/Core/CORE_DXE/Image.c
@@ -0,0 +1,1710 @@
+/*++
+
+Copyright (c) 2004 - 2009, 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:
+
+ Image.c
+
+Abstract:
+
+ Core image handling services
+
+--*/
+
+#include "Image.h"
+#include "EfiHobLib.h"
+#include "EfiPerf.h"
+//*** AMI PORTING BEGIN ***//
+BOOLEAN gFillFpdt = FALSE;
+EFI_STATUS IsValidDevicePath(
+ IN EFI_DEVICE_PATH_PROTOCOL *pDp
+);
+//*** AMI PORTING END ***//
+//
+// Module Globals
+//
+
+LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;
+
+LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {
+ LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,
+ NULL,
+ CoreLoadImageEx,
+ CoreUnloadImageEx
+};
+
+
+//
+// This code is needed to build the Image handle for the DXE Core
+//
+LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {
+ LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature
+ NULL, // Image handle
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type
+ TRUE, // If entrypoint has been called
+ NULL, // EntryPoint
+ {
+ EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision
+ NULL, // Parent handle
+ NULL, // System handle
+
+ NULL, // Device handle
+ NULL, // File path
+ NULL, // Reserved
+
+ 0, // LoadOptionsSize
+ NULL, // LoadOptions
+
+ NULL, // ImageBase
+ 0, // ImageSize
+ EfiBootServicesCode, // ImageCodeType
+ EfiBootServicesData // ImageDataType
+ },
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ NULL, // Loaded Image Device Path
+#endif
+ (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage
+ 0, // NumberOfPages
+ NULL, // FixupData
+ 0, // Tpl
+ EFI_SUCCESS, // Status
+ 0, // ExitDataSize
+ NULL, // ExitData
+ NULL, // JumpContext
+ 0, // Machine
+ NULL, // Ebc
+ NULL, // RuntimeData
+};
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+CoreFlushICache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ );
+
+
+
+EFI_STATUS
+CoreInitializeImageServices (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Add the Image Services to EFI Boot Services Table and install the protocol
+ interfaces for this image.
+
+Arguments:
+
+ HobStart - The HOB to initialize
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;
+ UINT64 DxeCoreImageLength;
+ VOID *DxeCoreEntryPoint;
+//*** AMI PORTING BEGIN ***//
+//Bug fix: see comments below
+static EFI_GUID gDxeCoreFileNameBuffer;
+//*** AMI PORTING END *****//
+
+ //
+ // Searching for image hob
+ //
+ Status = GetDxeCoreHobInfo (
+ HobStart,
+ &DxeCoreImageBaseAddress,
+ &DxeCoreImageLength,
+ &DxeCoreEntryPoint,
+ &gDxeCoreFileName
+ );
+ ASSERT_EFI_ERROR (Status);
+//*** AMI PORTING BEGIN ***//
+//Bug fix: gDxeCoreFileName points to a data somewhere in the HOB list.
+//However, later on HOB list will be reallocated, which will make gDxeCoreFileName pointer invalid.
+//This is a patch. Copy DXE Core file name to a static variable and
+//update gDxeCoreFileName to point to it.
+ gDxeCoreFileNameBuffer = *gDxeCoreFileName;
+ gDxeCoreFileName=&gDxeCoreFileNameBuffer;
+//*** AMI PORTING END *****//
+
+ //
+ // Initialize the fields for an internal driver
+ //
+ Image = &mCorePrivateImage;
+
+ Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
+ Image->ImageBasePage = DxeCoreImageBaseAddress;
+ Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));
+ Image->Tpl = gEfiCurrentTpl;
+ Image->Info.SystemTable = gST;
+ Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;
+ Image->Info.ImageSize = DxeCoreImageLength;
+
+ //
+ // Install the protocol interfaces for this image
+ //
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Image->Info
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ if (!EFI_ERROR (Status)) {
+ Status = InstallCoreDebugMaskProtocol(Image->Handle);
+ ASSERT_EFI_ERROR (Status);
+ }
+ )
+
+ mCurrentImage = Image;
+
+ //
+ // Fill in DXE globals
+ //
+ gDxeCoreImageHandle = Image->Handle;
+ gDxeCoreLoadedImage = &Image->Info;
+
+ //
+ // Export DXE Core PE Loader functionality
+ //
+ return CoreInstallProtocolInterface (
+ &mLoadPe32PrivateData.Handle,
+ &gEfiLoadPeImageGuid,
+ EFI_NATIVE_INTERFACE,
+ &mLoadPe32PrivateData.Pe32Image
+ );
+}
+
+
+STATIC
+EFI_STATUS
+CoreLoadPeImage (
+ IN BOOLEAN BootPolicy,
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+Routine Description:
+
+ Loads, relocates, and invokes a PE/COFF image.
+
+Arguments:
+
+ Pe32Handle - The handle of PE32 image.
+ Image - PE image to be loaded.
+ DstBuffer - The buffer to store the image.
+ EntryPoint - A pointer to the entry point.
+ Attribute - The bit mask of attributes to set for the load PE image.
+ CrossLoad - Whether expect to support cross architecture loading.
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded, relocated, and invoked.
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_BUFFER_TOO_SMALL - Buffer for image is too small.
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN DstBufAlocated;
+ UINTN Size;
+ EFI_IMAGE_NT_HEADERS64 *PeHdr;
+ EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;
+ IMAGE_FILE_HANDLE *FHandle;
+ BOOLEAN NeedAllocateAddress;
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ BOOLEAN OffsetMode;
+ STATIC BOOLEAN PrintTopAddress = TRUE;
+#endif
+
+ DEBUG_CODE (
+ UINTN Index;
+ UINTN StartIndex;
+ CHAR8 EfiFileName[256];
+ )
+
+ EfiCommonLibZeroMem (&(Image->ImageContext), sizeof (Image->ImageContext));
+
+ Image->ImageContext.Handle = Pe32Handle;
+ Image->ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) CoreReadImageFile;
+
+ //
+ // Get information about the image being loaded.
+ //
+ Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &(Image->ImageContext));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check the processor architecture of the image
+ //
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ if (CrossLoad) {
+ if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Allocate memory of the correct memory type aligned on the required image boundary.
+ //
+ DstBufAlocated = FALSE;
+ if (DstBuffer == 0) {
+ //
+ // Allocate Destination Buffer as caller did not pass it in.
+ //
+
+ if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+ Size = (UINTN) Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
+ } else {
+ Size = (UINTN) Image->ImageContext.ImageSize;
+ }
+
+ Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
+ //
+ // Following code is to support load a PE image at fixed offset relative to TOLM
+ //
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ {
+ typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_PHYSICAL_ADDRESS MaximumAddress;
+ UINT64 CurrentNumberOfPages;
+ UINT64 NumberOfPages;
+ UINTN InformationIndex;
+ BOOLEAN Special;
+ BOOLEAN Runtime;
+ } EFI_MEMORY_TYPE_STAISTICS;
+
+
+ extern EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1];
+ INT32 Offset;
+ UINTN ReadSize = sizeof (UINT32);
+
+ if (PrintTopAddress) {
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Runtime code top address: %lX\n", mMemoryTypeStatistics[EfiRuntimeServicesCode].MaximumAddress + 1));
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Boot time code top address: %lX\n", mMemoryTypeStatistics[EfiBootServicesCode].MaximumAddress + 1));
+ PrintTopAddress = FALSE;
+ }
+ OffsetMode = FALSE;
+ Status = Image->ImageContext.ImageRead (
+ Image->ImageContext.Handle,
+ Image->ImageContext.PeCoffHeaderOffset + 12,
+ &ReadSize,
+ &Offset
+ );
+ if (!EFI_ERROR (Status) && Offset != 0 &&
+ Image->ImageContext.ImageCodeMemoryType != EfiLoaderCode) {
+ OffsetMode = TRUE;
+ Image->ImageContext.ImageAddress = mMemoryTypeStatistics[Image->ImageContext.ImageCodeMemoryType].MaximumAddress + 1 - Offset;
+ }
+ }
+#endif
+
+ //
+ // If the image relocations are stripped, or fixed address/offset feature is valid,
+ // try to load the image to the specified address first.
+ // Otherwise try to load the image at any page if image relocations are available.
+ //
+ NeedAllocateAddress = FALSE;
+ if (Image->ImageContext.RelocationsStripped) {
+ NeedAllocateAddress = TRUE;
+ }
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_ADDRESS
+ NeedAllocateAddress = TRUE;
+#endif
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ if (OffsetMode) {
+ NeedAllocateAddress = TRUE;
+ }
+#endif
+ Status = EFI_OUT_OF_RESOURCES;
+ if (NeedAllocateAddress) {
+ Status = CoreAllocatePages (
+ AllocateAddress,
+ Image->ImageContext.ImageCodeMemoryType,
+ Image->NumberOfPages,
+ &Image->ImageContext.ImageAddress
+ );
+#ifdef EFI_LOAD_DRIVER_AT_FIXED_OFFSET
+ if (EFI_ERROR (Status) && OffsetMode) {
+ DEBUG((EFI_D_ERROR, "\nOffset mode load failure!"));
+ }
+#endif
+ }
+ if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
+ Status = CoreAllocatePages (
+ AllocateAnyPages,
+ Image->ImageContext.ImageCodeMemoryType,
+ Image->NumberOfPages,
+ &Image->ImageContext.ImageAddress
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ DstBufAlocated = TRUE;
+ } else {
+ //
+ // Caller provided the destination buffer.
+ //
+
+ if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
+ //
+ // If the image relocations were stripped, and the caller provided a
+ // destination buffer address that does not match the address that the
+ // image is linked at, then the image cannot be loaded.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Size = EFI_SIZE_TO_PAGES ((UINTN) Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
+
+ if ((Image->NumberOfPages != 0) && (Image->NumberOfPages < Size)) {
+ Image->NumberOfPages = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Image->NumberOfPages = Size;
+ Image->ImageContext.ImageAddress = DstBuffer;
+ }
+
+ Image->ImageBasePage = Image->ImageContext.ImageAddress;
+ Image->ImageContext.ImageAddress =
+ (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
+ ~((UINTN) Image->ImageContext.SectionAlignment - 1);
+
+ //
+ // Load the image from the file into the allocated memory
+ //
+ Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &(Image->ImageContext));
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // If this is a Runtime Driver, then allocate memory for the FixupData that
+ // is used to relocate the image when SetVirtualAddressMap() is called. The
+ // relocation is done by the Runtime AP.
+ //
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
+ if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER &&
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
+ if (Image->ImageContext.FixupData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Measure the image before applying fixup
+ //
+ Status = CoreLocateProtocol (
+ &gEfiTcgPlatformProtocolGuid,
+ NULL,
+ &TcgPlatformProtocol
+ );
+ if (!EFI_ERROR (Status)) {
+ PeHdr = (EFI_IMAGE_NT_HEADERS64 *)(UINTN) (
+ Image->ImageContext.ImageAddress +
+ Image->ImageContext.PeCoffHeaderOffset
+ );
+ FHandle = (IMAGE_FILE_HANDLE *)Image->ImageContext.Handle;
+
+ Status = TcgPlatformProtocol->MeasurePeImage (
+ BootPolicy,
+ (EFI_PHYSICAL_ADDRESS)FHandle->Source,
+ FHandle->SourceSize,
+ (UINTN) PeHdr->OptionalHeader.ImageBase,
+ Image->ImageContext.ImageType,
+ Image->Info.DeviceHandle,
+ Image->Info.FilePath
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Relocate the image in memory
+ //
+ Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &(Image->ImageContext));
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Flush the Instruction Cache
+ //
+ Status = CoreFlushICache (Image->ImageContext.ImageAddress, Image->ImageContext.ImageSize);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Get the image entry point. If it's an EBC image, then call into the
+ // interpreter to create a thunk for the entry point and use the returned
+ // value for the entry point.
+ //
+ Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT) (UINTN) Image->ImageContext.EntryPoint;
+
+ //
+ // Copy the machine type from the context to the image private data. This
+ // is needed during image unload to know if we should call an EBC protocol
+ // to unload the image.
+ //
+ Image->Machine = Image->ImageContext.Machine;
+ if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {
+ //
+ // Locate the EBC interpreter protocol
+ //
+ Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, &Image->Ebc);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Register a callback for flushing the instruction cache so that created
+ // thunks can be flushed.
+ //
+ Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, CoreFlushICache);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Create a thunk for the image's entry point. This will be the new
+ // entry point for the image.
+ //
+ Status = Image->Ebc->CreateThunk (
+ Image->Ebc,
+ Image->Handle,
+ (VOID *)(UINTN)Image->ImageContext.EntryPoint,
+ (VOID **)&Image->EntryPoint
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Fill in the image information for the Loaded Image Protocol
+ //
+ Image->Type = Image->ImageContext.ImageType;
+ Image->Info.ImageBase = (VOID *) (UINTN) Image->ImageContext.ImageAddress;
+ Image->Info.ImageSize = Image->ImageContext.ImageSize;
+ Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;
+ Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;
+
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {
+ if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ //
+ // Make a list off all the RT images so we can let the RT AP know about them.
+ //
+ Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));
+ if (Image->RuntimeData == NULL) {
+ goto Done;
+ }
+ Image->RuntimeData->ImageBase = Image->Info.ImageBase;
+ Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);
+ Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
+ Image->RuntimeData->Handle = Image->Handle;
+ InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
+ }
+ }
+
+ //
+ // Fill in the entry point of the image if it is available
+ //
+ if (EntryPoint != NULL) {
+ *EntryPoint = Image->ImageContext.EntryPoint;
+ }
+
+ //
+ // Print the load address and the PDB file name if it is available
+ //
+
+ DEBUG_CODE (
+ {
+//*** AMI PORTING BEGIN ***//
+//The message is printed in CoreStartImage. Disable this one.
+/*
+ DEBUG ((
+ EFI_D_INFO | EFI_D_LOAD,
+ "Loading driver at 0x%x EntryPoint=0x%x ",
+ (UINTN) Image->ImageContext.ImageAddress,
+ (UINTN) Image->ImageContext.EntryPoint
+ ));
+*/
+//*** AMI PORTING END *****//
+ if (Image->ImageContext.PdbPointer != NULL) {
+ StartIndex = 0;
+ for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
+ if (Image->ImageContext.PdbPointer[Index] == '\\') {
+ StartIndex = Index + 1;
+ }
+ }
+ //
+ // Copy the PDB file name to our temporary string, and replace .pdb with .efi
+ //
+ for (Index = 0; Index < sizeof (EfiFileName); Index++) {
+ EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
+ if (EfiFileName[Index] == 0) {
+ EfiFileName[Index] = '.';
+ }
+ if (EfiFileName[Index] == '.') {
+ EfiFileName[Index + 1] = 'e';
+ EfiFileName[Index + 2] = 'f';
+ EfiFileName[Index + 3] = 'i';
+ EfiFileName[Index + 4] = 0;
+ break;
+ }
+ }
+//*** AMI PORTING BEGIN ***//
+//The message is printed in CoreStartImage. Disable this one.
+// DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName));
+//*** AMI PORTING END *****//
+
+ }
+//*** AMI PORTING BEGIN ***//
+//The message is printed in CoreStartImage. Disable this one.
+// DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
+//*** AMI PORTING END *****//
+
+ }
+ );
+
+ return EFI_SUCCESS;
+
+Done:
+
+ //
+ // Free memory.
+ //
+
+ if (DstBufAlocated) {
+ CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
+ }
+
+ if (Image->ImageContext.FixupData != NULL) {
+ CoreFreePool (Image->ImageContext.FixupData);
+ }
+
+ return Status;
+}
+
+
+LOADED_IMAGE_PRIVATE_DATA *
+CoreLoadedImageInfo (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Get the image's private data from its handle.
+
+Arguments:
+
+ ImageHandle - The image handle
+
+Returns:
+
+ Return the image private data associated with ImageHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Status = CoreHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ &LoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);
+ } else {
+ DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));
+ Image = NULL;
+ }
+
+ return Image;
+}
+
+
+EFI_STATUS
+CoreLoadImageCommon (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ IN OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image
+ NumberOfPages - If not NULL, on input a pointer to the page number of DstBuffer and on
+ output a pointer to the page number of the image. If this number of DstBuffer
+ is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain
+ the required number.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+ EntryPoint - A pointer to the entry point
+ Attribute - The bit mask of attributes to set for the load PE image
+ CrossLoad - Whether expect to support cross architecture loading
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_BUFFER_TOO_SMALL - The buffer is too small
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ LOADED_IMAGE_PRIVATE_DATA *ParentImage;
+ IMAGE_FILE_HANDLE FHand;
+ EFI_STATUS Status;
+ EFI_STATUS SecurityStatus;
+ EFI_HANDLE DeviceHandle;
+ UINT32 AuthenticationStatus;
+ EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;
+ EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
+ UINTN FilePathSize;
+
+ SecurityStatus = EFI_SUCCESS;
+
+ ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);
+ ParentImage = NULL;
+
+ //
+ // The caller must pass in a valid ParentImageHandle
+ //
+ if (ImageHandle == NULL || ParentImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentImage = CoreLoadedImageInfo (ParentImageHandle);
+ if (ParentImage == NULL) {
+ DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get simple read access to the source file
+ //
+ OriginalFilePath = FilePath;
+ Status = CoreOpenImageFile (
+ BootPolicy,
+ SourceBuffer,
+ SourceSize,
+ &FilePath,
+ &DeviceHandle,
+ &FHand,
+ &AuthenticationStatus
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ Image = NULL;
+ goto Done;
+ } else if (EFI_ERROR (Status)) {
+ return Status;
+ }
+//*** AMI PORTING BEGIN ***//
+ //
+ // Verify the Authentication Status through the Security2 Architectural Protocol
+ //
+ if ((gSecurity2 != NULL) && (OriginalFilePath != NULL)) {
+ SecurityStatus = gSecurity2->FileAuthentication (
+ gSecurity2,
+ OriginalFilePath,
+ FHand.Source,
+ FHand.SourceSize,
+ BootPolicy
+ );
+ if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {
+ Status = SecurityStatus;
+ Image = NULL;
+ goto Done;
+ }
+ }
+//*** AMI PORTING END ***//
+
+ //
+ // Allocate a new image structure
+ //
+ Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Pull out just the file portion of the DevicePath for the LoadedImage FilePath
+ //
+ FilePath = OriginalFilePath;
+ Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, &HandleFilePath);
+ if (!EFI_ERROR (Status)) {
+ FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+ FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );
+ }
+
+ //
+ // Initialize the fields for an internal driver
+ //
+ Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;
+ Image->Info.SystemTable = gST;
+ Image->Info.DeviceHandle = DeviceHandle;
+ Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
+ Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);
+ Image->Info.ParentHandle = ParentImageHandle;
+
+ if (NumberOfPages != NULL) {
+ Image->NumberOfPages = *NumberOfPages ;
+ } else {
+ Image->NumberOfPages = 0 ;
+ }
+
+ //
+ // Install the protocol interfaces for this image
+ // don't fire notifications yet
+ //
+ Status = CoreInstallProtocolInterfaceNotify (
+ &Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Image->Info,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Install Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ Status = InstallDebugMaskProtocol(Image->Handle);
+ ASSERT_EFI_ERROR (Status);
+ )
+
+ //
+ // Load the image. If EntryPoint is Null, it will not be set.
+ //
+ Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute, CrossLoad);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
+ if (NumberOfPages != NULL) {
+ *NumberOfPages = Image->NumberOfPages;
+ }
+ }
+ goto Done;
+ }
+ if (NumberOfPages != NULL) {
+ *NumberOfPages = Image->NumberOfPages;
+ }
+
+ //
+ // Register the image in the Debug Image Info Table if the attribute is set
+ //
+ if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {
+ CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
+ }
+
+ //
+ //Reinstall loaded image protocol to fire any notifications
+ //
+ Status = CoreReinstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ &Image->Info,
+ &Image->Info
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,
+ // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.
+ //
+ if (OriginalFilePath != NULL) {
+ Image->LoadedImageDevicePath = CoreDuplicateDevicePath (OriginalFilePath);
+ }
+
+ //
+ // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image
+ //
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ Image->LoadedImageDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Install HII Package List Protocol onto the image handle
+ //
+ if (Image->ImageContext.HiiResourceData != 0) {
+ Status = CoreInstallProtocolInterface (
+ &Image->Handle,
+ &gEfiHiiPackageListProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+#endif
+
+ //
+ // Success. Return the image handle
+ //
+ *ImageHandle = Image->Handle;
+
+Done:
+ //
+ // All done accessing the source file
+ // If we allocated the Source buffer, free it
+ //
+ if (FHand.FreeBuffer) {
+ CoreFreePool (FHand.Source);
+ }
+
+ //
+ // There was an error. If there's an Image structure, free it
+ //
+ if (EFI_ERROR (Status)) {
+ if (Image != NULL) {
+ CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));
+ *ImageHandle = NULL;
+ }
+ } else if (EFI_ERROR (SecurityStatus)) {
+ Status = SecurityStatus;
+ }
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLoadImage (
+ IN BOOLEAN BootPolicy,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ OUT EFI_HANDLE *ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image.
+
+Arguments:
+
+ BootPolicy - If TRUE, indicates that the request originates from the boot manager,
+ and that the boot manager is attempting to load FilePath as a boot selection.
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ ImageHandle - Pointer to the returned image handle that is created when the image
+ is successfully loaded.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ EFI_STATUS Status;
+//*** AMI PORTING BEGIN ***//
+//Verify that device path is sane
+ if(FilePath != NULL) {
+ Status = IsValidDevicePath(FilePath);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ if (BootPolicy){
+ AmiFillFpdt (FillOsLoaderLoadImageStart); // Fill OsLoaderLoadImageStart field in FPDT
+ gFillFpdt = TRUE;
+ }
+//*** AMI PORTING END ***//
+ PERF_START (NULL, L"LoadImage", NULL, 0);
+
+ Status = CoreLoadImageCommon (
+ BootPolicy,
+ ParentImageHandle,
+ FilePath,
+ SourceBuffer,
+ SourceSize,
+ (EFI_PHYSICAL_ADDRESS)NULL,
+ NULL,
+ ImageHandle,
+ NULL,
+ EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION,
+ FALSE
+ );
+
+ if (!EFI_ERROR (Status)) {
+ PERF_UPDATE (0, L"LoadImage", NULL, *ImageHandle, L"LoadImage", NULL);
+ PERF_END (*ImageHandle, L"LoadImage", NULL, 0);
+ } else {
+ PERF_UPDATE (0, L"LoadImage", NULL, 0, L"Load Failed", L"CoreLoadImage");
+ PERF_END (0, L"Load Failed", L"CoreLoadImage", 0);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreLoadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image with extended parameters.
+
+Arguments:
+
+ This - Calling context
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image.
+ NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
+ For output, specifies the actual space size needed.
+ ImageHandle - Image handle for output.
+ EntryPoint - Image entry point for output.
+ Attribute - The bit mask of attributes to set for the load PE image.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+{
+ return CoreLoadImageCommon (
+ FALSE,
+ ParentImageHandle,
+ FilePath,
+ SourceBuffer,
+ SourceSize,
+ DstBuffer,
+ NumberOfPages,
+ ImageHandle,
+ EntryPoint,
+ Attribute,
+ TRUE
+ );
+}
+
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreStartImage (
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Transfer control to a loaded image's entry point.
+
+Arguments:
+
+ ImageHandle - Handle of image to be started.
+
+ ExitDataSize - Pointer of the size to ExitData
+
+ ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated
+ Unicode string, optionally followed by additional binary data. The string
+ is a description that the caller may use to further indicate the reason for
+ the image's exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully transfer control to the image's entry point.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+ LOADED_IMAGE_PRIVATE_DATA *LastImage;
+ UINT64 HandleDatabaseKey;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL_HANDLE || Image->Started) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Cannot start image of an unsupported processor architecture
+ //
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Don't profile Objects or invalid start requests
+ //
+//*** AMI PORTING BEGIN ***//
+ if (gFillFpdt)
+ {
+ AmiFillFpdt (FillOsLoaderStartImageStart); // Fill OsLoaderStartImageStart field in FPDT
+ gFillFpdt = FALSE;
+ }
+//*** AMI PORTING END ***//
+ PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);
+
+ //
+ // Push the current start image context, and
+ // link the current image to the head. This is the
+ // only image that can call Exit()
+ //
+ HandleDatabaseKey = CoreGetHandleDatabaseKey();
+ LastImage = mCurrentImage;
+ mCurrentImage = Image;
+ Image->Tpl = gEfiCurrentTpl;
+
+ //
+ // Set long jump for Exit() support
+ //
+ Image->JumpContext = CoreAllocateBootServicesPool (gEfiPeiTransferControl->JumpContextSize);
+ if (Image->JumpContext == NULL) {
+ PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gEfiPeiTransferControl->SetJump (gEfiPeiTransferControl, Image->JumpContext);
+ //
+ // The SetJump returns EFI_SUCCESS when LongJump Buffer has been armed
+ // SetJump returns EFI_WARN_RETURN_FROM_LONG_JUMP as a result of the LongJump
+ // All other return values for SetJump are undefined.
+ //
+ if (Status == EFI_SUCCESS) {
+
+ //
+ // Call the image's entry point
+ //
+ Image->Started = TRUE;
+//*** AMI PORTING BEGIN ***//
+#ifdef EFI_DEBUG
+{
+//Debug message: name/entry point of the module being started
+BOOLEAN GetImageName(EFI_HANDLE ImageHandle, CHAR8 *sName);
+VOID Trace(UINTN Level, CHAR8 *sFormat,...);
+CHAR8 sName[0x100];
+
+ GetImageName(ImageHandle,sName);
+ Trace(-1, "%s.Entry(%X)\n", sName, Image->EntryPoint);
+#endif
+{ // Report Status Code
+ static EFI_DEVICE_HANDLE_EXTENDED_DATA DeviceHandleExtData = {
+ {
+ sizeof(EFI_STATUS_CODE_DATA),
+ sizeof(EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof(EFI_STATUS_CODE_DATA),
+ EFI_STATUS_CODE_SPECIFIC_DATA_GUID
+ },
+ 0
+ };
+
+ DeviceHandleExtData.Handle = ImageHandle;
+ LibReportStatusCode(
+ EFI_PROGRESS_CODE,
+ EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN,
+ 0,
+ &gEfiDxeServicesTableGuid,
+ &DeviceHandleExtData.DataHeader
+ );
+}
+//*** AMI PORTING END *****//
+ Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
+//*** AMI PORTING BEGIN ***//
+#ifdef EFI_DEBUG
+ if (EFI_ERROR(Image->Status)&&Image->Status!=EFI_UNLOAD_IMAGE) Trace(-1, "ERROR: %s.Entry(%X)=%r\n", sName, Image->EntryPoint, Image->Status);
+}
+#endif
+
+ //
+ // Add some debug information if the image returned with error.
+ // This make the user aware and check if the driver image have already released
+ // all the resource in this situation.
+ //
+/* Comment out original message.
+ DEBUG_CODE (
+ if (EFI_ERROR (Image->Status)) {
+ DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));
+ }
+ )
+*/
+//*** AMI PORTING END *****//
+ //
+ // If the image returns, exit it through Exit()
+ //
+ CoreExit (ImageHandle, Image->Status, 0, NULL);
+ }
+
+ //
+ // Image has completed. Verify the tpl is the same
+ //
+ ASSERT (Image->Tpl == gEfiCurrentTpl);
+ CoreRestoreTpl (Image->Tpl);
+
+ CoreFreePool (Image->JumpContext);
+
+ //
+ // Pop the current start image context
+ //
+ mCurrentImage = LastImage;
+
+ //
+ // Go connect any handles that were created or modified while the image executed.
+ //
+ CoreConnectHandlesByKey (HandleDatabaseKey);
+
+ //
+ // Handle the image's returned ExitData
+ //
+ DEBUG_CODE (
+ if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {
+
+ DEBUG (
+ (EFI_D_LOAD,
+ "StartImage: ExitDataSize %d, ExitData %x",
+ Image->ExitDataSize,
+ Image->ExitData)
+ );
+ if (Image->ExitData != NULL) {
+ DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));
+ }
+ DEBUG ((EFI_D_LOAD, "\n"));
+ }
+ )
+
+ //
+ // Return the exit data to the caller
+ //
+ if (ExitData != NULL && ExitDataSize != NULL) {
+ *ExitDataSize = Image->ExitDataSize;
+ *ExitData = Image->ExitData;
+ } else {
+ //
+ // Caller doesn't want the exit data, free it
+ //
+ CoreFreePool (Image->ExitData);
+ Image->ExitData = NULL;
+ }
+
+ //
+ // Save the Status because Image will get destroyed if it is unloaded.
+ //
+ Status = Image->Status;
+
+ //
+ // If the image returned an error, or if the image is an application
+ // unload it
+ //
+ if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+ CoreUnloadAndCloseImage (Image, TRUE);
+ }
+
+ //
+ // Done
+ //
+ PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);
+ return Status;
+}
+
+
+VOID
+CoreUnloadAndCloseImage (
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN BOOLEAN FreePage
+ )
+/*++
+
+Routine Description:
+
+ Unloads EFI image from memory.
+
+Arguments:
+
+ Image - EFI image
+ FreePage - Free allocated pages
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleIndex;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+
+ if (Image->Ebc != NULL) {
+ //
+ // If EBC protocol exists we must perform cleanups for this image.
+ //
+ Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);
+ }
+
+ //
+ // Unload image, free Image->ImageContext->ModHandle
+ //
+ gEfiPeiPeCoffLoader->UnloadImage (&Image->ImageContext);
+
+ //
+ // Free our references to the image handle
+ //
+ if (Image->Handle != NULL_HANDLE) {
+
+ Status = CoreLocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Status = CoreProtocolsPerHandle (
+ HandleBuffer[HandleIndex],
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+ Status = CoreOpenProtocolInformation (
+ HandleBuffer[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
+ Status = CoreCloseProtocol (
+ HandleBuffer[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ Image->Handle,
+ OpenInfo[OpenInfoIndex].ControllerHandle
+ );
+ }
+ }
+ if (OpenInfo != NULL) {
+ CoreFreePool(OpenInfo);
+ }
+ }
+ }
+ if (ProtocolGuidArray != NULL) {
+ CoreFreePool(ProtocolGuidArray);
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ CoreFreePool (HandleBuffer);
+ }
+ }
+
+ CoreRemoveDebugImageInfoEntry (Image->Handle);
+
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageProtocolGuid,
+ &Image->Info
+ );
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ Image->LoadedImageDevicePath
+ );
+
+ if (Image->LoadedImageDevicePath != NULL) {
+ CoreFreePool (Image->LoadedImageDevicePath);
+ }
+
+ if (Image->ImageContext.HiiResourceData != 0) {
+ Status = CoreUninstallProtocolInterface (
+ Image->Handle,
+ &gEfiHiiPackageListProtocolGuid,
+ (VOID *) (UINTN) Image->ImageContext.HiiResourceData
+ );
+ }
+#endif
+
+ //
+ // Uninstall Debug Mask Protocol
+ //
+ DEBUG_CODE (
+ Status = UninstallDebugMaskProtocol(Image->Handle);
+ ASSERT_EFI_ERROR (Status);
+ )
+
+ }
+
+ if (Image->RuntimeData != NULL) {
+ if (Image->RuntimeData->Link.ForwardLink != NULL) {
+ //
+ // Remove the Image from the Runtime Image list as we are about to Free it!
+ //
+ RemoveEntryList (&Image->RuntimeData->Link);
+ }
+ CoreFreePool (Image->RuntimeData);
+ }
+
+ //
+ // Free the Image from memory
+ //
+ if ((Image->ImageBasePage != 0) && FreePage) {
+ CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
+ }
+
+ //
+ // Done with the Image structure
+ //
+ if (Image->Info.FilePath != NULL) {
+ CoreFreePool (Image->Info.FilePath);
+ }
+
+ if (Image->FixupData != NULL) {
+ CoreFreePool (Image->FixupData);
+ }
+
+ CoreFreePool (Image);
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_STATUS Status,
+ IN UINTN ExitDataSize,
+ IN CHAR16 *ExitData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Terminates the currently loaded EFI image and returns control to boot services.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image. This parameter is passed to the image
+ on entry.
+ Status - The image's exit code.
+ ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is
+ EFI_SUCCESS.
+ ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,
+ optionally followed by additional binary data. The string is a
+ description that the caller may use to further indicate the reason for
+ the image's exit.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.
+
+ EFI_SUCCESS - Successfully terminates the currently loaded EFI image.
+
+ EFI_ACCESS_DENIED - Should never reach there.
+
+ EFI_OUT_OF_RESOURCES - Could not allocate pool
+
+--*/
+{
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL_HANDLE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Image->Started) {
+ //
+ // The image has not been started so just free its resources
+ //
+ CoreUnloadAndCloseImage (Image, TRUE);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Image has been started, verify this image can exit
+ //
+ if (Image != mCurrentImage) {
+ DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set status
+ //
+ Image->Status = Status;
+
+ //
+ // If there's ExitData info, move it
+ //
+ if (ExitData != NULL) {
+ Image->ExitDataSize = ExitDataSize;
+ Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);
+ if (Image->ExitData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ EfiCommonLibCopyMem (Image->ExitData, ExitData, Image->ExitDataSize);
+ }
+
+ //
+ // return to StartImage
+ //
+ Status = gEfiPeiTransferControl->LongJump (gEfiPeiTransferControl, Image->JumpContext);
+
+ //
+ // If we return from LongJump, then it is an error
+ //
+ ASSERT (FALSE);
+ return EFI_ACCESS_DENIED;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unloads an image.
+
+Arguments:
+
+ ImageHandle - Handle that identifies the image to be unloaded.
+
+Returns:
+
+ EFI_SUCCESS - The image has been unloaded.
+ EFI_UNSUPPORTED - The image has been sarted, and does not support unload.
+ EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOADED_IMAGE_PRIVATE_DATA *Image;
+
+ Image = CoreLoadedImageInfo (ImageHandle);
+ if (Image == NULL ) {
+ //
+ // The image handle is not valid
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Image->Started) {
+ //
+ // The image has been started, request it to unload.
+ //
+ Status = EFI_UNSUPPORTED;
+ if (Image->Info.Unload != NULL) {
+ Status = Image->Info.Unload (ImageHandle);
+ }
+
+ } else {
+ //
+ // This Image hasn't been started, thus it can be unloaded
+ //
+ Status = EFI_SUCCESS;
+ }
+
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // if the Image was not started or Unloaded O.K. then clean up
+ //
+ CoreUnloadAndCloseImage (Image, TRUE);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ This - Indicates the calling context.
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+{
+ return CoreUnloadImage (ImageHandle);
+}
+
+
+
+//
+// This callback function is used by the EBC interpreter driver to flush the
+// processor instruction cache after creating thunks. We're simply hiding
+// the "this" pointer that must be passed into the real flush function.
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CoreFlushICache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ flush the processor instruction cache.
+
+Arguments:
+
+ Start - Start adddress in memory to flush.
+
+ Length - Length of memory to flush.
+
+Returns:
+
+--*/
+{
+ return gEfiPeiFlushInstructionCache->Flush (
+ gEfiPeiFlushInstructionCache,
+ Start,
+ Length
+ );
+}
+
+
diff --git a/Core/CORE_DXE/Image.h b/Core/CORE_DXE/Image.h
new file mode 100644
index 0000000..9679e1b
--- /dev/null
+++ b/Core/CORE_DXE/Image.h
@@ -0,0 +1,400 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Image.h
+
+Abstract:
+
+ EFI image loader
+
+--*/
+
+
+#ifndef _IMAGE_H_
+#define _IMAGE_H_
+
+
+#include "Tiano.h"
+#include "LinkedList.h"
+#include "DxeCore.h"
+
+#include EFI_PROTOCOL_PRODUCER (LoadedImage)
+#include EFI_PROTOCOL_PRODUCER (LoadPe32Image)
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#include EFI_PROTOCOL_PRODUCER (LoadedImageDevicePath)
+#include EFI_PROTOCOL_CONSUMER (LoadFile2)
+#include EFI_PROTOCOL_PRODUCER (HiiPackageList)
+#endif
+
+#include EFI_PROTOCOL_CONSUMER (Ebc)
+#include EFI_PROTOCOL_CONSUMER (SimpleFileSystem)
+#include EFI_PROTOCOL_CONSUMER (FileInfo)
+#include EFI_PROTOCOL_CONSUMER (LoadFile)
+#include EFI_PROTOCOL_CONSUMER (FirmwareVolume)
+#include EFI_PROTOCOL_CONSUMER (FirmwareVolume2)
+
+#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','d','r','i')
+
+typedef struct {
+ UINTN Signature; // Data Signature
+ EFI_HANDLE Handle; // Image handle
+ UINTN Type; // Image type
+
+ BOOLEAN Started; // If entrypoint has been called
+
+ EFI_IMAGE_ENTRY_POINT EntryPoint; // The image's entry point
+ EFI_LOADED_IMAGE_PROTOCOL Info; // loaded image protocol
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; // Loaded Image Device Path Protocl pointer
+#endif
+
+ EFI_PHYSICAL_ADDRESS ImageBasePage; // Location in memory
+ UINTN NumberOfPages; // Number of pages
+
+ CHAR8 *FixupData; // Original fixup data
+
+ EFI_TPL Tpl; // Tpl of started image
+ EFI_STATUS Status; // Status returned by started image
+
+ UINTN ExitDataSize; // Size of ExitData from started image
+ VOID *ExitData; // Pointer to exit data from started image
+ VOID *JumpContext; // Pointer to buffer for context save/retore
+ UINT16 Machine; // Machine type from PE image
+
+ EFI_EBC_PROTOCOL *Ebc; // EBC Protocol pointer
+
+ EFI_RUNTIME_IMAGE_ENTRY *RuntimeData; // Runtime image list
+
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; // PeCoffLoader ImageContext
+} LOADED_IMAGE_PRIVATE_DATA;
+
+#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
+
+
+#define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','p','e','i')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_PE32_IMAGE_PROTOCOL Pe32Image;
+} LOAD_PE32_IMAGE_PRIVATE_DATA;
+
+#define LOAD_PE32_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, LOAD_PE32_IMAGE_PRIVATE_DATA, Pe32Image, LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE)
+
+//
+// Private Data Types
+//
+#define IMAGE_FILE_HANDLE_SIGNATURE EFI_SIGNATURE_32('i','m','g','f')
+typedef struct {
+ UINTN Signature;
+ BOOLEAN FreeBuffer;
+ VOID *Source;
+ UINTN SourceSize;
+} IMAGE_FILE_HANDLE;
+
+
+//
+// Abstractions for reading image contents
+//
+
+EFI_STATUS
+CoreOpenImageFile (
+ IN BOOLEAN BootPolicy,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ IN IMAGE_FILE_HANDLE *ImageFileHandle,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+
+ Opens a file for (simple) reading. The simple read abstraction
+ will access the file either from a memory copy, from a file
+ system interface, or from the load file interface.
+
+Arguments:
+
+ BootPolicy - Policy for Open Image File.
+ SourceBuffer - Pointer to the memory location containing copy
+ of the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ FilePath - The specific file path from which the image is loaded
+ DeviceHandle - Pointer to the return device handle.
+ ImageFileHandle - Pointer to the image file handle.
+ AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
+
+Returns:
+
+ A handle to access the file
+
+--*/
+;
+
+
+EFI_STATUS
+EFIAPI
+CoreReadImageFile (
+ IN VOID *UserHandle,
+ IN UINTN Offset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Read image file (specified by UserHandle) into user specified buffer with specified offset
+ and length.
+
+Arguments:
+
+ UserHandle - Image file handle
+
+ Offset - Offset to the source file
+
+ ReadSize - For input, pointer of size to read;
+ For output, pointer of size actually read.
+
+ Buffer - Buffer to write into
+
+Returns:
+
+ EFI_SUCCESS - Successfully read the specified part of file into buffer.
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreCloseImageFile (
+ IN IMAGE_FILE_HANDLE *ImageFileHandle
+ )
+/*++
+
+Routine Description:
+
+ A function out of date, should be removed.
+
+Arguments:
+
+ ImageFileHandle - Handle of the file to close
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// Image processing worker functions
+//
+EFI_STATUS
+CoreDevicePathToInterface (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT VOID **Interface,
+ OUT EFI_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Search a handle to a device on a specified device path that supports a specified protocol,
+ interface of that protocol on that handle is another output.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ FilePath - The specified device path
+
+ Interface - Interface of the protocol on the handle
+
+ Handle - The handle to the device on the specified device path that supports the protocol.
+
+Returns:
+
+ Status code.
+
+--*/
+;
+
+STATIC
+EFI_STATUS
+CoreLoadPeImage (
+ IN BOOLEAN BootPolicy,
+ IN VOID *Pe32Handle,
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute,
+ IN BOOLEAN CrossLoad
+ )
+/*++
+
+Routine Description:
+
+ Loads, relocates, and invokes a PE/COFF image
+
+Arguments:
+
+ Pe32Handle - The handle of PE32 image
+ Image - PE image to be loaded
+ DstBuffer - The buffer to store the image
+ EntryPoint - A pointer to the entry point
+ Attribute - The bit mask of attributes to set for the load PE image
+ CrossLoad - Whether expect to support cross architecture loading
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded, relocated, and invoked
+
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_BUFFER_TOO_SMALL - Buffer for image is too small
+
+--*/
+;
+
+LOADED_IMAGE_PRIVATE_DATA *
+CoreLoadedImageInfo (
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+CoreUnloadAndCloseImage (
+ IN LOADED_IMAGE_PRIVATE_DATA *Image,
+ IN BOOLEAN FreePage
+ )
+/*++
+
+Routine Description:
+
+ Unloads EFI image from memory.
+
+Arguments:
+
+ Image - EFI image
+ FreePage - Free allocated pages
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+//
+// Exported Image functions
+//
+
+EFI_STATUS
+EFIAPI
+CoreLoadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ParentImageHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,
+ OUT UINTN *NumberOfPages OPTIONAL,
+ OUT EFI_HANDLE *ImageHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,
+ IN UINT32 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Loads an EFI image into memory and returns a handle to the image with extended parameters.
+
+Arguments:
+
+ ParentImageHandle - The caller's image handle.
+ FilePath - The specific file path from which the image is loaded.
+ SourceBuffer - If not NULL, a pointer to the memory location containing a copy of
+ the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ DstBuffer - The buffer to store the image.
+ NumberOfPages - For input, specifies the space size of the image by caller if not NULL.
+ For output, specifies the actual space size needed.
+ ImageHandle - Image handle for output.
+ EntryPoint - Image entry point for output.
+ Attribute - The bit mask of attributes to set for the load PE image.
+
+Returns:
+
+ EFI_SUCCESS - The image was loaded into memory.
+ EFI_NOT_FOUND - The FilePath was not found.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+ EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be
+ parsed to locate the proper protocol for loading the file.
+ EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CoreUnloadImageEx (
+ IN EFI_PE32_IMAGE_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Unload the specified image.
+
+Arguments:
+
+ This - Indicates the calling context.
+
+ ImageHandle - The specified image handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Image handle is NULL.
+
+ EFI_UNSUPPORTED - Attempt to unload an unsupported image.
+
+ EFI_SUCCESS - Image successfully unloaded.
+
+--*/
+;
+#endif
diff --git a/Core/CORE_DXE/ImageFile.c b/Core/CORE_DXE/ImageFile.c
new file mode 100644
index 0000000..0d36b7e
--- /dev/null
+++ b/Core/CORE_DXE/ImageFile.c
@@ -0,0 +1,639 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ ImageFile.c
+
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include "Image.h"
+#include "DxeCore.h"
+
+
+VOID
+CoreDevicePathToFileName (
+ IN FILEPATH_DEVICE_PATH *FilePath,
+ OUT CHAR16 **String
+ );
+
+
+
+EFI_STATUS
+CoreOpenImageFile (
+ IN BOOLEAN BootPolicy,
+ IN VOID *SourceBuffer OPTIONAL,
+ IN UINTN SourceSize,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ IN IMAGE_FILE_HANDLE *ImageFileHandle,
+ OUT UINT32 *AuthenticationStatus
+ )
+/*++
+
+Routine Description:
+
+ Opens a file for (simple) reading. The simple read abstraction
+ will access the file either from a memory copy, from a file
+ system interface, or from the load file interface.
+
+Arguments:
+
+ BootPolicy - Policy for Open Image File.
+ SourceBuffer - Pointer to the memory location containing copy
+ of the image to be loaded.
+ SourceSize - The size in bytes of SourceBuffer.
+ FilePath - The specific file path from which the image is loaded
+ DeviceHandle - Pointer to the return device handle.
+ ImageFileHandle - Pointer to the image file handle.
+ AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
+
+Returns:
+
+ EFI_SUCCESS - Image file successfully opened.
+
+ EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.
+
+ EFI_INVALID_PARAMETER - File path is not valid.
+
+ EFI_NOT_FOUND - File not found.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TempFilePath;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+ EFI_FILE_HANDLE FileHandle;
+ EFI_FILE_HANDLE LastHandle;
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_LOAD_FILE2_PROTOCOL *LoadFile2;
+#endif
+ EFI_SECTION_TYPE SectionType;
+ UINT8 *Pe32Buffer;
+ UINTN Pe32BufferSize;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attrib;
+ EFI_FILE_INFO *FileInfo;
+ UINTN FileInfoSize;
+ EFI_GUID *NameGuid;
+ FILEPATH_DEVICE_PATH *OriginalFilePathNode;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+#else
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+#endif
+
+ *AuthenticationStatus = 0;
+ EfiCommonLibZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));
+ ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;
+
+ //
+ // If the caller passed a copy of the file, then just use it
+ //
+ if (SourceBuffer != NULL) {
+ ImageFileHandle->Source = SourceBuffer;
+ ImageFileHandle->SourceSize = SourceSize;
+ *DeviceHandle = NULL;
+ CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, FilePath, DeviceHandle);
+ if (SourceSize > 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_LOAD_ERROR;
+ }
+ goto Done;
+ }
+
+ //
+ // Make sure FilePath is valid
+ //
+ if (*FilePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if it's in a Firmware Volume
+ //
+ FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) *FilePath;
+ Status = CoreDevicePathToInterface (
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+ #else
+ &gEfiFirmwareVolume2ProtocolGuid,
+ #endif
+ (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,
+ (VOID*)&FwVol,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // For FwVol File system there is only a single file name that is a GUID.
+ //
+ NameGuid = CoreGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);
+ if (NameGuid != NULL) {
+
+ SectionType = EFI_SECTION_PE32;
+ Pe32Buffer = NULL;
+ Status = FwVol->ReadSection (
+ FwVol,
+ &FwVolFilePathNode->NameGuid,
+ SectionType,
+ 0,
+ &Pe32Buffer,
+ &Pe32BufferSize,
+ AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Try a raw file, since a PE32 SECTION does not exist
+ //
+ if (Pe32Buffer != NULL) {
+ CoreFreePool (Pe32Buffer);
+ *AuthenticationStatus = 0;
+ }
+ Pe32Buffer = NULL;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &FwVolFilePathNode->NameGuid,
+ &Pe32Buffer,
+ &Pe32BufferSize,
+ &Type,
+ &Attrib,
+ AuthenticationStatus
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // One of the reads passed so we are done
+ //
+ ImageFileHandle->Source = Pe32Buffer;
+ ImageFileHandle->SourceSize = Pe32BufferSize;
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // Attempt to access the file via a file system interface
+ //
+ FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiSimpleFileSystemProtocolGuid,
+ (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,
+ (VOID*)&Volume,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Open the Volume to get the File System handle
+ //
+ Status = Volume->OpenVolume (Volume, &FileHandle);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Duplicate the device path to avoid the access to unaligned device path node.
+ // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
+ // nodes, It assures the fields in device path nodes are 2 byte aligned.
+ //
+ FilePathNode = (FILEPATH_DEVICE_PATH *) CoreDuplicateDevicePath(
+ (EFI_DEVICE_PATH_PROTOCOL *)(UINTN)FilePathNode
+ );
+ if (FilePathNode == NULL) {
+ FileHandle->Close (FileHandle);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ OriginalFilePathNode = FilePathNode;
+ //
+ // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
+ // directory information and filename can be seperate. The goal is to inch
+ // our way down each device path node and close the previous node
+ //
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Exit loop on Error
+ //
+ break;
+ }
+
+ LastHandle = FileHandle;
+ FileHandle = NULL;
+ Status = LastHandle->Open (
+ LastHandle,
+ &FileHandle,
+ FilePathNode->PathName,
+ EFI_FILE_MODE_READ,
+ 0
+ );
+
+ //
+ // Close the previous node
+ //
+ LastHandle->Close (LastHandle);
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+ //
+ // Free the allocated memory pool
+ //
+ CoreFreePool (OriginalFilePathNode);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // We have found the file. Now we need to read it. Before we can read the file we need to
+ // figure out how big the file is.
+ //
+ FileInfo = NULL;
+ FileInfoSize = sizeof (EFI_FILE_INFO);
+ while (CoreGrowBuffer (&Status, &FileInfo, FileInfoSize)) {
+ //
+ // Automatically allocate buffer of the correct size and make the call
+ //
+ Status = FileHandle->GetInfo (
+ FileHandle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo
+ );
+ }
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocate space for the file
+ //
+ ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize);
+ if (ImageFileHandle->Source != NULL) {
+ //
+ // Read the file into the buffer we allocated
+ //
+ ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize;
+ ImageFileHandle->FreeBuffer = TRUE;
+ Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);
+
+ //
+ // Close the file since we are done
+ //
+ FileHandle->Close (FileHandle);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ goto Done;
+ }
+ }
+ }
+ }
+
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Try LoadFile2 style
+ //
+ if (!BootPolicy) {
+ TempFilePath = *FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiLoadFile2ProtocolGuid,
+ &TempFilePath,
+ (VOID*)&LoadFile2,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Call LoadFile2 with the correct buffer size
+ //
+ while (CoreGrowBuffer (&Status, &ImageFileHandle->Source, ImageFileHandle->SourceSize)) {
+ Status = LoadFile2->LoadFile (
+ LoadFile2,
+ TempFilePath,
+ BootPolicy,
+ &ImageFileHandle->SourceSize,
+ ImageFileHandle->Source
+ );
+ //
+ // If success or other error happens, stop loop
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ break;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+ }
+#endif
+
+ //
+ // Try LoadFile style
+ //
+ TempFilePath = *FilePath;
+ Status = CoreDevicePathToInterface (
+ &gEfiLoadFileProtocolGuid,
+ &TempFilePath,
+ (VOID*)&LoadFile,
+ DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Call LoadFile with the correct buffer size
+ //
+ while (CoreGrowBuffer (&Status, &ImageFileHandle->Source, ImageFileHandle->SourceSize)) {
+ Status = LoadFile->LoadFile (
+ LoadFile,
+ TempFilePath,
+ BootPolicy,
+ &ImageFileHandle->SourceSize,
+ ImageFileHandle->Source
+ );
+ //
+ // If success or other error happens, stop loop
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ break;
+ }
+ }
+
+ if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {
+ ImageFileHandle->FreeBuffer = TRUE;
+ goto Done;
+ }
+ }
+
+ //
+ // Nothing else to try
+ //
+ DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));
+ Status = EFI_NOT_FOUND;
+
+Done:
+
+ //
+ // If the file was not accessed, clean up
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ if (ImageFileHandle->FreeBuffer) {
+ //
+ // Free the source buffer if we allocated it
+ //
+ CoreFreePool (ImageFileHandle->Source);
+ }
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CoreReadImageFile (
+ IN VOID *UserHandle,
+ IN UINTN Offset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Read image file (specified by UserHandle) into user specified buffer with specified offset
+ and length.
+
+Arguments:
+
+ UserHandle - Image file handle
+
+ Offset - Offset to the source file
+
+ ReadSize - For input, pointer of size to read;
+ For output, pointer of size actually read.
+
+ Buffer - Buffer to write into
+
+Returns:
+
+ EFI_SUCCESS - Successfully read the specified part of file into buffer.
+
+--*/
+{
+ UINTN EndPosition;
+ IMAGE_FILE_HANDLE *FHand;
+
+ FHand = (IMAGE_FILE_HANDLE *)UserHandle;
+ ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
+
+ //
+ // Move data from our local copy of the file
+ //
+ EndPosition = Offset + *ReadSize;
+ if (EndPosition > FHand->SourceSize) {
+ *ReadSize = (UINT32)(FHand->SourceSize - Offset);
+ }
+ if (Offset >= FHand->SourceSize) {
+ *ReadSize = 0;
+ }
+
+ EfiCommonLibCopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreDevicePathToInterface (
+ IN EFI_GUID *Protocol,
+ IN EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT VOID **Interface,
+ OUT EFI_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Search a handle to a device on a specified device path that supports a specified protocol,
+ interface of that protocol on that handle is another output.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ FilePath - The specified device path
+
+ Interface - Interface of the protocol on the handle
+
+ Handle - The handle to the device on the specified device path that supports the protocol.
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreLocateDevicePath (Protocol, FilePath, Handle);
+ if (!EFI_ERROR (Status)) {
+ Status = CoreHandleProtocol (*Handle, Protocol, Interface);
+ }
+ return Status;
+}
+
+
+VOID
+CoreDevicePathToFileName (
+ IN FILEPATH_DEVICE_PATH *FilePath,
+ OUT CHAR16 **String
+ )
+/*++
+
+Routine Description:
+
+ Transfer a device's full path a string.
+
+Arguments:
+
+ FilePath - Device path
+
+ String - The string represent the device's full path
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN StringSize;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ CHAR16 *Str;
+
+ *String = NULL;
+ StringSize = 0;
+ FilePathNode = FilePath;
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+
+ //
+ // For filesystem access each node should be a filepath component
+ //
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {
+
+ return;
+ }
+
+ StringSize += EfiStrLen (FilePathNode->PathName);
+
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+
+ *String = CoreAllocateBootServicesPool (StringSize);
+ if (*String == NULL) {
+ return;
+ }
+
+ FilePathNode = FilePath;
+ Str = *String;
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {
+ EfiStrCat (Str, FilePathNode->PathName);
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);
+ }
+}
+
+
+BOOLEAN
+CoreGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+Arguments:
+
+ Status - Current status
+
+ Buffer - Current allocated buffer, or NULL
+
+ BufferSize - Current buffer size needed
+
+Returns:
+
+ TRUE - if the buffer was reallocated and the caller
+ should try the API again.
+
+ FALSE - buffer could not be allocated and the caller
+ should not try the API again.
+
+--*/
+{
+ BOOLEAN TryAgain;
+
+ TryAgain = FALSE;
+ //
+ // If this is an initial request, buffer will be null with a new buffer size
+ //
+ if (*Buffer == NULL) {
+ *Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (BufferSize == 0) {
+ return TRUE;
+ }
+
+ //
+ // If the status code is "buffer too small", resize the buffer
+ //
+
+ if (*Status == EFI_BUFFER_TOO_SMALL) {
+ if (*Buffer != NULL) {
+ CoreFreePool (*Buffer);
+ }
+
+ *Buffer = CoreAllocateBootServicesPool (BufferSize);
+ if (*Buffer != NULL) {
+ TryAgain = TRUE;
+ } else {
+ *Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // If there's an error, free the buffer
+ //
+ if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) {
+ CoreFreePool (*Buffer);
+ *Buffer = NULL;
+ }
+
+ return TryAgain;
+}
+
diff --git a/Core/CORE_DXE/InstallConfigurationTable.c b/Core/CORE_DXE/InstallConfigurationTable.c
new file mode 100644
index 0000000..8aea9bc
--- /dev/null
+++ b/Core/CORE_DXE/InstallConfigurationTable.c
@@ -0,0 +1,230 @@
+/*++
+
+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:
+
+ InstallConfigurationTable.c
+
+
+Abstract:
+
+ Tiano Miscellaneous Services InstallConfigurationTable service
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+#define CONFIG_TABLE_SIZE_INCREASED 0x10
+
+UINTN mSystemTableAllocateSize = 0;
+
+
+EFI_STATUS
+CoreGetConfigTable (
+ IN EFI_GUID *Guid,
+ OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Find a config table by name in system table's ConfigurationTable.
+
+Arguments:
+
+ Guid - The table name to look for
+
+ Table - Pointer of the config table
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
+
+ EFI_SUCCESS - Table successfully found.
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (EfiCompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ *Table = gST->ConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreInstallConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+/*++
+
+Routine Description:
+
+ Boot Service called to add, modify, or remove a system configuration table from
+ the EFI System Table.
+
+Arguments:
+
+ Guid - Pointer to the GUID for the entry to add, update, or remove
+ Table - Pointer to the configuration table for the entry to add, update, or
+ remove, may be NULL.
+
+Returns:
+
+ EFI_SUCCESS Guid, Table pair added, updated, or removed.
+ EFI_INVALID_PARAMETER Input GUID not valid.
+ EFI_NOT_FOUND Attempted to delete non-existant entry
+ EFI_OUT_OF_RESOURCES Not enough memory available
+
+--*/
+{
+ UINTN Index;
+ EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
+
+ //
+ // If Guid is NULL, then this operation cannot be performed
+ //
+ if (Guid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EfiConfigurationTable = gST->ConfigurationTable;
+
+ //
+ // Search all the table for an entry that matches Guid
+ //
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (EfiCompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ break;
+ }
+ }
+
+ if (Index < gST->NumberOfTableEntries) {
+ //
+ // A match was found, so this is either a modify or a delete operation
+ //
+ if (Table != NULL) {
+ //
+ // If Table is not NULL, then this is a modify operation.
+ // Modify the table enty and return.
+ //
+ gST->ConfigurationTable[Index].VendorTable = Table;
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+#endif
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // A match was found and Table is NULL, so this is a delete operation.
+ //
+ gST->NumberOfTableEntries--;
+
+ //
+ // Copy over deleted entry
+ //
+ EfiCommonLibCopyMem (
+ &(EfiConfigurationTable[Index]),
+ &(gST->ConfigurationTable[Index + 1]),
+ (gST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+
+ } else {
+
+ //
+ // No matching GUIDs were found, so this is an add operation.
+ //
+
+ if (Table == NULL) {
+ //
+ // If Table is NULL on an add operation, then return an error.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Assume that Index == gST->NumberOfTableEntries
+ //
+ if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
+ //
+ // Allocate a table with one additional entry.
+ //
+ mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
+ EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize);
+ if (EfiConfigurationTable == NULL) {
+ //
+ // If a new table could not be allocated, then return an error.
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (gST->ConfigurationTable != NULL) {
+ //
+ // Copy the old table to the new table.
+ //
+ EfiCommonLibCopyMem (
+ EfiConfigurationTable,
+ gST->ConfigurationTable,
+ Index * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+
+ //
+ // Free Old Table
+ //
+ CoreFreePool (gST->ConfigurationTable);
+ }
+
+ //
+ // Update System Table
+ //
+ gST->ConfigurationTable = EfiConfigurationTable;
+ }
+
+ //
+ // Fill in the new entry
+ //
+ EfiConfigurationTable[Index].VendorGuid = *Guid;
+ EfiConfigurationTable[Index].VendorTable = Table;
+
+ //
+ // This is an add operation, so increment the number of table entries
+ //
+ gST->NumberOfTableEntries++;
+ }
+
+ //
+ // Fix up the CRC-32 in the EFI System Table
+ //
+ CalculateEfiHdrCrc (&gST->Hdr);
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+#endif
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/Library.c b/Core/CORE_DXE/Library.c
new file mode 100644
index 0000000..1f939ed
--- /dev/null
+++ b/Core/CORE_DXE/Library.c
@@ -0,0 +1,811 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Library.c
+
+Abstract:
+
+ DXE Core library services.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiCommonLib.h"
+
+DEBUG_CODE (
+ UINTN mErrorLevel = EFI_DBUG_MASK | EFI_D_LOAD;
+)
+
+EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = {
+ sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA),
+ EFI_STATUS_CODE_SPECIFIC_DATA_GUID,
+ NULL
+};
+
+VOID
+CoreReportProgressCodeSpecific (
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
+ with a handle as additional information.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+ Handle - Additional information.
+
+Returns:
+
+ None
+
+--*/
+{
+ mStatusCodeData.DataHeader.Size = sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA);
+ mStatusCodeData.Handle = Handle;
+
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ Value,
+ 0,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *) &mStatusCodeData
+ );
+ }
+}
+
+VOID
+CoreReportProgressCode (
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+Returns:
+
+ None
+
+--*/
+{
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ Value,
+ 0,
+ &gEfiDxeServicesTableGuid,
+ NULL
+ );
+ }
+}
+
+
+VOID *
+CoreAllocateBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory);
+ return Memory;
+}
+
+
+VOID *
+CoreAllocateZeroBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateBootServicesPool (AllocationSize);
+ EfiCommonLibSetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0);
+ return Memory;
+}
+
+
+VOID *
+CoreAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateBootServicesPool (AllocationSize);
+ EfiCommonLibCopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
+
+ return Memory;
+}
+
+
+
+VOID *
+CoreAllocateRuntimePool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+{
+ VOID *Memory;
+
+ CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory);
+ return Memory;
+}
+
+VOID *
+CoreAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+
+{
+ VOID *Memory;
+
+ Memory = CoreAllocateRuntimePool (AllocationSize);
+ EfiCommonLibCopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize);
+
+ return Memory;
+}
+
+
+
+//
+// Lock Stuff
+//
+
+
+
+EFI_STATUS
+CoreAcquireLockOrFail (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Initialize a basic mutual exclusion lock. Each lock
+ provides mutual exclusion access at it's task priority
+ level. Since there is no-premption (at any TPL) or
+ multiprocessor support, acquiring the lock only consists
+ of raising to the locks TPL.
+
+Arguments:
+
+ Lock - The EFI_LOCK structure to initialize
+
+Returns:
+
+ EFI_SUCCESS - Lock Owned.
+ EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
+
+--*/
+{
+ if (Lock->Lock != 0) {
+ //
+ // Lock is already owned, so bail out
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl);
+ Lock->Lock += 1;
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CoreAcquireLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Raising to the task priority level of the mutual exclusion
+ lock, and then acquires ownership of the lock.
+
+Arguments:
+
+ Lock - The lock to acquire
+
+Returns:
+
+ Lock owned
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreAcquireLockOrFail (Lock);
+
+ //
+ // Lock was already locked.
+ //
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+VOID
+CoreReleaseLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Releases ownership of the mutual exclusion lock, and
+ restores the previous task priority level.
+
+Arguments:
+
+ Lock - The lock to release
+
+Returns:
+
+ Lock unowned
+
+--*/
+{
+ EFI_TPL Tpl;
+
+ Tpl = Lock->OwnerTpl;
+
+ ASSERT (Lock->Lock == 1);
+ Lock->Lock -= 1;
+
+ CoreRestoreTpl (Tpl);
+}
+
+
+UINTN
+CoreDevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+
+ Calculate the size of a whole device path.
+
+Arguments:
+
+ DevicePath - The pointer to the device path data.
+
+Returns:
+
+ Size of device path data structure..
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Start;
+
+ if (DevicePath == NULL) {
+ return 0;
+ }
+
+ //
+ // Search for the end of the device path structure
+ //
+ Start = DevicePath;
+ while (!EfiIsDevicePathEnd (DevicePath)) {
+ DevicePath = EfiNextDevicePathNode (DevicePath);
+ }
+
+ //
+ // Compute the size and add back in the size of the end device path structure
+ //
+ return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL);
+}
+
+
+BOOLEAN
+CoreIsDevicePathMultiInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Return TRUE is this is a multi instance device path.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+
+Returns:
+ TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
+ instance.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+
+ if (DevicePath == NULL) {
+ return FALSE;
+ }
+
+ Node = DevicePath;
+ while (!EfiIsDevicePathEnd (Node)) {
+ if (EfiIsDevicePathEndInstance (Node)) {
+ return TRUE;
+ }
+ Node = EfiNextDevicePathNode (Node);
+ }
+ return FALSE;
+}
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreDuplicateDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Duplicate a new device path data structure from the old one.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+Returns:
+ A pointer to the new allocated device path data.
+ Caller must free the memory used by DevicePath if it is no longer needed.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ UINTN Size;
+
+ if (DevicePath == NULL) {
+ return NULL;
+ }
+
+ //
+ // Compute the size
+ //
+ Size = CoreDevicePathSize (DevicePath);
+
+ //
+ // Allocate space for duplicate device path
+ //
+ NewDevicePath = CoreAllocateCopyPool (Size, DevicePath);
+
+ return NewDevicePath;
+}
+
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreAppendDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *Src1,
+ IN EFI_DEVICE_PATH_PROTOCOL *Src2
+ )
+/*++
+
+Routine Description:
+ Function is used to append a Src1 and Src2 together.
+
+Arguments:
+ Src1 - A pointer to a device path data structure.
+
+ Src2 - A pointer to a device path data structure.
+
+Returns:
+
+ A pointer to the new device path is returned.
+ NULL is returned if space for the new device path could not be allocated from pool.
+ It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
+
+--*/
+{
+ UINTN Size;
+ UINTN Size1;
+ UINTN Size2;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath;
+
+ if (Src1 == NULL && Src2 == NULL) {
+ return NULL;
+ }
+
+ //
+ // Allocate space for the combined device path. It only has one end node of
+ // length EFI_DEVICE_PATH_PROTOCOL
+ //
+ Size1 = CoreDevicePathSize (Src1);
+ Size2 = CoreDevicePathSize (Src2);
+ Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+ NewDevicePath = CoreAllocateCopyPool (Size, Src1);
+ if (NewDevicePath != NULL) {
+
+ //
+ // Over write Src1 EndNode and do the copy
+ //
+ SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL)));
+ EfiCommonLibCopyMem (SecondDevicePath, Src2, Size2);
+ }
+
+ return NewDevicePath;
+}
+
+
+
+EFI_EVENT
+CoreCreateProtocolNotifyEvent (
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT VOID **Registration,
+ IN BOOLEAN SignalFlag
+ )
+/*++
+
+Routine Description:
+
+ Create a protocol notification event and return it.
+
+Arguments:
+
+ ProtocolGuid - Protocol to register notification event on.
+
+ NotifyTpl - Maximum TPL to signal the NotifyFunction.
+
+ NotifyFuncition - EFI notification routine.
+
+ NotifyContext - Context passed into Event when it is created.
+
+ Registration - Registration key returned from RegisterProtocolNotify().
+
+ SignalFlag - Boolean value to decide whether kick the event after register or not.
+
+Returns:
+
+ The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
+ is added to the system.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ //
+ // Create the event
+ //
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ NotifyTpl,
+ NotifyFunction,
+ NotifyContext,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+
+ Status = CoreRegisterProtocolNotify (
+ ProtocolGuid,
+ Event,
+ Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (SignalFlag) {
+ //
+ // Kick the event so we will perform an initial pass of
+ // current installed drivers
+ //
+ CoreSignalEvent (Event);
+ }
+
+ return Event;
+}
+
+VOID
+EFIAPI
+CoreInitializeFwVolDevicepathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+ IN EFI_GUID *NameGuid
+ )
+/*++
+Routine Description:
+
+ Initialize a Firmware Volume (FV) Media Device Path node.
+
+Arguments:
+
+ FvDevicePathNode - Pointer to a FV device path node to initialize
+ NameGuid - FV file name to use in FvDevicePathNode
+
+--*/
+{
+ FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH;
+ FvDevicePathNode->Header.SubType = MEDIA_FV_FILEPATH_DP;
+ SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH));
+
+ EfiCommonLibCopyMem (&FvDevicePathNode->NameGuid, NameGuid, sizeof(EFI_GUID));
+}
+
+EFI_GUID *
+EFIAPI
+CoreGetNameGuidFromFwVolDevicePathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode
+ )
+/*++
+
+Routine Description:
+
+ Check to see if the Firmware Volume (FV) Media Device Path is valid.
+
+Arguments:
+
+ FvDevicePathNode - Pointer to FV device path to check
+
+Returns:
+
+ NULL - FvDevicePathNode is not valid.
+ Other - FvDevicePathNode is valid and pointer to NameGuid was returned.
+
+--*/
+{
+ if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) {
+ return &FvDevicePathNode->NameGuid;
+ }
+
+ return NULL;
+}
+
+DEBUG_CODE (
+//*** AMI PORTING BEGIN ***//
+/* Defined in AmiDxeInit.c
+VOID
+EfiDebugAssert (
+ IN CHAR8 *FileName,
+ IN INTN LineNumber,
+ IN CHAR8 *Description
+ )
+*/
+/*++
+
+Routine Description:
+
+ Worker function for ASSERT(). If Error Logging hub is loaded, log DEBUG
+ information; If not, do BREAKPOINT().
+
+ We use UINT64 buffers due to IPF alignment concerns.
+
+Arguments:
+
+ FileName - File name of failing routine.
+
+ LineNumber - Line number of failing ASSERT().
+
+ Description - Descritption, usally the assertion string.
+
+Returns:
+
+ None
+
+--*/
+/*{
+ UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+
+ EfiDebugAssertWorker (FileName, LineNumber,Description, sizeof (Buffer), Buffer);
+
+ //
+ // Check if our pointers are valid. Can't assert because that would recurse.
+ //
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ (EFI_SOFTWARE_DXE_CORE | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE),
+ 0,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *)Buffer
+ );
+ }
+
+ //
+ // Put break point in module that contained the error.
+ //
+ EFI_BREAKPOINT ();
+}*/
+
+/* Defined in AmiDxeInit.c
+VOID
+EfiDebugVPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ IN VA_LIST Marker
+ )*/
+/*++
+
+Routine Description:
+
+ Worker function for DEBUG(). If Error Logging hub is loaded, DEBUG
+ information will be logged. If Error Logging hub is not loaded, do nothing.
+
+ We use UINT64 buffers due to IPF alignment concerns.
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ Marker - VarArgs
+
+Returns:
+
+ None
+
+--*/
+/*{
+ UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
+
+ if (!(mErrorLevel & ErrorLevel)) {
+ return;
+ }
+
+ EfiDebugVPrintWorker (ErrorLevel, Format, Marker, sizeof (Buffer), Buffer);
+
+ //
+ // Check if our pointers are valid. Can't assert because that would recurse.
+ //
+ if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) {
+ gStatusCode->ReportStatusCode (
+ EFI_DEBUG_CODE,
+ (EFI_SOFTWARE_DXE_CORE | EFI_DC_UNSPECIFIED),
+ (UINT32) ErrorLevel,
+ &gEfiDxeServicesTableGuid,
+ (EFI_STATUS_CODE_DATA *)Buffer
+ );
+ }
+}*/
+//*** AMI PORTING END *****//
+
+
+VOID
+EfiDebugPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Wrapper for EfiDebugVPrint ()
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ ... - Print arguments.
+
+Returns:
+
+ None
+
+--*/
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, Format);
+ EfiDebugVPrint (ErrorLevel, Format, Marker);
+ VA_END (Marker);
+}
+)
diff --git a/Core/CORE_DXE/Library.h b/Core/CORE_DXE/Library.h
new file mode 100644
index 0000000..8bac924
--- /dev/null
+++ b/Core/CORE_DXE/Library.h
@@ -0,0 +1,531 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Library.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _DXE_LIBRARY_H_
+#define _DXE_LIBRARY_H_
+
+typedef struct {
+ EFI_TPL Tpl;
+ EFI_TPL OwnerTpl;
+ UINTN Lock;
+} EFI_LOCK;
+
+
+//
+// Macro to initialize the state of a lock when a lock variable is declared
+//
+#define EFI_INITIALIZE_LOCK_VARIABLE(Tpl) {Tpl,0,0}
+
+VOID
+CoreReportProgressCode (
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReportProgressCodeSpecific (
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid,
+ with a handle as additional information.
+
+Arguments:
+
+ Value - Describes the class/subclass/operation of the hardware or software entity
+ that the Status Code relates to.
+
+ Handle - Additional information.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreAcquireLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Raising to the task priority level of the mutual exclusion
+ lock, and then acquires ownership of the lock.
+
+Arguments:
+
+ Lock - The lock to acquire
+
+Returns:
+
+ Lock owned
+
+--*/
+;
+
+EFI_STATUS
+CoreAcquireLockOrFail (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Initialize a basic mutual exclusion lock. Each lock
+ provides mutual exclusion access at it's task priority
+ level. Since there is no-premption (at any TPL) or
+ multiprocessor support, acquiring the lock only consists
+ of raising to the locks TPL.
+
+Arguments:
+
+ Lock - The EFI_LOCK structure to initialize
+
+Returns:
+
+ EFI_SUCCESS - Lock Owned.
+ EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned.
+
+--*/
+;
+
+VOID
+CoreReleaseLock (
+ IN EFI_LOCK *Lock
+ )
+/*++
+
+Routine Description:
+
+ Releases ownership of the mutual exclusion lock, and
+ restores the previous task priority level.
+
+Arguments:
+
+ Lock - The lock to release
+
+Returns:
+
+ Lock unowned
+
+--*/
+;
+
+//
+// Device Path functions
+//
+
+UINTN
+CoreDevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+
+ Calculate the size of a whole device path.
+
+Arguments:
+
+ DevicePath - The pointer to the device path data.
+
+Returns:
+
+ Size of device path data structure..
+
+--*/
+;
+
+BOOLEAN
+CoreIsDevicePathMultiInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Return TRUE is this is a multi instance device path.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+
+Returns:
+ TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi
+ instance.
+
+--*/
+;
+
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreDuplicateDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Duplicate a new device path data structure from the old one.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+Returns:
+ A pointer to the new allocated device path data.
+ Caller must free the memory used by DevicePath if it is no longer needed.
+
+--*/
+;
+
+EFI_DEVICE_PATH_PROTOCOL *
+CoreAppendDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *Src1,
+ IN EFI_DEVICE_PATH_PROTOCOL *Node
+ )
+/*++
+
+Routine Description:
+ Function is used to append a Src1 and Src2 together.
+
+Arguments:
+ Src1 - A pointer to a device path data structure.
+
+ Node - A pointer to a device path data structure.
+
+Returns:
+
+ A pointer to the new device path is returned.
+ NULL is returned if space for the new device path could not be allocated from pool.
+ It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed.
+
+--*/
+;
+
+VOID *
+CoreAllocateBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateZeroBootServicesPool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+EFI_STATUS
+CoreGetConfigTable (
+ IN EFI_GUID *Guid,
+ IN OUT VOID **Table
+ )
+/*++
+
+Routine Description:
+
+ Find a config table by name in system table's ConfigurationTable.
+
+Arguments:
+
+ Guid - The table name to look for
+
+ Table - Pointer of the config table
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable.
+
+ EFI_SUCCESS - Table successfully found.
+
+--*/
+;
+
+VOID *
+CoreAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateRuntimePool (
+ IN UINTN AllocationSize
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID *
+CoreAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool.
+
+Arguments:
+
+ AllocationSize - Size to allocate.
+
+ Buffer - Specified buffer that will be copy to the allocated pool
+
+Returns:
+
+ Pointer of the allocated pool.
+
+--*/
+;
+
+VOID
+EfiDebugAssert (
+ IN CHAR8 *FileName,
+ IN INTN LineNumber,
+ IN CHAR8 *Description
+ )
+/*++
+
+Routine Description:
+
+ Worker function for ASSERT(). If Error Logging hub is loaded, log DEBUG
+ information; If not, do BREAKPOINT().
+
+Arguments:
+
+ FileName - File name of failing routine.
+
+ LineNumber - Line number of failing ASSERT().
+
+ Description - Descritption, usally the assertion string.
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+EfiDebugPrint (
+ IN UINTN ErrorLevel,
+ IN CHAR8 *Format,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Wrapper for EfiDebugVPrint ()
+
+Arguments:
+
+ ErrorLevel - If error level is set do the debug print.
+
+ Format - String to use for the print, followed by Print arguments.
+
+ ... - Print arguments.
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_EVENT
+CoreCreateProtocolNotifyEvent (
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT VOID **Registration,
+ IN BOOLEAN SignalFlag
+ )
+/*++
+
+Routine Description:
+
+ Create a protocol notification event and return it.
+
+Arguments:
+
+ ProtocolGuid - Protocol to register notification event on.
+
+ NotifyTpl - Maximum TPL to signal the NotifyFunction.
+
+ NotifyFuncition - EFI notification routine.
+
+ NotifyContext - Context passed into Event when it is created.
+
+ Registration - Registration key returned from RegisterProtocolNotify().
+
+ SignalFlag - Boolean value to decide whether kick the event after register or not.
+
+Returns:
+
+ The EFI_EVENT that has been registered to be signaled when a ProtocolGuid
+ is added to the system.
+
+--*/
+;
+
+VOID
+EFIAPI
+CoreInitializeFwVolDevicepathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode,
+ IN EFI_GUID *NameGuid
+ )
+/*++
+
+Routine Description:
+
+ Initialize a Firmware Volume (FV) Media Device Path node.
+
+Arguments:
+
+ FvDevicePathNode - Pointer to a FV device path node to initialize
+ NameGuid - FV file name to use in FvDevicePathNode
+
+--*/
+;
+
+EFI_GUID *
+EFIAPI
+CoreGetNameGuidFromFwVolDevicePathNode (
+ IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode
+ )
+/*++
+
+Routine Description:
+
+ Check to see if the Firmware Volume (FV) Media Device Path is valid.
+
+Arguments:
+
+ FvDevicePathNode Pointer to FV device path to check
+
+Returns:
+
+ NULL - FvDevicePathNode is not valid.
+ Other - FvDevicePathNode is valid and pointer to NameGuid was returned.
+
+--*/
+;
+
+//*** AMI PORTING BEGIN ***//
+//PI 1.1 ++
+#if PI_SPECIFICATION_VERSION >= 0x00010000
+EFI_STATUS
+GetNextFirmwareVolume2Hob (
+ IN OUT VOID **HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length,
+ OUT EFI_GUID *FileName
+ )
+;
+#endif
+//PI 1.1 --
+//*** AMI PORTING END *****//
+
+#endif
diff --git a/Core/CORE_DXE/LinkedList.h b/Core/CORE_DXE/LinkedList.h
new file mode 100644
index 0000000..b9611b9
--- /dev/null
+++ b/Core/CORE_DXE/LinkedList.h
@@ -0,0 +1 @@
+#include<AmiLib.h>
diff --git a/Core/CORE_DXE/Notify.c b/Core/CORE_DXE/Notify.c
new file mode 100644
index 0000000..ea8e0fd
--- /dev/null
+++ b/Core/CORE_DXE/Notify.c
@@ -0,0 +1,344 @@
+/*++
+
+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:
+
+ notify.c
+
+Abstract:
+
+ EFI notify infrastructure
+
+
+
+Revision History
+
+--*/
+
+#include "hand.h"
+
+
+
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ )
+/*++
+
+Routine Description:
+
+ Signal event for every protocol in protocol entry.
+
+Arguments:
+
+ ProtEntry - Protocol entry
+
+Returns:
+
+--*/
+{
+ PROTOCOL_NOTIFY *ProtNotify;
+ EFI_LIST_ENTRY *Link;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+//*** AMI PORTING BEGIN ***//
+//Bug fix:
+// CoreSignalEvent may lead to immediate call of the event notification function,
+// which may call CloseEvent, which invalidates current ProtNotify.
+// As a result, Link=Link->ForwardLink after the loop body ends up
+// with an invalid pointer (Link is part of the invalid ProtNotify).
+// The code is updated to get pointer to the next element before CoreSignalEvent.
+// for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify;) {
+ ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+ Link=Link->ForwardLink;
+//*** AMI PORTING END *****//
+ CoreSignalEvent (ProtNotify->Event);
+ }
+}
+
+
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Removes Protocol from the protocol list (but not the handle list).
+
+Arguments:
+
+ Handle - The handle to remove protocol on.
+
+ Protocol - GUID of the protocol to be moved
+
+ Interface - The interface of the protocol
+
+Returns:
+
+ Protocol Entry
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_NOTIFY *ProtNotify;
+ PROTOCOL_ENTRY *ProtEntry;
+ EFI_LIST_ENTRY *Link;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+
+ Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
+ if (Prot != NULL) {
+
+ ProtEntry = Prot->Protocol;
+
+ //
+ // If there's a protocol notify location pointing to this entry, back it up one
+ //
+
+ for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+ ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Position == &Prot->ByProtocol) {
+ ProtNotify->Position = Prot->ByProtocol.BackLink;
+ }
+ }
+
+ //
+ // Remove the protocol interface entry
+ //
+
+ RemoveEntryList (&Prot->ByProtocol);
+ }
+
+ return Prot;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreRegisterProtocolNotify (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ )
+/*++
+
+Routine Description:
+
+ Add a new protocol notification record for the request protocol.
+
+Arguments:
+
+ Protocol - The requested protocol to add the notify registration
+
+ Event - The event to signal
+
+ Registration - Returns the registration record
+
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully returned the registration record that has been added
+
+--*/
+{
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_NOTIFY *ProtNotify;
+ EFI_STATUS Status;
+
+ if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireProtocolLock ();
+
+ ProtNotify = NULL;
+
+ //
+ // Get the protocol entry to add the notification too
+ //
+
+ ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
+ if (ProtEntry != NULL) {
+
+ //
+ // Allocate a new notification record
+ //
+
+ ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));
+
+ if (ProtNotify != NULL) {
+
+ ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
+ ProtNotify->Protocol = ProtEntry;
+ ProtNotify->Event = Event;
+ //
+ // start at the begining
+ //
+ ProtNotify->Position = &ProtEntry->Protocols;
+
+ InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+
+ //
+ // Done. If we have a protocol notify entry, then return it.
+ // Otherwise, we must have run out of resources trying to add one
+ //
+
+ Status = EFI_OUT_OF_RESOURCES;
+ if (ProtNotify != NULL) {
+ *Registration = ProtNotify;
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreReinstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+/*++
+
+Routine Description:
+
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
+
+Arguments:
+
+ UserHandle - Handle on which the interface is to be reinstalled
+ Protocol - The numeric ID of the interface
+ OldInterface - A pointer to the old interface
+ NewInterface - A pointer to the new interface
+
+
+Returns:
+
+ Status code.
+
+ On EFI_SUCCESS The protocol interface was installed
+ On EFI_NOT_FOUND The OldInterface on the handle was not found
+ On EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Handle = (IHANDLE *) UserHandle;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
+ if (Prot == NULL) {
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
+ //
+ Status = CoreDisconnectControllersUsingProtocolInterface (
+ UserHandle,
+ Prot
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // One or more drivers refused to release, so return the error
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
+
+ if (Prot == NULL) {
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+ }
+
+ ProtEntry = Prot->Protocol;
+
+ //
+ // Update the interface on the protocol
+ //
+ Prot->Interface = NewInterface;
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Update the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Release the lock and connect all drivers to UserHandle
+ //
+ CoreReleaseProtocolLock ();
+ Status = CoreConnectController (
+ UserHandle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ CoreAcquireProtocolLock ();
+
+ //
+ // Notify the notification list for this protocol
+ //
+ CoreNotifyProtocolEntry (ProtEntry);
+
+ CoreReleaseProtocolLock ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/Page.c b/Core/CORE_DXE/Page.c
new file mode 100644
index 0000000..523bf02
--- /dev/null
+++ b/Core/CORE_DXE/Page.c
@@ -0,0 +1,1685 @@
+/*++
+
+Copyright (c) 2007 - 2009, 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:
+
+ page.c
+
+Abstract:
+
+ EFI Memory page management
+
+
+Revision History
+
+--*/
+
+#include "imem.h"
+
+#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE)
+
+//
+// Entry for tracking the memory regions for each memory type to help coalesce like memory types
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress; // Base address of the coalesce bin if NumberOfPages is not 0, or 0 otherwise
+ EFI_PHYSICAL_ADDRESS MaximumAddress; // Top address of the coalesce bin if NumberOfPages is not 0, or the top address below all bin ranges
+ UINT64 CurrentNumberOfPages; // CurrentNumberOfPages allocated for this memory type
+ UINT64 NumberOfPages; // Number of pages specified in gMemoryTypeInformation
+ UINTN InformationIndex; // Index into gMemoryTypeInformation
+ BOOLEAN Special; // If this type of coalesce bin needs to be filled in memory map
+ BOOLEAN Runtime; // If this type is runtime available
+} EFI_MEMORY_TYPE_STAISTICS;
+
+//
+// MemoryMap - The current memory map
+//
+UINTN mMemoryMapKey = 0;
+
+//
+// mMapStack - space to use as temp storage to build new map descriptors
+// mMapDepth - depth of new descriptor stack
+//
+
+#define MAX_MAP_DEPTH 6
+UINTN mMapDepth = 0;
+MEMORY_MAP mMapStack[MAX_MAP_DEPTH];
+UINTN mFreeMapStack = 0;
+//
+// This list maintain the free memory map list
+//
+EFI_LIST_ENTRY mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);
+BOOLEAN mMemoryTypeInformationInitialized = FALSE;
+
+EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesData
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiConventionalMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiUnusableMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIReclaimMemory
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIMemoryNVS
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType
+};
+
+EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = EFI_MAX_ADDRESS;
+
+EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
+ { EfiReservedMemoryType, 0 },
+ { EfiLoaderCode, 0 },
+ { EfiLoaderData, 0 },
+ { EfiBootServicesCode, 0 },
+ { EfiBootServicesData, 0 },
+ { EfiRuntimeServicesCode, 0 },
+ { EfiRuntimeServicesData, 0 },
+ { EfiConventionalMemory, 0 },
+ { EfiUnusableMemory, 0 },
+ { EfiACPIReclaimMemory, 0 },
+ { EfiACPIMemoryNVS, 0 },
+ { EfiMemoryMappedIO, 0 },
+ { EfiMemoryMappedIOPortSpace, 0 },
+ { EfiPalCode, 0 },
+ { EfiMaxMemoryType, 0 }
+};
+
+//
+// Internal prototypes
+//
+VOID
+PromoteMemoryResource (
+ VOID
+);
+
+STATIC
+VOID
+CoreAddRange (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End,
+ IN UINT64 Attribute
+ );
+
+STATIC
+VOID
+CoreFreeMemoryMapStack (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+CoreConvertPages (
+ IN UINT64 Start,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType
+ );
+
+STATIC
+VOID
+RemoveMemoryMapEntry (
+ MEMORY_MAP *Entry
+ );
+
+
+MEMORY_MAP *
+AllocateMemoryMapEntry (
+ );
+
+VOID
+CoreAcquireMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gMemoryLock);
+}
+
+
+VOID
+CoreReleaseMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gMemoryLock);
+}
+
+VOID
+PromoteMemoryResource (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "Promote the memory resource\n"));
+
+ CoreAcquireGcdMemoryLock ();
+
+ Link = mGcdMemorySpaceMap.ForwardLink;
+ while (Link != &mGcdMemorySpaceMap) {
+
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved &&
+ Entry->EndAddress < EFI_MAX_ADDRESS &&
+ (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
+ (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) {
+ //
+ // Update the GCD map
+ //
+ Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+ Entry->Capabilities |= EFI_MEMORY_TESTED;
+ Entry->ImageHandle = gDxeCoreImageHandle;
+ Entry->DeviceHandle = NULL;
+
+ //
+ // Add to allocable system memory resource
+ //
+
+ CoreAddRange (
+ EfiConventionalMemory,
+ Entry->BaseAddress,
+ Entry->EndAddress,
+ Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
+ );
+ mMemoryTypeStatistics[EfiConventionalMemory].CurrentNumberOfPages += RShiftU64 ((Entry->EndAddress - Entry->BaseAddress + 1), EFI_PAGE_SHIFT);
+ CoreFreeMemoryMapStack ();
+
+ }
+
+ Link = Link->ForwardLink;
+ }
+
+ CoreReleaseGcdMemoryLock ();
+
+ return;
+}
+
+VOID
+CoreAddMemoryDescriptor (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 NumberOfPages,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the memory map and add descriptors to
+ the current descriptor list.
+
+ N.B. The first descriptor that is added must be general usable
+ memory as the addition allocates heap.
+
+Arguments:
+
+ Type - The type of memory to add
+
+ Start - The starting address in the memory range
+ Must be page aligned
+
+ NumberOfPages - The number of pages in the range
+
+ Attribute - Attributes of the memory to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+{
+ EFI_PHYSICAL_ADDRESS End;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN FreeIndex;
+
+ if ((Start & EFI_PAGE_MASK) != 0) {
+ return;
+ }
+
+ if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {
+ return;
+ }
+
+ CoreAcquireMemoryLock ();
+ End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
+ CoreAddRange (Type, Start, End, Attribute);
+ mMemoryTypeStatistics[Type].CurrentNumberOfPages += NumberOfPages;
+ CoreFreeMemoryMapStack ();
+ CoreReleaseMemoryLock ();
+
+ //
+ // Check to see if the statistics for the different memory types have already been established
+ //
+ if (mMemoryTypeInformationInitialized) {
+ return;
+ }
+
+ //
+ // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
+ //
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[Index].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
+ //
+ // Allocate pages for the current memory type from the top of available memory
+ //
+ Status = CoreAllocatePages (
+ AllocateAnyPages,
+ Type,
+ gMemoryTypeInformation[Index].NumberOfPages,
+ &mMemoryTypeStatistics[Type].BaseAddress
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If an error occurs allocating the pages for the current memory type, then
+ // free all the pages allocates for the previous memory types and return. This
+ // operation with be retied when/if more memory is added to the system
+ //
+ for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[FreeIndex].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {
+ CoreFreePages (
+ mMemoryTypeStatistics[Type].BaseAddress,
+ gMemoryTypeInformation[FreeIndex].NumberOfPages
+ );
+ mMemoryTypeStatistics[Type].BaseAddress = 0;
+ mMemoryTypeStatistics[Type].MaximumAddress = EFI_MAX_ADDRESS;
+ }
+ }
+ return;
+ }
+
+ //
+ // Compute the address at the top of the current statistics
+ //
+ mMemoryTypeStatistics[Type].MaximumAddress =
+ mMemoryTypeStatistics[Type].BaseAddress +
+ LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1;
+
+ //
+ // If the current base address is the lowest address so far, then update the default
+ // maximum address
+ //
+ if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
+ mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
+ }
+ }
+ }
+
+ //
+ // There was enough system memory for all the the memory types were allocated. So,
+ // those memory areas can be freed for future allocations, and all future memory
+ // allocations can occur within their respective bins
+ //
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ //
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid
+ //
+ Type = gMemoryTypeInformation[Index].Type;
+ if (Type < 0 || Type > EfiMaxMemoryType) {
+ continue;
+ }
+
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
+ CoreFreePages (
+ mMemoryTypeStatistics[Type].BaseAddress,
+ gMemoryTypeInformation[Index].NumberOfPages
+ );
+ mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages;
+ gMemoryTypeInformation[Index].NumberOfPages = 0;
+ }
+ }
+
+ //
+ // If the number of pages reserved for a memory type is 0, then all allocations for that type
+ // should be in the default range.
+ //
+ for (Type = 0; Type < EfiMaxMemoryType; Type++) {
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+ if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
+ mMemoryTypeStatistics[Type].InformationIndex = Index;
+ }
+ }
+ if (mMemoryTypeStatistics[Type].MaximumAddress == EFI_MAX_ADDRESS) {
+ mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
+ }
+ }
+
+ mMemoryTypeInformationInitialized = TRUE;
+}
+
+
+STATIC
+VOID
+CoreAddRange (
+ IN EFI_MEMORY_TYPE Type,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End,
+ IN UINT64 Attribute
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Adds a ranges to the memory map.
+ The range must not already exist in the map.
+
+Arguments:
+
+ Type - The type of memory range to add
+
+ Start - The starting address in the memory range
+ Must be paged aligned
+
+ End - The last address in the range
+ Must be the last byte of a page
+
+ Attribute - The attributes of the memory range to add
+
+Returns:
+
+ None. The range is added to the memory map
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ ASSERT ((Start & EFI_PAGE_MASK) == 0);
+ ASSERT (End > Start) ;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ DEBUG ((EFI_D_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, (UINTN)Type));
+
+ //
+ // Memory map being altered
+ //
+
+ mMemoryMapKey += 1;
+
+ //
+ // Look for adjoining memory descriptor
+ //
+
+ // Two memory descriptors can only be merged if they have the same Type
+ // and the same Attribute
+ //
+
+ Link = gMemoryMap.ForwardLink;
+ while (Link != &gMemoryMap) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ Link = Link->ForwardLink;
+
+ if (Entry->Type != Type) {
+ continue;
+ }
+
+ if (Entry->Attribute != Attribute) {
+ continue;
+ }
+
+ if (Entry->End + 1 == Start) {
+
+ Start = Entry->Start;
+ RemoveMemoryMapEntry (Entry);
+
+ } else if (Entry->Start == End + 1) {
+
+ End = Entry->End;
+ RemoveMemoryMapEntry (Entry);
+ }
+ }
+
+ //
+ // Add descriptor
+ //
+
+ mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
+ mMapStack[mMapDepth].FromPages = FALSE;
+ mMapStack[mMapDepth].Type = Type;
+ mMapStack[mMapDepth].Start = Start;
+ mMapStack[mMapDepth].End = End;
+ mMapStack[mMapDepth].VirtualStart = 0;
+ mMapStack[mMapDepth].Attribute = Attribute;
+ InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link);
+
+ mMapDepth += 1;
+ ASSERT (mMapDepth < MAX_MAP_DEPTH);
+ return ;
+}
+
+STATIC
+VOID
+CoreFreeMemoryMapStack (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Moves any memory descriptors that are on the
+ temporary descriptor stack to heap.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ MEMORY_MAP *Entry;
+ MEMORY_MAP *Entry2;
+ EFI_LIST_ENTRY *Link2;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ //
+ // If already freeing the map stack, then return
+ //
+ if (mFreeMapStack) {
+ return ;
+ }
+
+ //
+ // Move the temporary memory descriptor stack into pool
+ //
+ mFreeMapStack += 1;
+
+ while (mMapDepth) {
+ //
+ // Deque an memory map entry from mFreeMemoryMapEntryList
+ //
+ Entry = AllocateMemoryMapEntry ();
+
+ ASSERT (Entry);
+
+ //
+ // Update to proper entry
+ //
+ mMapDepth -= 1;
+
+ if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
+
+ //
+ // Move this entry to general memory
+ //
+ RemoveEntryList (&mMapStack[mMapDepth].Link);
+ mMapStack[mMapDepth].Link.ForwardLink = NULL;
+
+ *Entry = mMapStack[mMapDepth];
+ Entry->FromPages = TRUE;
+
+ //
+ // Find insertion location
+ //
+ for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {
+ Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry2->FromPages && Entry2->Start > Entry->Start) {
+ break;
+ }
+ }
+
+ InsertTailList (Link2, &Entry->Link);
+
+ } else {
+ //
+ // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list,
+ // so here no need to move it to memory.
+ //
+ InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
+ }
+ }
+
+ mFreeMapStack -= 1;
+}
+
+STATIC
+VOID
+RemoveMemoryMapEntry (
+ MEMORY_MAP *Entry
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Removes a descriptor entry.
+
+Arguments:
+
+ Entry - The entry to remove
+
+Returns:
+
+ None
+
+--*/
+{
+ RemoveEntryList (&Entry->Link);
+ Entry->Link.ForwardLink = NULL;
+
+ if (Entry->FromPages) {
+ //
+ // Insert the free memory map descriptor to the end of mFreeMemoryMapEntryList
+ //
+ InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
+ }
+}
+
+MEMORY_MAP *
+AllocateMemoryMapEntry (
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
+ If the list is emtry, then allocate a new page to refuel the list.
+ Please Note this algorithm to allocate the memory map descriptor has a property
+ that the memory allocated for memory entries always grows, and will never really be freed
+ For example, if the current boot uses 2000 memory map entries at the maximum point, but
+ ends up with only 50 at the time the OS is booted, then the memory associated with the 1950
+ memory map entries is still allocated from EfiBootServicesMemory.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ The Memory map descriptor dequed from the mFreeMemoryMapEntryList
+
+--*/
+{
+ MEMORY_MAP* FreeDescriptorEntries;
+ MEMORY_MAP* Entry;
+ UINTN Index;
+
+ if (IsListEmpty (&mFreeMemoryMapEntryList)) {
+ //
+ // The list is empty, to allocate one page to refuel the list
+ //
+ FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
+ if(FreeDescriptorEntries != NULL) {
+ //
+ // Enque the free memmory map entries into the list
+ //
+ for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) {
+ FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;
+ InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);
+ }
+ } else {
+ return NULL;
+ }
+ }
+ //
+ // dequeue the first descriptor from the list
+ //
+ Entry = CR (mFreeMemoryMapEntryList.ForwardLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ RemoveEntryList (&Entry->Link);
+
+ return Entry;
+}
+
+STATIC
+EFI_STATUS
+CoreConvertPages (
+ IN UINT64 Start,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Converts a memory range to the specified type.
+ The range must exist in the memory map.
+
+Arguments:
+
+ Start - The first address of the range
+ Must be page aligned
+
+ NumberOfPages - The number of pages to convert
+
+ NewType - The new type for the memory range
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Could not find a descriptor cover the specified range
+ or convertion not allowed.
+
+ EFI_SUCCESS - Successfully converts the memory range to the specified type.
+
+--*/
+{
+
+ UINT64 NumberOfBytes;
+ UINT64 End;
+ UINT64 RangeEnd;
+ UINT64 Attribute;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ UINT64 NumberOfRangePages;
+
+ Entry = NULL;
+ NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
+ End = Start + NumberOfBytes - 1;
+
+ ASSERT (NumberOfPages);
+ ASSERT ((Start & EFI_PAGE_MASK) == 0);
+ ASSERT (End > Start) ;
+ ASSERT_LOCKED (&gMemoryLock);
+
+ if (NumberOfPages == 0 || (Start & EFI_PAGE_MASK ) || (Start > (Start + NumberOfBytes))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Convert the entire range
+ //
+
+ while (Start < End) {
+
+ //
+ // Find the entry that the covers the range
+ //
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+
+ if (Entry->Start <= Start && Entry->End > Start) {
+ break;
+ }
+ }
+
+ if (Link == &gMemoryMap) {
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Convert range to the end, or to the end of the descriptor
+ // if that's all we've got
+ //
+ RangeEnd = End;
+ if (Entry->End < End) {
+ RangeEnd = Entry->End;
+ }
+
+ DEBUG ((EFI_D_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, (UINTN)NewType));
+
+ //
+ // Debug code - verify conversion is allowed
+ //
+ if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {
+ DEBUG ((EFI_D_ERROR , "ConvertPages: Incompatible memory types\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Update counters for the number of pages allocated to each memory type
+ //
+ NumberOfRangePages = RShiftU64 (RangeEnd - Start + 1, EFI_PAGE_SHIFT);
+ if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {
+ ASSERT (NumberOfRangePages <= mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages);
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfRangePages;
+ gMemoryTypeInformation[mMemoryTypeStatistics[Entry->Type].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages;
+ }
+
+ if (NewType >= 0 && NewType < EfiMaxMemoryType) {
+ mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfRangePages;
+ gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
+ }
+
+ //
+ // Pull range out of descriptor
+ //
+ if (Entry->Start == Start) {
+
+ //
+ // Clip start
+ //
+ Entry->Start = RangeEnd + 1;
+
+ } else if (Entry->End == RangeEnd) {
+
+ //
+ // Clip end
+ //
+ Entry->End = Start - 1;
+
+ } else {
+
+ //
+ // Pull it out of the center, clip current
+ //
+
+ //
+ // Add a new one
+ //
+ mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
+ mMapStack[mMapDepth].FromPages = FALSE;
+ mMapStack[mMapDepth].Type = Entry->Type;
+ mMapStack[mMapDepth].Start = RangeEnd+1;
+ mMapStack[mMapDepth].End = Entry->End;
+
+ //
+ // Inherit Attribute from the Memory Descriptor that is being clipped
+ //
+ mMapStack[mMapDepth].Attribute = Entry->Attribute;
+
+ Entry->End = Start - 1;
+ ASSERT (Entry->Start < Entry->End);
+
+ Entry = &mMapStack[mMapDepth];
+ InsertTailList (&gMemoryMap, &Entry->Link);
+
+ mMapDepth += 1;
+ ASSERT (mMapDepth < MAX_MAP_DEPTH);
+ }
+
+ //
+ // The new range inherits the same Attribute as the Entry
+ //it is being cut out of
+ //
+ Attribute = Entry->Attribute;
+
+ //
+ // If the descriptor is empty, then remove it from the map
+ //
+ if (Entry->Start == Entry->End + 1) {
+ RemoveMemoryMapEntry (Entry);
+ Entry = NULL;
+ }
+
+ //
+ // Add our new range in
+ //
+ CoreAddRange (NewType, Start, RangeEnd, Attribute);
+
+ //
+ // Move any map descriptor stack to general pool
+ //
+ CoreFreeMemoryMapStack ();
+
+ //
+ // Bump the starting address, and convert the next range
+ //
+ Start = RangeEnd + 1;
+ }
+
+ //
+ // Converted the whole range, done
+ //
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+UINT64
+CoreFindFreePagesI (
+ IN UINT64 MaxAddress,
+ IN UINT64 NumberOfPages,
+ IN EFI_MEMORY_TYPE NewType,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Finds a consecutive free page range below
+ the requested address.
+
+Arguments:
+
+ MaxAddress - The address that the range must be below
+
+ NumberOfPages - Number of pages needed
+
+ NewType - The type of memory the range is going to be turned into
+
+ Alignment - Bits to align with
+
+Returns:
+
+ The base address of the range, or 0 if the range was not found
+
+--*/
+{
+ UINT64 NumberOfBytes;
+ UINT64 Target;
+ UINT64 DescStart;
+ UINT64 DescEnd;
+ UINT64 DescNumberOfBytes;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ if ((MaxAddress < EFI_PAGE_MASK) ||(NumberOfPages == 0)) {
+ return 0;
+ }
+
+ if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
+
+ //
+ // If MaxAddress is not aligned to the end of a page
+ //
+
+ //
+ // Change MaxAddress to be 1 page lower
+ //
+ MaxAddress -= (EFI_PAGE_MASK + 1);
+
+ //
+ // Set MaxAddress to a page boundary
+ //
+ MaxAddress &= ~EFI_PAGE_MASK;
+
+ //
+ // Set MaxAddress to end of the page
+ //
+ MaxAddress |= EFI_PAGE_MASK;
+ }
+
+ NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
+ Target = 0;
+
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+
+ //
+ // If it's not a free entry, don't bother with it
+ //
+ if (Entry->Type != EfiConventionalMemory) {
+ continue;
+ }
+
+ DescStart = Entry->Start;
+ DescEnd = Entry->End;
+
+ //
+ // If desc is past max allowed address, skip it
+ //
+ if (DescStart >= MaxAddress) {
+ continue;
+ }
+
+ //
+ // If desc ends past max allowed address, clip the end
+ //
+ if (DescEnd >= MaxAddress) {
+ DescEnd = MaxAddress;
+ }
+
+ DescEnd = ((DescEnd + 1) & (~(Alignment - 1))) - 1;
+
+ //
+ // Compute the number of bytes we can used from this
+ // descriptor, and see it's enough to satisfy the request
+ //
+ DescNumberOfBytes = DescEnd - DescStart + 1;
+
+ if (DescNumberOfBytes >= NumberOfBytes) {
+
+ //
+ // If this is the best match so far remember it
+ //
+ if (DescEnd > Target) {
+ Target = DescEnd;
+ }
+ }
+ }
+
+ //
+ // If this is a grow down, adjust target to be the allocation base
+ //
+ Target -= NumberOfBytes - 1;
+
+ //
+ // If we didn't find a match, return 0
+ //
+ if ((Target & EFI_PAGE_MASK) != 0) {
+ return 0;
+ }
+
+ return Target;
+}
+
+STATIC
+UINT64
+FindFreePages (
+ IN UINT64 MaxAddress,
+ IN UINT64 NoPages,
+ IN EFI_MEMORY_TYPE NewType,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Finds a consecutive free page range below
+ the requested address
+
+Arguments:
+
+ MaxAddress - The address that the range must be below
+
+ NoPages - Number of pages needed
+
+ NewType - The type of memory the range is going to be turned into
+
+ Alignment - Bits to align with
+
+Returns:
+
+ The base address of the range, or 0 if the range was not found.
+
+--*/
+{
+ UINT64 NewMaxAddress;
+ UINT64 Start;
+
+ NewMaxAddress = MaxAddress;
+
+ if (NewType >= 0 && NewType < EfiMaxMemoryType && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {
+ NewMaxAddress = mMemoryTypeStatistics[NewType].MaximumAddress;
+ } else {
+ if (NewMaxAddress > mDefaultMaximumAddress) {
+ NewMaxAddress = mDefaultMaximumAddress;
+ }
+ }
+
+ Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);
+ if (!Start) {
+ Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
+ if (!Start) {
+ //
+ // Here means there may be no enough memory to use, so try to go through
+ // all the memory descript to promote the untested memory directly
+ //
+ PromoteMemoryResource ();
+
+ //
+ // Allocate memory again after the memory resource re-arranged
+ //
+ Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
+ }
+ }
+
+ return Start;
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreAllocatePages (
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN NumberOfPages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Memory
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages from the memory map.
+
+Arguments:
+
+ Type - The type of allocation to perform
+
+ MemoryType - The type of memory to turn the allocated pages into
+
+ NumberOfPages - The number of pages to allocate
+
+ Memory - A pointer to receive the base allocated memory address
+
+Returns:
+
+ Status. On success, Memory is filled in with the base address allocated
+
+ EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec.
+
+ EFI_NOT_FOUND - Could not allocate pages match the requirement.
+
+ EFI_OUT_OF_RESOURCES - No enough pages to allocate.
+
+ EFI_SUCCESS - Pages successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Start;
+ UINT64 MaxAddress;
+ UINTN Alignment;
+
+ if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) ||
+ MemoryType == EfiConventionalMemory) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
+
+ if (MemoryType == EfiACPIReclaimMemory ||
+ MemoryType == EfiACPIMemoryNVS ||
+ MemoryType == EfiRuntimeServicesCode ||
+ MemoryType == EfiRuntimeServicesData) {
+
+ Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+ }
+
+//*** AMI PORTING BEGIN ***//
+//Bug fix(EIP 82751): original code was accessing *Memory without
+// checking for a NULL pointer.
+// This caused problems with the WHCK AllocatePages Compliance Test
+ if (Memory == NULL) return EFI_INVALID_PARAMETER;
+//*** AMI PORTING END *****//
+
+ if (Type == AllocateAddress) {
+ if ((*Memory & (Alignment - 1)) != 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
+ NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
+
+ //
+ // If this is for below a particular address, then
+ //
+ Start = *Memory;
+
+ //
+ // The max address is the max natively addressable address for the processor
+ //
+ MaxAddress = EFI_MAX_ADDRESS;
+
+ if (Type == AllocateMaxAddress) {
+ MaxAddress = Start;
+ }
+
+ CoreAcquireMemoryLock ();
+
+ //
+ // If not a specific address, then find an address to allocate
+ //
+ if (Type != AllocateAddress) {
+ Start = FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignment);
+ if (Start == 0) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+
+ //
+ // Convert pages from FreeMemory to the requested type
+ //
+ Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
+
+Done:
+ CoreReleaseMemoryLock ();
+
+ if (!EFI_ERROR (Status)) {
+ *Memory = Start;
+ }
+
+ return Status;
+}
+
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreFreePages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Frees previous allocated pages.
+
+Arguments:
+
+ Memory - Base address of memory being freed
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ EFI_NOT_FOUND - Could not find the entry that covers the range
+
+ EFI_INVALID_PARAMETER - Address not aligned
+
+ EFI_SUCCESS -Pages successfully freed.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ UINTN Alignment;
+
+ //
+ // Free the range
+ //
+ CoreAcquireMemoryLock ();
+
+ //
+ // Find the entry that the covers the range
+ //
+ Entry = NULL;
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry->Start <= Memory && Entry->End > Memory) {
+ break;
+ }
+ }
+ if (Link == &gMemoryMap) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
+
+ if (Entry->Type == EfiACPIReclaimMemory ||
+ Entry->Type == EfiACPIMemoryNVS ||
+ Entry->Type == EfiRuntimeServicesCode ||
+ Entry->Type == EfiRuntimeServicesData) {
+
+ Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+
+ }
+
+ if ((Memory & (Alignment - 1)) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
+ NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
+
+ Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Destroy the contents
+ //
+ if (Memory < EFI_MAX_ADDRESS) {
+ DEBUG_SET_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT);
+ }
+
+ Done:
+ CoreReleaseMemoryLock ();
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMap (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ )
+/*++
+
+Routine Description:
+
+ This function returns a copy of the current memory map. The map is an array of
+ memory descriptors, each of which describes a contiguous block of memory.
+
+Arguments:
+
+ MemoryMapSize - A pointer to the size, in bytes, of the MemoryMap buffer. On
+ input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware
+ if the buffer was large enough, or the size of the buffer needed
+ to contain the map if the buffer was too small.
+ MemoryMap - A pointer to the buffer in which firmware places the current memory map.
+ MapKey - A pointer to the location in which firmware returns the key for the
+ current memory map.
+ DescriptorSize - A pointer to the location in which firmware returns the size, in
+ bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+ DescriptorVersion - A pointer to the location in which firmware returns the version
+ number associated with the EFI_MEMORY_DESCRIPTOR.
+
+Returns:
+
+ EFI_SUCCESS - The memory map was returned in the MemoryMap buffer.
+ EFI_BUFFER_TOO_SMALL - The MemoryMap buffer was too small. The current buffer size
+ needed to hold the memory map is returned in MemoryMapSize.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN BufferSize;
+ UINTN NumberOfRuntimeEntries;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+ EFI_GCD_MAP_ENTRY *GcdMapEntry;
+ EFI_MEMORY_TYPE Type;
+
+ //
+ // Make sure the parameters are valid
+ //
+ if (MemoryMapSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Count the number of Reserved and MMIO entries that are marked for runtime use
+ //
+ NumberOfRuntimeEntries = 0;
+ for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
+ GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
+ (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
+ NumberOfRuntimeEntries++;
+ }
+ }
+ }
+
+ Size = sizeof (EFI_MEMORY_DESCRIPTOR);
+
+ //
+ // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
+ // prevent people from having pointer math bugs in their code.
+ // now you have to use *DescriptorSize to make things work.
+ //
+ Size += sizeof(UINT64) - (Size % sizeof (UINT64));
+
+ if (DescriptorSize != NULL) {
+ *DescriptorSize = Size;
+ }
+
+ if (DescriptorVersion != NULL) {
+ *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
+ }
+
+ CoreAcquireMemoryLock ();
+
+ //
+ // Compute the buffer size needed to fit the entire map
+ //
+ BufferSize = Size * NumberOfRuntimeEntries;
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ BufferSize += Size;
+ }
+
+ if (*MemoryMapSize < BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Done;
+ }
+
+ if (MemoryMap == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Build the map
+ //
+ EfiCommonLibZeroMem (MemoryMap, BufferSize);
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ ASSERT (Entry->VirtualStart == 0);
+
+ //
+ // Convert internal map into an EFI_MEMORY_DESCRIPTOR
+ //
+ MemoryMap->Type = Entry->Type;
+ MemoryMap->PhysicalStart = Entry->Start;
+ MemoryMap->VirtualStart = Entry->VirtualStart;
+ MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
+ //
+ // If the memory type is EfiConventionalMemory, then determine if the range is part of a
+ // memory type bin and needs to be converted to the same memory type as the rest of the
+ // memory type bin in order to minimize EFI Memory Map changes across reboots. This
+ // improves the chances for a successful S4 resume in the presence of minor page allocation
+ // differences across reboots.
+ //
+ if (MemoryMap->Type == EfiConventionalMemory) {
+ for (Type = (EFI_MEMORY_TYPE) 0; Type < EfiMaxMemoryType; Type++) {
+ if (mMemoryTypeStatistics[Type].Special &&
+ mMemoryTypeStatistics[Type].NumberOfPages > 0 &&
+ Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress &&
+ Entry->End <= mMemoryTypeStatistics[Type].MaximumAddress ) {
+ MemoryMap->Type = Type;
+ }
+ }
+ }
+ MemoryMap->Attribute = Entry->Attribute;
+ if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {
+ MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
+ }
+
+ MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
+ }
+
+ for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
+ GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
+ (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
+
+ MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
+ MemoryMap->VirtualStart = 0;
+ MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
+ MemoryMap->Attribute = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO;
+
+ if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {
+ MemoryMap->Type = EfiReservedMemoryType;
+//*** AMI PORTING BEGIN ***//
+/*
+Enhancement (EIP 83128): Windows 8 compatibility test suite reports an error
+on memory map entries of type EfiReserverdMemoryType with the EFI_MEMORY_RUNTIME attribute set.
+This is a workaround.
+
+In a pure UEFI world there should be no such entries:
+If the region requires virtual address mapping (this is implied by the EFI_MEMORY_RUNTIME attribute),
+it should be of EfiRuntimeServicesData or EfiRuntimeServicesCode type.
+If no virtual address mapping is required, there should be no EFI_MEMORY_RUNTIME attribute.
+
+Our reality is more complicated than a pure UEFI world.
+Most of the EfiReserverdMemoryType entries are imported from the GCD memory map.
+The PI specification does not define how to reflect GCD memory maps entries
+in the UEFI memory map, which makes it up to implementation.
+The EDK implementation ignores all non-runtime GCD entries.
+So, the only way to report GCD entry to OS (which only deals with UEFI memory map),
+is to set a runtime attribute.
+
+Our workaround is to reset EFI_MEMORY_RUNTIME attribute during import of the memory map entry from GCD to UEFI.
+
+A real solution is update the PI specification to define clear rules on how to
+reflect GCD memory maps entries in the UEFI memory map.
+AMI initiated the process with the PI working group, but it may take a while.
+*/
+ MemoryMap->Attribute &= ~EFI_MEMORY_RUNTIME;
+//*** AMI PORTING END *****//
+ } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
+ MemoryMap->Type = EfiMemoryMappedIOPortSpace;
+ } else {
+ MemoryMap->Type = EfiMemoryMappedIO;
+ }
+ }
+
+ MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
+ }
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+
+ CoreReleaseMemoryLock ();
+
+ CoreReleaseGcdMemoryLock ();
+
+ //
+ // Update the map key finally
+ //
+ if (MapKey != NULL) {
+ *MapKey = mMemoryMapKey;
+ }
+
+ *MemoryMapSize = BufferSize;
+
+ return Status;
+}
+
+VOID *
+CoreAllocatePoolPages (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NumberOfPages,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Used by the pool functions to allocate pages
+ to back pool allocation requests.
+
+Arguments:
+
+ PoolType - The type of memory for the new pool pages
+
+ NumberOfPages - No of pages to allocate
+
+ Alignment - Bits to align.
+
+Returns:
+
+ The allocated memory, or NULL
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Start;
+
+ //
+ // Find the pages to convert
+ //
+ Start = FindFreePages (EFI_MAX_ADDRESS, NumberOfPages, PoolType, Alignment);
+
+ //
+ // Convert it to boot services data
+ //
+ if (Start == 0) {
+ DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", NumberOfPages));
+ } else {
+ Status = CoreConvertPages (Start, NumberOfPages, PoolType);
+ }
+
+ return (VOID *)(UINTN)Start;
+}
+
+VOID
+CoreFreePoolPages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Frees pool pages allocated via AllocatePoolPages ()
+
+Arguments:
+
+ Memory - The base address to free
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
+}
+
+
+EFI_STATUS
+CoreTerminateMemoryMap (
+ IN UINTN MapKey
+ )
+/*++
+
+Routine Description:
+
+ Make sure the memory map is following all the construction rules,
+ it is the last time to check memory map error before exit boot services.
+
+Arguments:
+
+ MapKey - Memory map key
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Memory map not consistent with construction rules.
+
+ EFI_SUCCESS - Valid memory map.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *Link;
+ MEMORY_MAP *Entry;
+
+ Status = EFI_SUCCESS;
+
+ CoreAcquireMemoryLock ();
+
+ if (MapKey == mMemoryMapKey) {
+
+ //
+ // Make sure the memory map is following all the construction rules
+ // This is the last chance we will be able to display any messages on
+ // the console devices.
+ //
+
+ for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
+ Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
+ if (Entry->Attribute & EFI_MEMORY_RUNTIME) {
+ if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
+ DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
+ CoreReleaseMemoryLock ();
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ //
+ // The map key they gave us matches what we expect. Fall through and
+ // return success. In an ideal world we would clear out all of
+ // EfiBootServicesCode and EfiBootServicesData. However this function
+ // is not the last one called by ExitBootServices(), so we have to
+ // preserve the memory contents.
+ //
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ CoreReleaseMemoryLock ();
+
+ return Status;
+}
+
+
+
+
+
+
+
+
diff --git a/Core/CORE_DXE/Partition/ElTorito.c b/Core/CORE_DXE/Partition/ElTorito.c
new file mode 100644
index 0000000..749ba74
--- /dev/null
+++ b/Core/CORE_DXE/Partition/ElTorito.c
@@ -0,0 +1,470 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.c 21 8/28/12 3:14p Pats $
+//
+// $Revision: 21 $
+//
+// $Date: 8/28/12 3:14p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.c $
+//
+// 21 8/28/12 3:14p Pats
+// [TAG] EIP99287
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Problem booting certain HDD emulation ElTorito CD/DVD's.
+// [RootCause] If the CD has ElTorito and ISO9660 partitions, the block
+// sizeread will be the ISO9660 block size, but the ElTorito partition
+// needs the HDD block size
+// [Solution] Set block size to HDD block size if HDD emulation detected.
+// [Files] Eltorito.c
+//
+// 20 5/10/12 5:54a Rameshr
+// [TAG] EIP88924
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] UEFI 2.3.1 SCT block io read test fail
+// [RootCause] If the CD has two Boot image , two blockio will be
+// installed by Partition driver. But the second blockIo , LastBlock value
+// is wrong
+// [Solution] 2nd logical blockIO LastBlock size calculation corrected.
+// [Files] Eltorito.c
+//
+// 19 9/27/11 7:43p Yul
+// [TAG] EIP69053
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System cannot boot to WINPE from CD/DVD.
+// [RootCause] Blocksize change
+// [Solution] Blocksize change
+// [Files] EIOorito.c
+//
+// 18 5/10/11 11:21a Pats
+// [TAG] - EIP 57859
+// [Category]- BUG FIX
+// [Severity]- Normal
+// [Symptom] - On EFI shell, though CD media is recognized as a Block
+// device, is not recognized as a File system.
+// [RootCause] - Blocksize change from EIP 30719.
+// [Solution] - Removed change from EIP 30719.
+// [Files] - ElTorito.c
+//
+// 17 4/16/10 4:24p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 16 10/20/09 5:02p Felixp
+// Check for a block I/O device errors is added in
+// ElToritoCreateChildHandle function.
+//
+// 14 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 13 4/23/09 11:54a Oleksiyy
+// Memory free error fix
+//
+// 12 2/19/09 1:02p Artems
+// EIP 19052 Minor improvement to support CD burned with Windows Explorer
+//
+// 11 1/16/09 3:02p Felixp
+// New Feature:
+// CD-ROM handling code is updated to create additional logical instance
+// of the Bock I/O protocol
+// based on primary volume descriptor of the CR-ROM.
+// The instance is used by the ISO 9660 file systems driver
+// (separate eModule. Not part of the Core) to implement file system
+// protocol.
+// The new parittion driver funcionality is only enabled when ISO 9660
+// file systems driver
+// ($/Source/Modules/FsIso9660) is included into the project.
+//
+// 10 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 9 4/24/07 5:31p Robert
+// Updated Headers to compile with CHM creation
+//
+// 8 3/22/07 5:39p Robert
+// Updated Files for coding standard
+//
+// 7 8/24/06 12:34p Felixp
+// x64 support (fixes for warnings/errors)
+//
+// 5 5/19/06 10:47p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 3 5/05/05 5:07p Robert
+// When reading the data for the Volume Descriptor. There was no check
+// for the Status of the Read Blocks call. If this returned an error then it
+// was continuing on. Now it exits when an error is found
+//
+// 2 2/11/05 6:13p Felixp
+// Code optimized by using DPAddNode instead of DPAdd
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 3 12/21/04 4:53p Markw
+// Modified device path defines for consistency.
+//
+// 2 12/02/04 5:54p Robert
+// Partition driver version works
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ElTorito.c
+//
+// Description: EFI El Torito Partition Support Functions
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//=============================================================================
+// Includes
+#include "Partition.h"
+#include "ElTorito.h"
+#include "mbr.h"
+
+extern BOOLEAN Iso9660FileSystemSupportEnabled;
+EFI_GUID VendorDpGuid = AMI_ISO9660_MEDIA_GUID;
+
+//=============================================================================
+// Local Variables
+
+//=============================================================================
+// Function Definitions
+
+
+
+//<AMI_PHDR_START>
+//=============================================================================
+// Procedure: ElToritoCreateChildHandle
+//
+// Description: Searches CDROM disk for El Torito bootable partitions
+// and creates a child handle for each one found
+//
+// Input:
+// *This - Pointer to the instance of this blockIo protocol
+// *BlockIo - Pointer to the parent blockIo Protocol
+// *DiskIo - Pointer to the parent DiskIo protocol
+// *DevicePath - Pointer to the Parent's device path
+// ControllerHandle - the parent's controller handle
+//
+// Output:
+//
+// Returns:
+// EFI_SUCCESS - Partition found
+// EFI_INVALID_MEDIA - a parameter passed in or in the data structure
+// is invalid
+// EFI_NO_MEDIA - No partitions found
+// EFI_OUT_OF RESOURCES - Not enough resources to allocate memory
+//
+// Referrals: ReadBlocks AllocatePool MemCmp FreePool Div64 SetMem
+// CreateChildHandle DPAddNode SET_NODE_LENGTH
+//
+//=============================================================================
+//<AMI_PHDR_END>
+EFI_STATUS ElToritoCreateChildHandle (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+)
+{
+ PARTITION_DATA PData, DData;
+ EFI_STATUS Status;
+ EFI_LBA Lba;
+ BOOT_RECORD_DESC *VolDesc = NULL;
+ EL_TORITO_ENTRIES *Entry = NULL, *StartEntry = NULL;
+ CDROM_DEVICE_PATH CdDp;
+ UINT32 BlockSize;
+ UINT16 Checksum;
+ UINT16 *Temp = NULL;
+ UINTN Idx;
+ UINT32 VolSize;
+ UINT32 Sectors;
+ UINTN BootEntry;
+ UINTN Dummy;
+
+ AMI_ISO9660_DEVICE_PATH VendorDp;
+ PRIMARY_VOLUME_DESC_HEADER *PrimVolDesc;
+
+
+// TODO: The El Torito spec says that the Boot Record Volume only exists on the last session
+// we need to find the last session on the CD
+
+ // Verify that the CDROM is using the correct block size
+ if (BlockIo->Media->BlockSize != CDROM_BLOCK_SIZE)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate memory for the Boot Record Volume
+ Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &VolDesc);
+
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ // CDROM Spec says sector 16 contains the Primary Volume descriptor
+ Lba = CDROM_BOOT_PRI_VOL_DESCRIPTOR_SECTOR;
+
+ Status = BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba,
+ BlockIo->Media->BlockSize, VolDesc );
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(VolDesc);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check for valid volume descriptor signature
+ if (MemCmp (VolDesc->IsoId, "CD001", 5))
+ {
+ gBS->FreePool(VolDesc);
+ return EFI_INVALID_PARAMETER;
+ }
+
+//***********************************************************************
+// Add Logical partition for ISO 9660 support
+//***********************************************************************
+ PrimVolDesc = (PRIMARY_VOLUME_DESC_HEADER *)VolDesc;
+ BlockSize = CDROM_BLOCK_SIZE;
+
+ //Set Vendor device path
+ VendorDp.Dp.Header.Type = MEDIA_DEVICE_PATH;
+ VendorDp.Dp.Header.SubType = MEDIA_VENDOR_DP;
+ VendorDp.Dp.Guid = VendorDpGuid;
+ VendorDp.VolumeSize = PrimVolDesc->VolSpaceSize;
+ VendorDp.Root = PrimVolDesc->Root;
+ MemCpy(VendorDp.VolumeLabel, PrimVolDesc->VolId, 32);
+ SET_NODE_LENGTH(&VendorDp.Dp.Header,sizeof(AMI_ISO9660_DEVICE_PATH));
+
+
+ // clear the data structure
+ gBS->SetMem(&DData, sizeof(PARTITION_DATA), 0);
+
+ // create new device path
+ DData.DevPath = DPAddNode(DevicePath, &(VendorDp.Dp.Header));
+
+ // save pertinent info
+ DData.Handle = NULL;
+ DData.ParentBlockIo = BlockIo;
+ DData.ParentDiskIo = DiskIo;
+ DData.StartingLba = 0;
+ DData.EndingLba = BlockIo->Media->LastBlock;
+
+ // Store Parent Handle
+ DData.ParentHandle = ControllerHandle;
+
+//***********************************************************************
+// End of ISO 9660 support
+//***********************************************************************
+
+ // Get the Volume Space Size from Primary Volume Descriptor,
+ // the 32-bit numerical value is stored in Both-Little and Big Endian
+ VolSize = VolDesc->VolSpaceSize[0];
+
+
+ // El Torito Spec says sector 17 contains the Boot Record
+ // Volume: Read and verify the data
+ Lba = CDROM_BOOT_REC_VOL_DESCRIPTOR_SECTOR;
+
+ Status = BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba,
+ BlockIo->Media->BlockSize, VolDesc );
+
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(VolDesc);
+ VolDesc = NULL;
+ goto EndOfEltorito;
+ }
+
+ // Validate the info in the Boot Record
+ if ((VolDesc->BootIndicator != 0) || ( MemCmp (VolDesc->IsoId, "CD001", 5)) ||
+ (VolDesc->Version != 1) || (MemCmp(VolDesc->Identifier, EL_TORITO_SPEC, 23) ) )
+ {
+ // not a valid boot Record
+ gBS->FreePool(VolDesc);
+ VolDesc = NULL;
+ goto EndOfEltorito;
+ }
+
+ // There is a valid boot record. move on to the Boot catalog
+ Lba = VolDesc->BootCatalog;
+
+ Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &StartEntry);
+
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(VolDesc);
+ VolDesc = NULL;
+ goto EndOfEltorito;
+ }
+
+ // Now load the Boot Catalog and find all the partitions
+ BlockIo->ReadBlocks( BlockIo, BlockIo->Media->MediaId, Lba,
+ BlockIo->Media->BlockSize, StartEntry );
+
+ // get pointer to the first entry in the Boot Record
+ Entry = (EL_TORITO_ENTRIES *)StartEntry;
+
+ if ((Entry->ValEntry.HeaderId != 1) || (Entry->ValEntry.Sig != 0xaa55))
+ {
+ gBS->FreePool(VolDesc);
+ VolDesc = NULL;
+ gBS->FreePool(StartEntry);
+ StartEntry = NULL;
+ goto EndOfEltorito;
+ }
+
+ // Now Calculate checksum
+ Checksum = 0;
+ Temp = (UINT16 *)Entry;
+
+ for (Idx = 0; Idx < 16; Idx++)
+ Checksum += Temp[Idx];
+
+ // if the checksum is not 0 then the Boot catalog is considered invalid
+ if (Checksum)
+ {
+ gBS->FreePool(VolDesc);
+ VolDesc = NULL;
+ gBS->FreePool(StartEntry);
+ StartEntry = NULL;
+ goto EndOfEltorito;
+ }
+
+ // The checksum is zero so here we go
+
+ // Find and install the Boot entries
+ // loop through the boot catalog looking for bootable entries
+ // start at the second entry in the boot catalog,
+ // the first is the validation entry
+ Entry++;
+
+ for ( Idx = 0, BootEntry = 0; Idx < ((CDROM_BLOCK_SIZE/ sizeof(EL_TORITO_ENTRIES)) - 1);
+ Idx++, Entry++)
+ {
+ // if it isn't bootable, get next entry
+ if (Entry->DefaultEntry.BootId != CDROM_BOOTABLE)
+ continue;
+
+
+ BlockSize = BlockIo->Media->BlockSize;
+ if( (BlockSize == 0) || (BlockSize == 0xFFFFFFFF) ) {
+ BlockSize = 512;
+ }
+ TRACE((TRACE_DXE_CORE, "BlockSize is %d, MediaID is %d\n", BlockSize, BlockIo->Media->MediaId));
+
+ Sectors = Entry->DefaultEntry.SectorCount;
+ TRACE((TRACE_DXE_CORE, "Sector count is %d\n", Sectors));
+ TRACE((TRACE_DXE_CORE, "Media Type is %d\n", Entry->DefaultEntry.MediaType));
+
+ // use this switch to set the Partition Size
+ switch (Entry->DefaultEntry.MediaType)
+ {
+ case FLOPPY_144:
+ Sectors = FLOPPY_144_SIZE_LBA;
+ break;
+ case FLOPPY_288:
+ Sectors = FLOPPY_288_SIZE_LBA;
+ break;
+ case FLOPPY_12:
+ Sectors = FLOPPY_12_SIZE_LBA;
+ break;
+
+ case NO_EMULATION:
+ BlockSize = CDROM_BLOCK_SIZE;
+ break;
+
+ case HARD_DRIVE:
+ BlockSize = 512;
+ break;
+ default:
+ continue;
+ }
+
+
+ if ((Idx != 0) && (BootEntry == 0))
+ BootEntry++;
+
+ CdDp.BootEntry = (UINT32) BootEntry++;
+
+ CdDp.PartitionStart = Entry->DefaultEntry.LoadLba;
+
+ if (Sectors < 2)
+ CdDp.PartitionSize = (VolSize > BlockIo->Media->LastBlock + 1) ?
+ (UINT32)(BlockIo->Media->LastBlock - CdDp.PartitionStart + 1) :
+ (UINT32)(VolSize - CdDp.PartitionStart);
+
+ else
+ CdDp.PartitionSize = Div64(Sectors* BlockSize + BlockIo->Media->BlockSize - 1,
+ BlockIo->Media->BlockSize, &Dummy );
+
+ // set up the device path for the partition
+ CdDp.Header.Type = MEDIA_DEVICE_PATH;
+ CdDp.Header.SubType = MEDIA_CDROM_DP;
+ SET_NODE_LENGTH(&CdDp.Header,sizeof(CDROM_DEVICE_PATH));
+
+ // clear the data structure
+ gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0);
+
+ // create new device path
+ PData.DevPath = DPAddNode(DevicePath, &CdDp.Header);
+
+ // save pertinent info
+ PData.Handle = NULL;
+ PData.ParentBlockIo = BlockIo;
+ PData.ParentDiskIo = DiskIo;
+ PData.StartingLba = CdDp.PartitionStart;
+ PData.EndingLba = CdDp.PartitionStart + CdDp.PartitionSize - 1;
+
+ // Store Parent Handle
+ PData.ParentHandle = ControllerHandle;
+
+ // This is a valid GPT partition: Add a child instance
+ Status = CreateChildHandle(This, &PData, BlockSize);
+ }
+
+EndOfEltorito:
+
+ if (VolDesc != NULL) gBS->FreePool(VolDesc);
+
+ if (StartEntry != NULL) gBS->FreePool(StartEntry);
+
+ if (Iso9660FileSystemSupportEnabled)
+ {
+ Status = CreateChildHandle(This, &DData, CDROM_BLOCK_SIZE);
+ }
+
+ return Status;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/ElTorito.h b/Core/CORE_DXE/Partition/ElTorito.h
new file mode 100644
index 0000000..ebbd7ba
--- /dev/null
+++ b/Core/CORE_DXE/Partition/ElTorito.h
@@ -0,0 +1,264 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.h 5 7/09/09 5:01p Oleksiyy $
+//
+// $Revision: 5 $
+//
+// $Date: 7/09/09 5:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/ElTorito.h $
+//
+// 5 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 4 1/16/09 3:02p Felixp
+// New Feature:
+// CD-ROM handling code is updated to create additional logical instance
+// of the Bock I/O protocol
+// based on primary volume descriptor of the CR-ROM.
+// The instance is used by the ISO 9660 file systems driver
+// (separate eModule. Not part of the Core) to implement file system
+// protocol.
+// The new parittion driver funcionality is only enabled when ISO 9660
+// file systems driver
+// ($/Source/Modules/FsIso9660) is included into the project.
+//
+// 2 12/02/04 5:54p Robert
+// Partition driver version works
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <ElTorito.h>
+//
+// Description: EFI El Torito Partition Generic Driver Header.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __EL_TORITO_H__
+#define __EL_TORITO_H__
+
+#define CDROM_BOOT_PRI_VOL_DESCRIPTOR_SECTOR 16
+#define CDROM_BOOT_REC_VOL_DESCRIPTOR_SECTOR 17
+
+#define CDROM_BLOCK_SIZE 2048
+
+#define CDROM_BOOTABLE 0x88
+
+
+#define NO_EMULATION 0x00
+#define FLOPPY_12 0x01
+#define FLOPPY_144 0x02
+#define FLOPPY_288 0x03
+#define HARD_DRIVE 0x04
+
+
+#define HD_BLOCK_SIZE 512
+#define FLOPPY_144_SIZE_LBA 720
+#define FLOPPY_288_SIZE_LBA 1440
+#define FLOPPY_12_SIZE_LBA 615
+
+#define EL_TORITO_SPEC "EL TORITO SPECIFICATION"
+
+// {BA7C46D1-9C5E-4fc8-943D-1A491F23FE01}
+#define AMI_ISO9660_MEDIA_GUID \
+ { 0xba7c46d1, 0x9c5e, 0x4fc8, 0x94, 0x3d, 0x1a, 0x49, 0x1f, 0x23, 0xfe, 0x1 }
+
+
+//<AMI_GHDR_START>
+//------------------------------------------------------------------
+// Name: Data_Structures
+//
+// Description:
+// Data Structures needed for El Torito
+//
+// BOOT_RECORD - Data Structure definition of a boot record
+// that is contained within an El Torito Disk
+//
+// EL_TORITO_ENTRIES - A union of possible structs that could be
+// contained within an entry on the disk
+//
+//------------------------------------------------------------------
+//<AMI_GHDR_END>
+#pragma pack(1)
+
+typedef struct _BOOT_RECORD
+{
+ UINT8 BootIndicator;
+ CHAR8 IsoId[5];
+ UINT8 Version;
+ CHAR8 Identifier[32];
+ UINT8 Unused[32];
+ UINT32 BootCatalog;
+ UINT8 Unused2[5];
+ UINT32 VolSpaceSize[2];
+} BOOT_RECORD_DESC;
+
+
+
+typedef union
+{
+ struct
+ {
+ UINT8 HeaderId;
+ UINT8 PlatformId;
+ UINT16 Res0;
+ CHAR8 Id[24];
+ UINT16 Checksum;
+ UINT16 Sig;
+ } ValEntry;
+
+
+ struct
+ {
+ UINT8 BootId;
+ UINT8 MediaType;
+ UINT16 LoadSegment;
+ UINT8 SystemType;
+ UINT8 Unused;
+ UINT16 SectorCount;
+ UINT32 LoadLba;
+ } DefaultEntry;
+
+
+ struct
+ {
+ UINT8 HeaderId;
+ UINT8 PlatformId;
+ UINT16 NumSectionEntries;
+ CHAR8 IdString[28];
+ } SecHeader;
+
+
+ struct
+ {
+ UINT8 BootId;
+ UINT8 MediaType;
+ UINT16 LoadSegment;
+ UINT8 SystemType;
+ UINT8 Unused;
+ UINT16 SectorCount;
+ UINT32 LoadLba;
+ UINT8 SelectionType;
+ UINT8 Criteria[19];
+ } SecEntry;
+
+} EL_TORITO_ENTRIES;
+
+typedef struct
+{
+ UINT8 VolDescType;
+ CHAR8 StdId[5];
+ UINT8 VolDescVer;
+} VOLUME_DESCRIPTOR_HEADER;
+
+typedef struct
+{
+ UINT32 Year;
+ UINT16 Month;
+ UINT16 Day;
+ UINT16 Hour;
+ UINT16 Minute;
+ UINT16 Second;
+ UINT16 HSecond;
+ INT8 Offset;
+} CD_DATE_TIME;
+
+typedef struct
+{
+ UINT8 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ INT8 Offset;
+} FILE_DATE_TIME;
+
+typedef struct
+{
+ UINT8 RecordLength;
+ UINT8 ExtAttrRecLength;
+ UINT64 StartLba;
+ UINT64 DataLength;
+ FILE_DATE_TIME RecTime;
+ UINT8 Flags;
+ UINT8 FileUnitSize;
+ UINT8 InterleaveGap;
+ UINT32 VolSeqNum;
+ UINT8 FileIdLength;
+ UINT8 FileId[1];
+} ROOT_DIR_HEADER;
+
+typedef struct
+{
+ VOLUME_DESCRIPTOR_HEADER Header;
+ UINT8 Flags;
+ CHAR8 SysId[32];
+ CHAR8 VolId[32];
+ UINT64 Unused;
+ UINT64 VolSpaceSize;
+ CHAR8 EscSeq[32];
+ UINT32 VolSetSize;
+ UINT32 VolSeqNum;
+ UINT32 LBlockSize;
+ UINT64 PathTblSize;
+ UINT32 LPathTbl1;
+ UINT32 LPathTbl2;
+ UINT32 MPathTbl1;
+ UINT32 MPathTbl2;
+ ROOT_DIR_HEADER Root;
+ CHAR8 VolSetId[128];
+ CHAR8 PublisherId[128];
+ CHAR8 DataPrepId[128];
+ CHAR8 ApplicationId[128];
+ CHAR8 CopyrightFileId[37];
+ CHAR8 AbstractFileId[37];
+ CHAR8 BiblioFileId[37];
+ CD_DATE_TIME CreationTime;
+ CD_DATE_TIME ModifyTime;
+ CD_DATE_TIME ExpireTime;
+ CD_DATE_TIME EffectiveTime;
+ UINT8 FileStrucVer;
+ UINT8 Unused1;
+} PRIMARY_VOLUME_DESC_HEADER;
+
+typedef struct
+{
+ VENDOR_DEVICE_PATH Dp;
+ UINT64 VolumeSize;
+ ROOT_DIR_HEADER Root;
+ CHAR8 VolumeLabel[32];
+} AMI_ISO9660_DEVICE_PATH;
+
+#pragma pack()
+
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Gpt.c b/Core/CORE_DXE/Partition/Gpt.c
new file mode 100644
index 0000000..3a1fe92
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Gpt.c
@@ -0,0 +1,606 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.c 16 7/19/12 10:26a Artems $
+//
+// $Revision: 16 $
+//
+// $Date: 7/19/12 10:26a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.c $
+//
+// 16 7/19/12 10:26a Artems
+// [TAG] EIP94126
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] GPT system recovery can't work and backup GPT partition
+// will also be destroyed after GPT recovery.
+// [RootCause] Incorrect LBA used to restore GPT partition
+// [Solution] Use correct LBA
+// [Files] Gpt.c
+//
+// 15 5/02/11 5:57p Artems
+// EIP 59571: New partition driver functionality as per UEFI spec v.2.3.1
+//
+// 14 11/23/10 4:43p Vyacheslava
+// [TAG] EIP45145
+// [Category] New Feature
+// [Description] A new feature has done by Cire Lin: We're did the code
+// for repairing GPT table. If CRC checking fails then it will run
+// CopyGpt() to repair GPT table.
+//
+// 13 4/16/10 4:24p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 12 2/04/10 2:07p Oleksiyy
+// Minor fixes
+//
+// 11 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 10 4/03/09 5:24p Oleksiyy
+// EIP 20879: Linux GPT discovering logic improvement.
+//
+// 9 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 8 4/24/07 6:07p Robert
+// Update for CHM compliance
+//
+// 7 4/12/07 7:04p Robert
+// Coding Standard Updates
+//
+// 6 3/22/07 5:39p Robert
+// Updated Files for coding standard
+//
+// 5 10/10/06 3:22p Yakovlevs
+// Bug fixes. The GPT Partition Driver working now.
+//
+// 4 5/19/06 10:47p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 3 2/11/05 6:14p Felixp
+// - Code optimized by using DPAddNode instead of DPAdd
+// - bug fixes
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Gpt.c
+//
+// Description: EFI GPT Partition Generic Driver.
+// This file detects whether or not the system has a GPT format
+// for the drive and sets up all partitions on the drive
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//-----------------------------------------------------------------------------
+// Includes
+#include "Partition.h"
+#include "Gpt.h"
+#include "Mbr.h"
+
+//-----------------------------------------------------------------------------
+// global variables
+
+
+//-----------------------------------------------------------------------------
+// Function Definitions
+
+
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+// Procedure: AdjustBufferSize
+//
+// Description: Calculates correct Buffer size for BlockIO trasfer
+//
+// Input: EFI_BLOCK_IO_PROTOCOL *BlockIo BlockIo Protocol Interface
+// UINTN *BufferSize Pointer To the Size Needed
+//
+// Output: Modifies Buffer Size to reflect correct number of bytes
+//
+// Returns: Nothing
+//
+// Referrals:
+//
+//<AMI_PHDR_END>
+//-----------------------------------------------------------------------------
+
+VOID AdjustBufferSize(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN OUT UINTN *BufferSize)
+{
+ UINTN sz;
+
+ // Calculate the size of trazaction
+ sz=BlockIo->Media->BlockSize * (*BufferSize/BlockIo->Media->BlockSize);
+
+ if (*BufferSize % BlockIo->Media->BlockSize) sz+=BlockIo->Media->BlockSize;
+
+ *BufferSize=sz;
+}
+
+
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: CopyGpt
+//
+// Description: Copies a valid GPT to the location of an invalid one
+//
+// Input:
+// BlockIo - pointer to the BlockIo partition so we can read and write
+// to the Block Device
+// DiskIo - Unused at this time
+// Destination - Pointer to where the valid GPT will be copied
+// Source - Pointer to a valid GPT
+//
+// Output: None - A valid GPT will be written to the Destination address
+//
+// Returns: None
+//
+// Referrals: CopyMem ReadBlocks CalculateCrc32 AllocatePool AdjustBufferSize
+// WriteBlocks FreePool
+//
+//<AMI_PHDR_END>
+//-----------------------------------------------------------------------------
+
+VOID CopyGpt(
+ EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ EFI_DISK_IO_PROTOCOL *DiskIo,
+ GPT_HEADER *Destination,
+ GPT_HEADER *Source
+)
+{
+ EFI_STATUS Status;
+ UINT8 *EntryArray;
+ EFI_LBA EntryLba;
+ UINTN Size;
+ UINT32 Crc32;
+
+ // Calculate Buffer Size for Enrty array
+ Size = Source->NumberOfPartitionEntries * Source->SizeOfPartitionEntry;
+ AdjustBufferSize(BlockIo, &Size);
+
+ if (Source->MyLba == 1)
+ EntryLba = Source->LastUsableLba + 1;
+ else
+ EntryLba = Source->AlternateLba + 1;
+
+ // Copy the GPT Header
+ gBS->CopyMem( Destination, Source, sizeof(GPT_HEADER) );
+
+ Destination->MyLba = Source->AlternateLba;
+ Destination->AlternateLba = Source->MyLba;
+ Destination->PartitionEntryLba = EntryLba;
+ Destination->Crc32 = 0;
+ Destination->Header.CRC32 = 0;
+
+ // Allocate Memory for Source Patrition Table Array
+ Status = gBS->AllocatePool( EfiBootServicesData, Size, &EntryArray );
+
+ // Zero it out
+ gBS->SetMem( EntryArray, Size, 0 );
+
+ // Read Source's Partition Table Entry Array to the buffer
+ Status = BlockIo->ReadBlocks(
+ BlockIo,
+ BlockIo->Media->MediaId,
+ Source->PartitionEntryLba,
+ Size,
+ EntryArray
+ );
+
+ // Calculate CRC32 of GIUID Partition Table Entry Array
+ gBS->CalculateCrc32(
+ (UINT8*)EntryArray,
+ Source->NumberOfPartitionEntries * Source->SizeOfPartitionEntry,
+ &Crc32
+ );
+ Destination->Crc32 = Crc32;
+
+ gBS->CalculateCrc32(
+ (UINT8*)Destination,
+ sizeof(GPT_HEADER),
+ &Crc32
+ );
+ Destination->Header.CRC32 = Crc32;
+
+
+ // Write to Destination Partition Header Block
+ Status = BlockIo->WriteBlocks(
+ BlockIo,
+ BlockIo->Media->MediaId,
+ Destination->MyLba,
+ BlockIo->Media->BlockSize,
+ Destination
+ );
+
+ // Write Destination Partition Table Entry Array
+ Status = BlockIo->WriteBlocks(
+ BlockIo,
+ BlockIo->Media->MediaId,
+ Destination->PartitionEntryLba,
+ Size,
+ EntryArray
+ );
+
+ gBS->FreePool(EntryArray);
+}
+
+
+//<AMI_PHDR_START>
+//=============================================================================
+// Procedure: ValidateGptHeader
+//
+// Description: Checks if the GPT table is valid
+//
+// Input:
+// BlockIo - Pointer to the Parent BlockIo instance
+// GptHeader - Pointer to a memory area that contains the GPT header
+// to validate
+// HdrLoc - Header location
+//
+// Output: None
+//
+// Returns:
+// EFI_SUCCESS - GPT is valid
+// EFI_INVALID_PARAMETER - checks to see if the CRC, signature, and Header
+// Location are vlaid
+// EFI_OUT_OF_RESOURCES - Not enough free memory to allocate to read the
+// GPT entry table
+//
+// Referrals: CalculateCrc32 MemCmp AdjustBufferSize AllocatePool ReadBlocks
+// FreePool
+//
+//=============================================================================
+//<AMI_PHDR_END>
+EFI_STATUS ValidateGptHeader(
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN GPT_HEADER *GptHeader,
+ IN EFI_LBA HdrLoc
+)
+{
+ EFI_STATUS Status;
+ UINT32 Crc;
+ UINT32 Temp32;
+ UINTN Size;
+ PARTITION_ENTRY *GptEntryTable;
+
+
+ // Get CRC of the Partition Header
+ Temp32 = GptHeader->Header.CRC32;
+ GptHeader->Header.CRC32 = 0;
+
+ gBS->CalculateCrc32((UINT8*)GptHeader, sizeof(GPT_HEADER), &Crc);
+ GptHeader->Header.CRC32 = Crc;
+
+ // Check calculated CRC
+ // Check signature
+ // Check that MyLBA parameter points to the location of the current Header
+ if (MemCmp(EFI_GPT_HEADER_ID, &GptHeader->Header.Signature, sizeof(UINT64))
+ || (Temp32 != Crc)
+ || (GptHeader->MyLba != HdrLoc) )
+ return EFI_INVALID_PARAMETER;
+
+ // Calculate the size of trasaction
+ Size = GptHeader->NumberOfPartitionEntries *
+ GptHeader->SizeOfPartitionEntry;
+ AdjustBufferSize(BlockIo,&Size);
+
+ // allocate memory for the Entry array
+ Status = gBS->AllocatePool( EfiBootServicesData, Size, &GptEntryTable);
+
+ if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+
+ // get the data from the entry array
+ BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId,
+ GptHeader->PartitionEntryLba,
+ Size, GptEntryTable);
+
+ // calculate the CRC value for the entry array
+ gBS->CalculateCrc32((UINT8*)GptEntryTable,
+ GptHeader->NumberOfPartitionEntries*
+ GptHeader->SizeOfPartitionEntry, &Crc);
+
+ // the the allocated memory
+ if (GptEntryTable != NULL ) gBS->FreePool(GptEntryTable);
+
+ // check if the CRC that was calculated matches the value that was stored
+ if (Crc != GptHeader->Crc32) return EFI_INVALID_PARAMETER;
+
+ // All checks passed, the GPT is valid
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//=============================================================================
+// Procedure: VerifyPartionTables
+//
+// Description: Check if either GPT is valid. if only one is then fix the other
+// if both are bad, then it is not a valid GPT system. return error
+//
+// Input:
+// BlockIo - pointer to the BlockIo partition so we can read and write
+// to the Block Device
+// DiskIo - Unused at this time
+//
+// Output:
+// GPT - pointer to a memory space for one GPT
+//
+// Returns: EFI_SUCCESS - If a valid GPT is found
+// EFI_UNSUPPORTED - if no valid GPT is found
+// EFI_OUT_OF_RESOURCES - not enough allocateable memory is available
+//
+// Referrals: AllocatePool ReadBlocks FreePool AdjustBufferSize
+// ValidateGPTHeader CopyGPT CopyMem
+//
+// Notes
+//
+//=============================================================================
+//<AMI_PHDR_END>
+EFI_STATUS VerifyPartionTables(
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ OUT GPT_HEADER *Gpt
+)
+{
+ EFI_STATUS Status;
+ GPT_HEADER *Primary = NULL;
+ GPT_HEADER *Secondary = NULL;
+ MASTER_BOOT_RECORD *Pmbr = NULL;
+ UINTN Size;
+ UINT8 i, FoundPP = 0;
+
+ // Allocate a buffer for the Protective MBR
+ Status = gBS->AllocatePool(EfiBootServicesData, BlockIo->Media->BlockSize, &Pmbr);
+
+ if (EFI_ERROR(Status)) return EFI_OUT_OF_RESOURCES;
+
+ // Read the Protective MBR from LBA #0
+ Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, 0,
+ BlockIo->Media->BlockSize, Pmbr);
+
+ if (EFI_ERROR (Status))
+ {
+ gBS->FreePool(Pmbr);
+ return Status;
+ }
+
+ for (i=0; i < 4; i++)
+
+ // See if Protective MBR is valid and if not free allocated memory and return EFI_UNSUPPORTED
+ if ((Pmbr->PartRec[i].BootIndicator == 0x00) && (Pmbr->PartRec[i].OSType == 0xee) &&
+ (Pmbr->PartRec[i].StartingLba == 1)) FoundPP++;
+
+ if (FoundPP == 0)
+ {
+ gBS->FreePool(Pmbr);
+ return EFI_UNSUPPORTED;
+ }
+
+ // Allocate memory to hold the data for the Primary and Secondary GPT headers
+ // Allocate Primary
+ Size=sizeof(GPT_HEADER);
+ AdjustBufferSize(BlockIo, &Size);
+
+ Status = gBS->AllocatePool(EfiBootServicesData, Size, &Primary);
+
+ // if error is returned, exit with No resources available
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(Pmbr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Allocate for secondary header
+ Status = gBS->AllocatePool(EfiBootServicesData, Size, &Secondary);
+
+ // if error, free memory allocated for primary and then exit with no resources available
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(Pmbr);
+ gBS->FreePool(Primary);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Read primary and backup table
+ BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 1, Size, Primary);
+ BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, BlockIo->Media->LastBlock, Size, Secondary);
+
+ // read primary header from the block device and verify if it is valid
+ if (EFI_ERROR(ValidateGptHeader(BlockIo, Primary, 1)))
+ {
+ // if primary is not valid, check secondary to see if it is valid
+ if (EFI_ERROR(ValidateGptHeader(BlockIo, Secondary, BlockIo->Media->LastBlock)))
+ {
+ gBS->FreePool(Pmbr);
+ gBS->FreePool(Primary);
+ gBS->FreePool(Secondary);
+ return EFI_UNSUPPORTED;
+ }
+
+ // if secondary table is good, copy to primary
+ else
+ {
+ CopyGpt(BlockIo, DiskIo, Primary, Secondary);
+ }
+ }
+
+ // if primary is good, check secondary
+ else
+ {
+ // if secondary is bad, copy primary to secondary
+ if (EFI_ERROR(ValidateGptHeader(BlockIo, Secondary, BlockIo->Media->LastBlock)))
+ {
+ CopyGpt(BlockIo, DiskIo, Secondary, Primary);
+ }
+ }
+
+ // now that both tables are fixed, copy to GPT output variable and exit
+ gBS->CopyMem(Gpt, Primary, sizeof(GPT_HEADER));
+
+ // before we exit free all memory allocation and exit with success
+ gBS->FreePool(Pmbr);
+ gBS->FreePool(Primary);
+ gBS->FreePool(Secondary);
+
+ return EFI_SUCCESS;
+}
+
+
+
+//<AMI_PHDR_START>
+//=============================================================================
+// Procedure: GPTDiscoverPartitions
+//
+// Description: Searches GPT Table for partitions
+//
+// Input:
+// *This - Pointer to the instance of this blockIo protocol
+// *BlockIo - Pointer to the parent blockIo Protocol
+// *DiskIo - Pointer to the parent DiskIo protocol
+// *DevicePath - Pointer to the Parent's device path
+// ControllerHandle - the parent's controller handle
+//
+// Output: None
+//
+// Returns:
+// EFI_SUCCESS - Driver loaded
+// other - Driver not loaded
+//
+// Referrals: AllocatePool FreePool VerifyPartionTables AdjustBufferSize
+// MemCmp SetMem CopyMem CreateChildHandle SET_NODE_LENGTH
+//
+//=============================================================================
+//<AMI_PHDR_END>
+EFI_STATUS GptDiscoverPartitions (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+)
+{
+ EFI_STATUS Status;
+ GPT_HEADER *Gpt = NULL;
+ UINT8 *EntryArray = NULL;
+ PARTITION_ENTRY *PartEntry=NULL;
+ HARDDRIVE_DEVICE_PATH HdDp;
+ PARTITION_DATA PData;
+ UINTN Idx;
+ UINTN Size;
+
+
+ // Allocate memory for a valid GPT partiton header
+ Status = gBS->AllocatePool(EfiBootServicesData, sizeof(GPT_HEADER), &Gpt);
+
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+// EFI_DEADLOOP();
+ // verify that the GPT headers on this BlockIo device are valid
+ if (EFI_ERROR(VerifyPartionTables(BlockIo, DiskIo, Gpt )) )
+ {
+ gBS->FreePool(Gpt);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // If this gets executed, then the Headers are valid and the Entry array
+ // has the correct CRC value
+ // Now parse through the Entry Array and create instances for each
+ // partition on the media
+ // Check Entry Table Crc
+ Size = Gpt->NumberOfPartitionEntries * Gpt->SizeOfPartitionEntry;
+ AdjustBufferSize(BlockIo, &Size);
+
+ Status = gBS->AllocatePool(EfiBootServicesData, Size, &EntryArray);
+
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(Gpt);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId,
+ Gpt->PartitionEntryLba, Size, EntryArray);
+
+ for (Idx = 0; Idx < Gpt->NumberOfPartitionEntries; Idx++)
+ {
+ PartEntry = (PARTITION_ENTRY *)(EntryArray + Idx * Gpt->SizeOfPartitionEntry);
+
+ // Check to see if this is an unused partition
+ if (!(MemCmp(&PartEntry->PartitionTypeGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID))))
+ continue; // This is an unused partition
+
+ if(PartEntry->Attributes & 0x2) //bit 1 of Attributes set?
+ continue; //no BlockIo for this partition - UEFI spec 2.3.1 p.5.3.3 table 19
+
+ // clear the data structure
+ gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0);
+
+ // set up the device path for the partition
+ HdDp.Header.Type = MEDIA_DEVICE_PATH;
+ HdDp.Header.SubType = MEDIA_HARDDRIVE_DP;
+ SET_NODE_LENGTH(&HdDp.Header,sizeof(HARDDRIVE_DEVICE_PATH));
+
+ // Idx is 0 based so add one so that partitionNumber is 1 based
+ HdDp.PartitionNumber = (UINT32) Idx + 1;
+ HdDp.PartitionStart = PartEntry->StartingLba;
+ HdDp.PartitionSize = PartEntry->EndingLba - PartEntry->StartingLba + 1;
+ gBS->CopyMem(&HdDp.Signature, &PartEntry->UniquePartitionGuid,
+ sizeof(EFI_GUID));
+ HdDp.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+ HdDp.SignatureType = SIGNATURE_TYPE_GUID;
+
+ PData.DevPath = DPAddNode(DevicePath, &HdDp.Header);
+
+ // save pertinent info
+ PData.Handle = NULL;
+ PData.ParentHandle = ControllerHandle;
+ PData.ParentBlockIo = BlockIo;
+ PData.ParentDiskIo = DiskIo;
+ PData.StartingLba = PartEntry->StartingLba;
+ PData.EndingLba = PartEntry->EndingLba;
+ gBS->CopyMem(&PData.PartGuid, &PartEntry->PartitionTypeGuid,
+ sizeof (EFI_GUID));
+
+ // This is a valid GPT partition: Add a child instance
+ Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize);
+
+ }
+
+ gBS->FreePool(Gpt);
+ gBS->FreePool(EntryArray);
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Gpt.h b/Core/CORE_DXE/Partition/Gpt.h
new file mode 100644
index 0000000..120b90a
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Gpt.h
@@ -0,0 +1,161 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.h 6 7/09/09 5:01p Oleksiyy $
+//
+// $Revision: 6 $
+//
+// $Date: 7/09/09 5:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Gpt.h $
+//
+// 6 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 5 1/08/08 4:37p Robert
+//
+// 4 1/08/08 4:00p Robert
+//
+// 3 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 2 4/24/07 6:06p Robert
+// Update for CHM compliance
+//
+// 1 1/28/05 1:17p Felixp
+//
+// 2 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 1 12/22/04 6:19p Admin
+//
+// 1 12/22/04 6:18p Admin
+//
+// 2 12/02/04 5:54p Robert
+// Partition driver version works
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <GPT.h>
+//
+// Description: EFI GPT Partition Generic Driver Header.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _GPT_H_
+#define _GPT_H_
+
+#pragma pack(1)
+
+#define EFI_GPT_HEADER_ID "EFI PART"
+
+// GUID Partition Table Header
+//<AMI_STHDR_START>
+//============================================================================
+// Structure: GPT_HEADER
+//
+// Description: Data Structure definition of the GPT table
+//
+// Fields:
+// Header - EFI_TABLE_HEADER - defines generic EFI header information
+// MyLba - EFI_LBA - The LBA that contains this GPT data structure
+// AlternateLba - EFI_LBA - The LBA that contains the alternative GPT
+// data structure
+// FirstUsableLba - EFI_LBA - the first logical block that can be used
+// in a partition that is defined by the GPT
+// LastUsableLba - EFI_LBA - the last logical block that can be used
+// in a partition that is defined by the GPT
+// DiskGuid - EFI_GUID - Unique GUID to identify this hard drive
+// PartitionEntryLba - EFI_LBA - the starting LBA of the GUID Partition
+// Entry Array
+// NumberOfPartitionEntries - UINT32 - the number of partition entries
+// in the Array
+// SizeOfPartitionEntry - UINT32 - the size of each partition entry
+// Crc32 - UINT32 - crc value of the entire GPT block
+//
+// Referral:
+// EFI_TABLE_HEADER EFI_LBA EFI_GUID
+//============================================================================
+//<AMI_STHDR_END>
+typedef struct
+{
+ EFI_TABLE_HEADER Header;
+ EFI_LBA MyLba;
+ EFI_LBA AlternateLba;
+ EFI_LBA FirstUsableLba;
+ EFI_LBA LastUsableLba;
+ EFI_GUID DiskGuid;
+ EFI_LBA PartitionEntryLba;
+ UINT32 NumberOfPartitionEntries;
+ UINT32 SizeOfPartitionEntry;
+ UINT32 Crc32;
+} GPT_HEADER;
+
+// GPT Partition Entry
+//<AMI_STHDR_START>
+//============================================================================
+// Structure: PARTITION_ENTRY
+//
+// Description: Data Structure definition of a partion entry in the GPT table
+//
+// Fields:
+// PartitionTypeGuid - EFI_GUID - contains GUID that defines that type
+// of GUID
+// UniquePartitionGuid - EFI_GUID - contains unique GUID for each
+// partition
+// StartingLba - EFI_LBA - first LBA of the partition
+// EndingLba - EFI_LBA - last logical block address
+// Attributes - UINT64 - UEFI defined attributes
+// Bit 0 - Partition is required for platform to function
+// Bits 1 - 47 - undefined
+// Bits 48 - 64 - reserved for GUID specific use
+// PartitionName[36] - CHAR16 - unicode string containing the name of
+// the partition
+//
+// Referral:
+// EFI_LBA
+//============================================================================
+//<AMI_STHDR_END>
+typedef struct
+{
+ EFI_GUID PartitionTypeGuid;
+ EFI_GUID UniquePartitionGuid;
+ EFI_LBA StartingLba;
+ EFI_LBA EndingLba;
+ UINT64 Attributes;
+ CHAR16 PartitionName[36];
+} PARTITION_ENTRY;
+
+
+#pragma pack()
+
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Mbr.c b/Core/CORE_DXE/Partition/Mbr.c
new file mode 100644
index 0000000..7ccdae8
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Mbr.c
@@ -0,0 +1,407 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.c 12 4/16/10 4:24p Pats $
+//
+// $Revision: 12 $
+//
+// $Date: 4/16/10 4:24p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.c $
+//
+// 12 4/16/10 4:24p Pats
+// EIP 30719: Support for the HDD with sector size more than 512bytes.
+//
+// 11 2/04/10 3:03p Oleksiyy
+// EIP 31633 Minor Fix
+//
+// 10 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 9 11/13/08 6:10p Felixp
+// Bug fix in MbrCreateChildHandle: unsed part of the signature (12 bytes)
+// in hard driver device path was never initialized.
+//
+// 8 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 7 4/25/07 11:52a Robert
+// Updated for CHM and coding standard commpliance
+//
+// 5 5/19/06 10:47p Felixp
+// Device Path code updated to use NEXT_NODE/NODE_LENGTH/SET_NODE_LENGTH
+// macros to remove direct access to the Length field
+//
+// 3 7/12/05 5:01p Robert
+// The Free BSD operating system created a partition that referenced
+// itself. This was not checked for in the partition driver so an
+// infinite loop was created.
+// this reference now causes an error condition..
+//
+// 2 2/11/05 6:13p Felixp
+// Code optimized by using DPAddNode instead of DPAdd
+//
+// 6 12/21/04 4:54p Markw
+// Modified device path defines for consistency.
+//
+// 5 12/02/04 5:54p Robert
+// Partition driver version works
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Mbr.c
+//
+// Description: EFI Mbr Partition Generic Driver. This file finds all
+// the partitions defined in the MBR found on a Device
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+//-----------------------------------------------------------------------------
+// Includes
+#include "partition.h"
+#include "mbr.h"
+
+
+//-----------------------------------------------------------------------------
+// Global Variables
+EFI_GUID gMbrPartition = EFI_PART_TYPE_LEGACY_MBR_GUID;
+
+
+
+//-----------------------------------------------------------------------------
+// Function Prototypes
+
+
+
+//-----------------------------------------------------------------------------
+// Function Definitions
+
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+// Procedure: CheckValidMbr
+//
+// Description: Makes sure the Master Boot Record has valid partitions
+//
+// Input:
+// *BlockIo - Pointer to the parent blockIo Protocol
+// *Mbr - pointer to a data structure that contains the MBR for
+// the current drive
+//
+// Output: None
+//
+// Returns:
+// TRUE - MBR is valid
+// FALSE - MBR is invalid
+//
+// Referrals: ReadBlocks
+//
+//<AMI_PHDR_END>
+//-----------------------------------------------------------------------------
+
+BOOLEAN CheckValidMbr(
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN MASTER_BOOT_RECORD *Mbr
+)
+{
+ EFI_STATUS Status;
+ EFI_LBA EndLba;
+ UINT8 PartitionFound = 0;
+ UINT8 Idx;
+ UINT8 Loop2;
+
+ // read the first block of the Harddrive
+ Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0,
+ BlockIo->Media->BlockSize, Mbr);
+
+ if (Mbr->Sig != MBR_SIGNATURE)
+ return FALSE;
+
+ // check for valid LBA range for all the partitions
+ for (Idx = 0; Idx < NUM_MBR_PARTITIONS; Idx++)
+ {
+ // ignore partitions whose OSType or Size is zero
+ if ((Mbr->PartRec[Idx].OSType == 0)
+ || (Mbr->PartRec[Idx].SizeInLba == 0))
+ continue;
+
+ if (Mbr->PartRec[Idx].StartingLba == 0)
+ continue;
+
+ PartitionFound++;
+
+ EndLba = Mbr->PartRec[Idx].StartingLba
+ + Mbr->PartRec[Idx].SizeInLba - 1;
+
+ // check to make sure the partition does not exceed the length
+ // of the disk
+ if (EndLba > BlockIo->Media->LastBlock)
+ return FALSE;
+
+ // Now loop through all partitions to make sure they don't overlap
+ for (Loop2 = Idx+1; Loop2 < NUM_MBR_PARTITIONS; Loop2++)
+ {
+ // ignore partitions whose OSType or Size is zero
+ if ((Mbr->PartRec[Loop2].OSType == 0)
+ || (Mbr->PartRec[Loop2].SizeInLba == 0))
+ continue;
+
+ // check for overlapping partitions
+ if ( EndLba >= Mbr->PartRec[Loop2].StartingLba )
+ return FALSE;
+ }
+ }
+
+ if (PartitionFound)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+
+//-----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+// Procedure: MbrCreateChildHandle
+//
+// Description: Searches Master Boot Record for partitions
+//
+// Input:
+// *This - Pointer to the instance of this blockIo protocol
+// *BlockIo - Pointer to the parent blockIo Protocol
+// *DiskIo - Pointer to the parent DiskIo protocol
+// *DevicePath - Pointer to the Parent's device path
+// ControllerHandle - the parent's controller handle
+//
+// Output: None
+//
+// Returns:
+// EFI_SUCCESS - Driver loaded
+// other - Driver not loaded
+//
+// Referrals: AllocatePool FreePool CheckValidMbr SetMem ReadBlocks
+// CopyMem CreateChildHandle SET_NODE_LENGTH
+//<AMI_PHDR_END>
+//-----------------------------------------------------------------------------
+
+EFI_STATUS MbrCreateChildHandle(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+)
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *Mbr = NULL;
+ MASTER_BOOT_RECORD *ExtPart = NULL;
+ UINT8 Idx;
+ UINT32 PartitionExists = 0;
+ PARTITION_DATA PData;
+ EFI_GUID *PartType = NULL;
+ EFI_LBA Lba;
+ HARDDRIVE_DEVICE_PATH HdDp;
+
+
+ // allocate memory for the MBR and then read the data from the disk
+ Status = gBS->AllocatePool( EfiBootServicesData,
+ BlockIo->Media->BlockSize, &Mbr);
+
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ // check to see if the current drive has a valid MBR and a valid
+ // partition on the drive
+ if (CheckValidMbr(BlockIo, Mbr) == FALSE)
+ {
+ gBS->FreePool(Mbr);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // To get here there is a valid partition
+ // create a handle for the partitions
+
+ // set up the device path header for the partition
+ HdDp.Header.Type = MEDIA_DEVICE_PATH;
+ HdDp.Header.SubType = MEDIA_HARDDRIVE_DP;
+ SET_NODE_LENGTH(&HdDp.Header,sizeof(HARDDRIVE_DEVICE_PATH));
+
+ // Loop through the partitions
+ for (Idx=0; Idx < NUM_MBR_PARTITIONS; Idx++)
+ {
+ // skip over empty partitions
+ if ((Mbr->PartRec[Idx].OSType == 0)
+ || (Mbr->PartRec[Idx].SizeInLba == 0))
+ continue;
+
+ // Take care of repetative data assignment
+ // clear the data structure
+ gBS->SetMem(&PData, sizeof(PARTITION_DATA), 0);
+
+ // set up the device path for the partition
+ HdDp.MBRType = MBR_TYPE_MASTER_BOOT_RECORD;
+ HdDp.SignatureType = SIGNATURE_TYPE_MBR;
+ pBS->SetMem(&HdDp.Signature,sizeof(HdDp.Signature),0);
+ PData.Handle = NULL;
+ PData.ParentBlockIo = BlockIo;
+ PData.ParentDiskIo = DiskIo;
+
+
+ // Now that a valid partition is found process it
+ // TODO: are there any other types of extended partitions
+ // if so, add them to this if statement
+ if ((Mbr->PartRec[Idx].OSType == EXTENDED_PARTITION) ||
+ (Mbr->PartRec[Idx].OSType == WIN95_EXTENDED_PARTITION))
+ {
+ // process the logical partitions that may or may not exist
+ Status = gBS->AllocatePool( EfiBootServicesData,
+ BlockIo->Media->BlockSize, &ExtPart);
+
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(Mbr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // defines where to start reading the next MBR/partition
+ // table from
+ Lba = Mbr->PartRec[Idx].StartingLba;
+
+ // loop through logical partitions: any number of
+ // possible partitions
+ while (TRUE)
+ {
+ // if the table points back to itself, exit
+ if ( Lba == 0)
+ break;
+
+ // get Partition table from the first block of the device
+ Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId,
+ Lba, BlockIo->Media->BlockSize, ExtPart);
+
+ // check to see if the disk was read
+ // Also check for All logical partitions having an OSType
+ // of 0x05 or EXTENDED_PARTITION
+ if (EFI_ERROR(Status))
+ {
+ gBS->FreePool(Mbr);
+ gBS->FreePool(ExtPart);
+ return Status;
+ }
+
+ // make sure this is a valid partition
+ if (ExtPart->PartRec[0].OSType == NO_PARTITION)
+ break;
+
+ // check for problems that make the partition invalid
+ if ((Lba + ExtPart->PartRec[0].SizeInLba) >
+ (Mbr->PartRec[Idx].StartingLba
+ + Mbr->PartRec[Idx].SizeInLba))
+ break;
+
+ // register the Partition
+ HdDp.PartitionNumber = ++PartitionExists;
+
+ // notice that the start of the partition is after the
+ // partition table
+ HdDp.PartitionStart = ExtPart->PartRec[0].StartingLba + Lba;
+ HdDp.PartitionSize = ExtPart->PartRec[0].SizeInLba;
+ gBS->CopyMem(&HdDp.Signature, &ExtPart->UniqueMbrSig,
+ sizeof(UINT32));
+ PData.StartingLba = HdDp.PartitionStart;
+ PData.EndingLba = HdDp.PartitionStart
+ + ExtPart->PartRec[0].SizeInLba - 1;
+
+ // create device path
+ PData.DevPath = DPAddNode(DevicePath, &HdDp.Header);
+
+ // Store Parent Handle
+ PData.ParentHandle = ControllerHandle;
+
+ // if the OSType member is 0xEF this variable set.
+ // otherwise it is left as 0
+ if (ExtPart->PartRec[0].OSType == EFI_SYSTEM_PARTITION)
+ gBS->CopyMem(&PData.PartGuid, &gMbrPartition,
+ sizeof (EFI_GUID));
+
+ // This is a valid GPT partition: Add a child instance
+ Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize);
+
+ // check to see if the next partition is an extended partition
+ if ((ExtPart->PartRec[1].OSType != EXTENDED_PARTITION) &&
+ (ExtPart->PartRec[1].OSType != WIN95_EXTENDED_PARTITION) )
+ break;
+
+ // get set up for the next partition. The Starting Lba
+ // address is a relative address inside the extended
+ // partition add the starting address of the extended
+ // partition to get the actual LBA where it starts
+ Lba = ExtPart->PartRec[1].StartingLba
+ + Mbr->PartRec[Idx].StartingLba;
+ }
+ }
+
+ else // process primary partition
+ {
+ // set up the device path for the partition
+ HdDp.PartitionNumber = ++PartitionExists;
+ HdDp.PartitionStart = Mbr->PartRec[Idx].StartingLba;
+ HdDp.PartitionSize = Mbr->PartRec[Idx].SizeInLba;
+ gBS->CopyMem(HdDp.Signature, &Mbr->UniqueMbrSig, sizeof(UINT32));
+
+ // create device path
+ PData.DevPath = DPAddNode(DevicePath, &HdDp.Header);
+
+ // save pertinent info
+ PData.StartingLba = Mbr->PartRec[Idx].StartingLba;
+ PData.EndingLba = Mbr->PartRec[Idx].StartingLba
+ + Mbr->PartRec[Idx].SizeInLba - 1;
+
+ // Store Parent Handle
+ PData.ParentHandle = ControllerHandle;
+
+ // if the OSType member is 0xEF is this variable set.
+ // otherwise it is left as 0
+ if (Mbr->PartRec[Idx].OSType == 0xEF)
+ gBS->CopyMem(&PData.PartGuid, &gMbrPartition,
+ sizeof (EFI_GUID));
+
+ // This is a valid GPT partition: Add a child instance
+ Status = CreateChildHandle(This, &PData, BlockIo->Media->BlockSize);
+
+ }
+ }
+
+ gBS->FreePool(Mbr);
+ gBS->FreePool(ExtPart);
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Mbr.h b/Core/CORE_DXE/Partition/Mbr.h
new file mode 100644
index 0000000..2aa5123
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Mbr.h
@@ -0,0 +1,171 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.h 7 7/09/09 5:01p Oleksiyy $
+//
+// $Revision: 7 $
+//
+// $Date: 7/09/09 5:01p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Mbr.h $
+//
+// 7 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 6 1/08/08 3:10p Robert
+//
+// 5 1/08/08 3:08p Robert
+//
+// 4 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 3 4/25/07 11:53a Robert
+// Updated for CHM and Coding Standard Compliance
+//
+// 2 4/24/05 12:45a Felixp
+// Definitions of SIGNATURE_TYPE_xxx macroses removed since they are
+// already defined in DevicePath.h
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <Mbr.h>
+//
+// Description: EFI Mbr Partition Generic Driver Header. This header
+// contains Data structures and Definitions needed to recognize
+// partitions in an MBR
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef _MBR_H
+#define _MBR_H
+
+#define MBR_SIGNATURE 0xaa55
+#define NUM_MBR_PARTITIONS 4
+
+// Type definitions for the Hard drive device path
+#define MBR_TYPE_MASTER_BOOT_RECORD 0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+// Needed Partition Type definitions for MBR
+#define NO_PARTITION 0x0
+#define EXTENDED_PARTITION 0x05
+#define WIN95_EXTENDED_PARTITION 0x0f
+
+
+//<AMI_GHDR_START>
+//------------------------------------------------------------------
+// Name: Data_Structures
+//
+// Description:
+// Data Structures needed for MBR
+//
+// MASTER_BOOT_RECORD - Data Structure definition of the
+// MBR located in the first block on an MBR drive
+//
+// MBR_PARTITION - Data Structure definition for each
+// partition in the MBR
+//
+//------------------------------------------------------------------
+//<AMI_GHDR_END>
+
+#pragma pack(1)
+
+//<AMI_STHDR_START>
+//============================================================================
+// Structure: MBR_PARTITION
+//
+// Description: Data Structure that defines a partition within the MBR
+//
+// Fields:
+// BootIndicator - UINT8 - indicates whether this partition is bootable
+// StartHead - UINT8 - unused in EFI
+// StartSector - UINT8 - unused in EFI
+// StartTrack - UINT8 - unused in EFI
+// OSType - UINT8 - defines type of the partition
+// EndHead - UINT8 - unused in EFI
+// EndSector - UINT8 - unused in EFI
+// EndTrack - UINT8 - unused in EFI
+// StartingLba - UINT32 - LBA where the partiton starts on the hard drive
+// SizeInLba - UINT32 - LBA where the partiton ends on the hard drive
+//
+// Referral:
+// None
+//============================================================================
+//<AMI_STHDR_END>
+typedef struct _MBR_PARTITION
+{
+ UINT8 BootIndicator;
+ UINT8 StartHead;
+ UINT8 StartSector;
+ UINT8 StartTrack;
+ UINT8 OSType;
+ UINT8 EndHead;
+ UINT8 EndSector;
+ UINT8 EndTrack;
+ UINT32 StartingLba;
+ UINT32 SizeInLba;
+} MBR_PARTITION;
+
+
+// MBR Partition table
+//============================================================================
+// Structure: MASTER_BOOT_RECORD
+//
+// Description: Data Structure that mimicks the structure of a Master Boot
+// Record on a hard drive
+//
+// Fields:
+// BootCode[440] - UINT8 - executable code in the first 440 bytes of a
+// hard drive
+// UniqueMbrSig - UINT32 - Uniques signature associated with the hard
+// drive
+// Unknown - UINT16 - an unknown portion of the data structure
+// PartRec[4] - MBR_PARTITION - an array of partition entries that
+// define the partitions that exist on the hard drive
+// Sig - UINT16 - 0xaa55 - value that indicates this is an MBR
+//
+// Referral:
+// MBR_PARTITION
+//============================================================================
+//<AMI_STHDR_END>
+typedef struct _MASTER_BOOT_RECORD
+{
+ UINT8 BootCode[440];
+ UINT32 UniqueMbrSig;
+ UINT16 Unknown;
+ MBR_PARTITION PartRec[4];
+ UINT16 Sig;
+} MASTER_BOOT_RECORD;
+
+
+#pragma pack()
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Partition.c b/Core/CORE_DXE/Partition/Partition.c
new file mode 100644
index 0000000..78cbb10
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Partition.c
@@ -0,0 +1,1006 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.c 21 10/27/11 3:57p Artems $
+//
+// $Revision: 21 $
+//
+// $Date: 10/27/11 3:57p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.c $
+//
+// 21 10/27/11 3:57p Artems
+// EIP 73250: Verified DriverBinding Stop function frees all resources
+// allocated by Start function
+//
+// 20 10/25/11 12:01p Artems
+// EIP 70530: Fixed bugs reported by SCT 2.3.1
+//
+// 19 8/12/11 12:16p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 18 5/02/11 5:58p Artems
+// EIP 59571: Extended partition driver functionality - support of BlockIO
+// protocol version 3
+//
+// 17 2/05/11 3:52p Artems
+// Removed previous check-in changes
+//
+// 16 1/06/11 5:59p Oleksiyy
+// [TAG] EIP28607
+// [Category] Improvement
+// [Description] System was hanging for some time if Floppy Media
+// removed while writing in meda in progress.
+// EFI_TPL_CALLBACK priority level rised during media related calls.
+// [Files] DiskIo.c, Info.c, MediaAccess.c, Open.c, Partition.c
+//
+// 15 2/04/10 3:06p Oleksiyy
+// EIP 31633 Minor fixes. OpenProtocol error status handling added to
+// DriverBindingStop function.
+//
+// 14 8/28/09 9:10a Felixp
+// Component Name protocol implementation is upadted to support both
+// ComponentName and ComponentName2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 13 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 12 1/16/09 11:25a Felixp
+// Bug fix in the DriverBindingStop function.
+// The stop function was unconditionally closing disk I/O protocol.
+// The protocol should only be closed when no child devices exist.
+//
+// 11 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 10 4/26/07 9:32a Robert
+// Updated for CHM and Coding Standard compliance
+//
+// 8 3/23/07 5:13p Robert
+// More coding standard changes and updated the copyright date
+//
+// 7 3/22/07 5:39p Robert
+// Updated Files for coding standard
+//
+// 6 10/10/06 3:43p Yakovlevs
+// Uncommented GPT Partition discovery
+//
+// 5 8/24/06 12:34p Felixp
+// x64 support (fixes for warnings/errors)
+//
+// 3 10/28/05 8:36p Felixp
+// DriverBindingSupported: Device Path test changed from BY_DRIVER to
+// TEST_PROTOCOL
+//
+// 2 2/08/05 12:50p Felixp
+// Bug fix in ReadBlocks and WriteBlocks: attemp to read/write
+// Last LBA on the partition returned EFI_INVALID_PARAMETER
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Partition.c
+//
+// Description: EFI Partition Generic Driver. Provides the Driver
+// Binding protocol and a Block I/O protocol for Partition detection
+// and interaction
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+//;-------------------------------------------------------------------------
+// Includes
+#include "partition.h"
+
+
+//;-------------------------------------------------------------------------
+// Global Variables
+EFI_BOOT_SERVICES *gBS;
+EFI_GUID gUnusedPartitionGuid = EFI_PART_TYPE_UNUSED_GUID;
+static EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+
+EFI_STATUS gDevicePathStatus = EFI_SUCCESS;
+EFI_STATUS gDiskIoStatus = EFI_SUCCESS;
+
+//;-------------------------------------------------------------------------
+//GUID Variables
+static EFI_GUID gDevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+EFI_GUID gBlockIoGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+EFI_GUID gDiskIoGuid = EFI_DISK_IO_PROTOCOL_GUID;
+
+//;-------------------------------------------------------------------------
+// Function Prototypes
+EFI_STATUS DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS EFIAPI DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath );
+
+EFI_STATUS EFIAPI DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer);
+
+EFI_STATUS Reset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification);
+
+EFI_STATUS ReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+EFI_STATUS WriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+EFI_STATUS FlushBlocks ( IN EFI_BLOCK_IO_PROTOCOL *PartBlockIo);
+
+//;-------------------------------------------------------------------------
+// Protocol Definition
+EFI_BLOCK_IO_PROTOCOL mPartitionBlockIo =
+{
+ EFI_BLOCK_IO_PROTOCOL_REVISION3,
+ NULL,
+ Reset,
+ ReadBlocks,
+ WriteBlocks,
+ FlushBlocks
+};
+
+
+//;-------------------------------------------------------------------------
+// Partition Driver Binding Procol
+EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding =
+{
+ DriverBindingSupported,
+ DriverBindingStart,
+ DriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+
+//;-------------------------------------------------------------------------
+// Function Definitions
+#ifdef EFI_DEBUG
+#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core
+#ifndef LANGUAGE_CODE_ENGLISH
+#define LANGUAGE_CODE_ENGLISH "eng"
+#endif
+static BOOLEAN LanguageCodesEqual(
+ CONST CHAR8* LangCode1, CONST CHAR8* LangCode2
+){
+ return LangCode1[0]==LangCode2[0]
+ && LangCode1[1]==LangCode2[1]
+ && LangCode1[2]==LangCode2[2];
+}
+static EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+#endif
+//Driver Name
+static UINT16 *gDriverName=L"AMI Partition Driver";
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+//
+// Procedure: ComponentNameGetControllerName
+//
+// Description: Retrieves a Unicode string that is the user readable name of
+// the controller that is being managed by an EFI Driver.
+//
+// Input:
+// 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 Supported Languages. The number of languages supported by a
+// driver is up to the driver writer.
+//
+// Output:
+// 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 thedriver 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.
+//
+// Referrals:
+//
+// Notes:
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: ComponentNameGetDriverName
+//
+// Description: Returns the Driver Name if the language is supported
+//
+// Input:
+// This - Pointer to the instance of this driver
+// Language - Current operating language
+// DriverName - return parameter that will contain the Driver's Name
+//
+// Output: DriverName - return parameter that will contain the Driver's Name
+//
+// Returns:
+// EFI_SUCCESS - Driver loaded
+// EFI_INVALID_PARAMETER - If the Language or DriverName variable is
+// not defined
+// EFI_UNSUPPORTED - If the current laungage is not supported
+//
+// Referrals:
+//
+// Notes:
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS ComponentNameGetDriverName(
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName)
+{
+ //Supports only English
+ if (!Language || !DriverName) return EFI_INVALID_PARAMETER;
+
+ if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH))
+ return EFI_UNSUPPORTED;
+ else
+ *DriverName=gDriverName;
+
+ return EFI_SUCCESS;
+}
+
+//Component Name Protocol
+static EFI_COMPONENT_NAME2_PROTOCOL gComponentName =
+{
+ ComponentNameGetDriverName,
+ ComponentNameGetControllerName,
+ LANGUAGE_CODE_ENGLISH
+};
+#endif
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: PartitionEntryPoint
+//
+// Description: Register Driver Binding protocol for this driver.
+//
+// Input:
+// ImageHandle - Identification Handle for the Partition
+// Block I/O driver
+// *SystemTable - Pointer to the EFI System Table
+//
+// Returns:
+// EFI_SUCCESS - Driver Binding Protocol Loaded
+// other - Driver Binding Protocol not loaded
+//
+// Referrals: InitAmiLib InstallMultipleProtocolInterfaces
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS PartitionEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+
+ InitAmiLib(ImageHandle, SystemTable);
+
+ gBS = SystemTable->BootServices;
+
+ // initiaize the ImageHandle and DriverBindingHandle
+ gPartitionDriverBinding.DriverBindingHandle = NULL;
+ gPartitionDriverBinding.ImageHandle = ImageHandle;
+
+ // Install driver binding protocol here
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gPartitionDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gPartitionDriverBinding,
+#ifdef EFI_DEBUG
+ &gEfiComponentName2ProtocolGuid, &gComponentName,
+#endif
+ NULL);
+
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: DriverBindingSupported
+//
+// Description: Test to see if this driver supports ControllerHandle. Any
+// ControllerHandle than contains a BlockIo and DiskIo protocol can be
+// supported.
+//
+// Input:
+// This - Protocol instance pointer.
+// ControllerHandle - Handle of device to test
+// RemainingDevicePath - Not used
+//
+// Output: None
+//
+// Returns:
+// EFI_SUCCESS - This driver supports this device
+// EFI_ALREADY_STARTED - This driver is already running on this device
+// other - This driver does not support this device
+//
+// Referrals: OpenProtocol CloseProtocol
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_STATUS Status;
+
+ // see if the DevicePath is installed on controllerHandle
+ Status = gBS->OpenProtocol(ControllerHandle, &gDevicePathGuid,
+ NULL, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ if (EFI_ERROR(Status))
+ return Status;
+
+ // Close the Device Path Protocol once the tests have been done
+ gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ // see if the DiskIo has already been started on controllerHandle
+ Status = gBS->OpenProtocol(ControllerHandle, &gDiskIoGuid,
+ &DiskIo, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ if (EFI_ERROR(Status))
+ return Status;
+
+ // Close the DiskIo protocol once the tests have been done
+ gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ // Now check for BlockIo Protocol
+ Status = gBS->OpenProtocol(ControllerHandle, &gBlockIoGuid,
+ NULL, This->DriverBindingHandle, ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+
+ // return the status of finding the BlockIo protocol.
+ // if it gets this far the driver supports this device
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: DriverBindingStart
+//
+// Description: Start this driver on ControllerHandle by opening a Block IO and
+// Disk IO protocol, reading Device Path, and creating a child handle with
+// a Disk IO and device path protocol.
+//
+// Input:
+// This - Protocol instance pointer.
+// ControllerHandle - Handle of device to bind driver to
+// RemainingDevicePath - Not used
+//
+// Output: None
+//
+// Return:
+// EFI_SUCCESS - This driver is added to DeviceHandle
+// other - This driver does not support this device
+//
+// Referrals: OpenProtocol CloseProtocol GptDiscoverPartitions
+// ElToritoCreateChildHandle MbrCreateChildHandle
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS EFIAPI DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+)
+{
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+
+ // Open the BlockIo protocol first because we are opening it by
+ // GET_PROTOCOL, if this fails it does not need to be closed. It is
+ // opened by GET_PROTOCOL because DiskIo already opens it BY_DRIVER
+ Status = gBS->OpenProtocol(ControllerHandle, &gBlockIoGuid,
+ &BlockIo, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR (Status))
+ return Status;
+
+ Status = gBS->OpenProtocol(ControllerHandle, &gDevicePathGuid,
+ &ParentDevicePath, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR (Status))
+ return Status;
+
+ // Check to see if the Controller has already been started by
+ // another driver
+ // Now open the DiskIo protocol for the controller
+ Status = gBS->OpenProtocol(ControllerHandle, &gDiskIoGuid,
+ &DiskIo, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ if (EFI_ERROR (Status))
+ {
+ // if there is an error, close all opened protocols, only close
+ // this one if
+ // Close the Device Path protocol once the tests have been done
+ gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ return Status;
+ }
+
+
+ // parse the devices and create the child handles
+ if (BlockIo->Media->MediaPresent == TRUE)
+ {
+ Status = EFI_NOT_FOUND;
+
+ // search for the children
+ Status = GptDiscoverPartitions(This, BlockIo, DiskIo,
+ ParentDevicePath, ControllerHandle);
+
+ if (EFI_ERROR(Status))
+ Status = ElToritoCreateChildHandle(This, BlockIo, DiskIo,
+ ParentDevicePath, ControllerHandle);
+
+ if (EFI_ERROR(Status))
+ Status = MbrCreateChildHandle(This, BlockIo, DiskIo,
+ ParentDevicePath, ControllerHandle);
+ }
+
+ else
+ Status = EFI_NO_MEDIA;
+
+
+ // Now close all protocols That were not already started
+ if (EFI_ERROR(Status) )
+ {
+ gBS->CloseProtocol(ControllerHandle, &gDevicePathGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid,
+ This->DriverBindingHandle, ControllerHandle);
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: DriverBindingStop
+//
+// Description: Stop this driver on ControllerHandle. Support stoping
+// any child handles created by this driver.
+//
+// Input:
+// This - Protocol instance pointer.
+// DeviceHandle - Handle of device to stop driver on
+// NumberOfChildren - Number of Children in the ChildHandleBuffer
+// ChildHandleBuffer - List of handles for the children we need to stop.
+//
+// Output: None
+//
+// Return:
+// EFI_SUCCESS - This driver is removed DeviceHandle
+// other - This driver was not removed from this device
+//
+// Referrals: CloseProtocol OpenProtocol FlushBlocks MemCmp FreePool
+// UninstallMultipleProtocolInterfaces
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS EFIAPI DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+)
+{
+
+ EFI_HANDLE Handle = *ChildHandleBuffer;
+ PARTITION_DATA *Child = NULL;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_GUID *PartType = NULL;
+ BOOLEAN ChildrenLeft = FALSE;
+ EFI_STATUS Status;
+ UINTN Idx = 0;
+
+
+ // Close these protocols if there are no children left
+ if (NumberOfChildren == 0)
+ {
+ gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid,
+ This->DriverBindingHandle, ControllerHandle);
+
+ return EFI_SUCCESS;
+ }
+
+ // There are children, uninstall protocols and uninstall interfaces,
+ // and free memory
+ while (Idx < NumberOfChildren)
+ {
+ Status = gBS->OpenProtocol(ChildHandleBuffer[Idx], &gBlockIoGuid,
+ (VOID **)&BlockIo, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status))
+ {
+ Idx++;
+ continue;
+ }
+
+ Child = (PARTITION_DATA *)BlockIo;
+
+ // clear all buffers for the current device
+ BlockIo->FlushBlocks(BlockIo);
+
+ // now close all handles
+ gBS->CloseProtocol(ControllerHandle, &gDiskIoGuid,
+ This->DriverBindingHandle, ChildHandleBuffer[Idx]);
+
+ // look for a non 0 Partition type GUID
+ // if non zero, set the point to the address, otherwise leave pointer
+ // as zero
+ if (MemCmp(&Child->PartGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID)))
+ PartType = &Child->PartGuid;
+
+ // Create the new handle for the child device
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Idx],
+ &gDevicePathGuid, Child->DevPath,
+ &gBlockIoGuid, &Child->BlockIo,
+ PartType, NULL,
+ NULL );
+
+ if (EFI_ERROR(Status))
+ ChildrenLeft = TRUE;
+
+ // free the memory that was allocated for The Child handle and the
+ // device path for the child handle
+
+
+ if (Child->DevPath != NULL)
+ gBS->FreePool(Child->DevPath);
+
+ if (Child->BlockIo.Media != NULL)
+ gBS->FreePool(Child->BlockIo.Media);
+
+ gBS->FreePool(Child);
+
+
+ // Increment Child Handle Pointer
+ Idx++;
+
+ // clear PartGuid pointer for the next child
+ PartType = NULL;
+ }
+
+ // if there are childrem left, exit with error
+ if (ChildrenLeft == TRUE)
+ return EFI_DEVICE_ERROR;
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: Reset
+//
+// Description: Reset the parent Block Device.
+//
+// Input:
+// This - Protocol instance pointer.
+// ExtendedVerification - Driver may perform diagnostics on reset.
+//
+// Output: None
+//
+// Return:
+// EFI_SUCCESS - The device was reset.
+// EFI_DEVICE_ERROR - The device is not functioning properly and could
+// not be reset.
+//
+// Referrals: ParentBlockIo->Reset
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Reset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+)
+{
+ PARTITION_DATA *PartData;
+
+ if (This == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ // Find the parent's BlockIo Protocol
+ PartData = (PARTITION_DATA *) This;
+
+ return PartData->ParentBlockIo->Reset(PartData->ParentBlockIo,
+ ExtendedVerification);
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: ReadBlocks
+//
+// Description: Reads blocks from the parent device
+//
+// Input:
+// This - Protocol instance pointer.
+// MediaId - Id of the media, changes every time the media is replaced.
+// Lba - The starting Logical Block Address to read from
+// BufferSize - Size of Buffer, must be a multiple of device block size.
+//
+// Output:
+// Buffer - Buffer containing read data
+//
+// Return:
+// EFI_SUCCESS - The data was read correctly from the device.
+// EFI_DEVICE_ERROR - The device reported an error while performing the read.
+// EFI_NO_MEDIA - There is no media in the device.
+// EFI_MEDIA_CHANGED - The MediaId does not match the current device.
+// EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
+// device.
+// EFI_INVALID_PARAMETER - The read request contains device addresses that are not
+// valid for the device.
+//
+// Referrals: Mul64 ReadDisk
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadBlocks ( IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ PARTITION_DATA *PartData;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ UINT64 Start;
+
+ if (This == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ // Find the parent BlockIo Protocol
+ PartData = (PARTITION_DATA *) This;
+
+ if(MediaId != PartData->BlockIo.Media->MediaId)
+ return EFI_MEDIA_CHANGED;
+
+ if(BufferSize == 0)
+ return EFI_SUCCESS;
+
+ if (BufferSize % PartData->BlockIo.Media->BlockSize != 0)
+ return EFI_BAD_BUFFER_SIZE;
+
+ // calculate the byte from which to start the read
+ Start = (Mul64(PartData->StartingLba,
+ PartData->ParentBlockIo->Media->BlockSize) +
+ Mul64(Lba, This->Media->BlockSize));
+
+ // check to see if the read will go beyond the end of the
+ // current partition
+ if ( ((Start + BufferSize - 1) >=
+ Mul64(PartData->EndingLba+1,
+ PartData->ParentBlockIo->Media->BlockSize)) ||
+ (Buffer == NULL))
+ return EFI_INVALID_PARAMETER;
+
+
+ // Make call directly to DiskIo of the device
+
+ DiskIo = PartData->ParentDiskIo;
+
+ return DiskIo->ReadDisk(DiskIo, MediaId, Start, BufferSize, Buffer);
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: WriteBlocks
+//
+// Description: Write blocks to the parent device
+//
+// Input:
+// This - Protocol instance pointer.
+// MediaId - Id of the media, changes every time the media is replaced.
+// Lba - The starting Logical Block Address to read from
+// BufferSize - Size of Buffer, must be a multiple of device block size.
+// Buffer - Buffer containing read data
+//
+// Output: None
+//
+// Return:
+// EFI_SUCCESS - The data was written correctly to the device.
+// EFI_WRITE_PROTECTED - The device can not be written to.
+// EFI_DEVICE_ERROR - The device reported an error while performing the write.
+// EFI_NO_MEDIA - There is no media in the device.
+// EFI_MEDIA_CHANGED - The MediaId does not match the current device.
+// EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the
+// device.
+// EFI_INVALID_PARAMETER - The write request contains a LBA that is not
+// valid for the device.
+//
+// Referrals: Mul64 WriteDisk
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+)
+{
+ PARTITION_DATA *PartData;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ UINT64 Start;
+
+ if (This == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ // Find the parent BlockIo Protocol
+ PartData = (PARTITION_DATA *) This;
+
+ if(MediaId != PartData->BlockIo.Media->MediaId)
+ return EFI_MEDIA_CHANGED;
+
+ if (BufferSize % PartData->BlockIo.Media->BlockSize != 0)
+ return EFI_BAD_BUFFER_SIZE;
+
+ // calculated the start address of the write command
+ Start = Mul64(PartData->StartingLba,
+ PartData->ParentBlockIo->Media->BlockSize) +
+ Mul64(Lba, This->Media->BlockSize);
+
+ if ( ((Start + BufferSize - 1) >=
+ Mul64(PartData->EndingLba+1,
+ PartData->ParentBlockIo->Media->BlockSize)) ||
+ (Buffer == NULL))
+ return EFI_INVALID_PARAMETER;
+
+ DiskIo = PartData->ParentDiskIo;
+
+ return DiskIo->WriteDisk(DiskIo, MediaId, Start, BufferSize, Buffer);
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: FlushBlocks
+//
+// Description: Flush the parent Block Device.
+//
+// Input: This - Protocol instance pointer.
+//
+// Output: None
+//
+// Return:
+// EFI_SUCCESS - All outstanding data was written to the device
+// EFI_DEVICE_ERROR - The device reported an error while writing back
+// the data
+// EFI_NO_MEDIA - There is no media in the device.
+//
+// Referrals: ParentBlockIo->FlushBlocks
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+)
+{
+ PARTITION_DATA *PartData;
+
+ if (This == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ PartData = (PARTITION_DATA *) This;
+
+ // return the same value that the device specific BlockIo instance returns
+ return PartData->ParentBlockIo->FlushBlocks(PartData->ParentBlockIo);
+}
+
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+// Procedure: CreateChildHandle
+//
+// Description: Generic create child handle for the partition driver. This
+// should work for GPT, MBR, and El Torito.
+//
+// Input:
+// *This - Pointer to the current instance of the blockIo protocol
+// *PData - a pointer to the start of the private data structure for
+// the partition
+// BlockSize - the blocksize for the partition
+//
+// Output:
+//
+// Return:
+// EFI_SUCCESS - Child created
+// other - no child created
+//
+// Referrals: AllocatePool FreePool CopyMem MemCmp Div64 OpenProtocol
+// InstallMultipleProtocolInterfaces UninstallMultipleProtocolInterfaces
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CreateChildHandle(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN PARTITION_DATA *PData,
+ IN UINT32 BlockSize
+)
+{
+ PARTITION_DATA *Child;
+ EFI_BLOCK_IO_MEDIA *Media;
+ EFI_STATUS Status;
+ EFI_GUID *PartType = NULL;
+ UINTN Temp;
+
+
+ // allocate memory for the Child handle
+ Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PARTITION_DATA), &Child);
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ Status = gBS->AllocatePool(EfiBootServicesData, sizeof(EFI_BLOCK_IO_MEDIA), &Media);
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool(Child);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Copy the data from one location to the other,
+ gBS->CopyMem(Child, PData, sizeof(PARTITION_DATA));
+
+ // get the BlockIo protocol for the partition driver and the
+ // media information from the parent device
+ gBS->CopyMem(&Child->BlockIo, &mPartitionBlockIo, sizeof(EFI_BLOCK_IO_PROTOCOL));
+
+ // just point to the media info for the device, that way we don't have to
+ // worry about changing values
+ Child->BlockIo.Media = Media;
+
+ gBS->CopyMem(Media, PData->ParentBlockIo->Media, sizeof(EFI_BLOCK_IO_MEDIA));
+
+ Media->LogicalPartition = TRUE;
+ Media->BlockSize = BlockSize;
+ Media->IoAlign = 1; //no alignment requirements
+ Media->LowestAlignedLba = 0; //added in Revision 2
+ Media->LogicalBlocksPerPhysicalBlock = 0; //added in Revision 2
+ Media->OptimalTransferLengthGranularity = 0; //added in Revision 3
+
+ // Calculate the last block of the partition
+ Media->LastBlock = Div64( Mul64(PData->EndingLba - PData->StartingLba + 1,
+ Child->ParentBlockIo->Media->BlockSize),
+ BlockSize, &Temp) - 1;
+
+ // look for a non 0 Partition type GUID
+ // if non zero, set the point to the address, otherwise leave
+ // pointer as zero
+ if (MemCmp(&Child->PartGuid, &gUnusedPartitionGuid, sizeof(EFI_GUID)))
+ PartType = &Child->PartGuid;
+
+ // Create the new handle for the child device
+ Child->Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Child->Handle,
+ &gDevicePathGuid, Child->DevPath,
+ &gBlockIoGuid, &Child->BlockIo,
+ PartType, NULL,
+ NULL );
+
+ // Now open the diskIo protocol for the child, if the install multiple
+ // protocol interface returns SUCCESS
+ if (!EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol ( Child->ParentHandle,
+ &gDiskIoGuid,
+ &Child->ParentDiskIo,
+ This->DriverBindingHandle,
+ Child->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER );
+
+ if (EFI_ERROR(Status)) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ &Child->Handle,
+ &gDevicePathGuid, Child->DevPath,
+ &gBlockIoGuid, &Child->BlockIo,
+ PartType, NULL,
+ NULL );
+ //free all resources
+ gBS->FreePool(Child->DevPath);
+ gBS->FreePool(Media);
+ gBS->FreePool(Child);
+ }
+ }
+
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Partition.cif b/Core/CORE_DXE/Partition/Partition.cif
new file mode 100644
index 0000000..feaa5cb
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Partition.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "Partition"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\Partition\"
+ RefName = "Partition"
+[files]
+"Partition.sdl"
+"ElTorito.c"
+"ElTorito.h"
+"Gpt.c"
+"Gpt.h"
+"Mbr.c"
+"Mbr.h"
+"Partition.c"
+"Partition.h"
+<endComponent>
diff --git a/Core/CORE_DXE/Partition/Partition.h b/Core/CORE_DXE/Partition/Partition.h
new file mode 100644
index 0000000..047cfc8
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Partition.h
@@ -0,0 +1,188 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.h 10 8/12/11 12:16p Artems $
+//
+// $Revision: 10 $
+//
+// $Date: 8/12/11 12:16p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/Partition/Partition.h $
+//
+// 10 8/12/11 12:16p Artems
+// EIP 64107: Added changes for module to be compliant with UEFI
+// specification v 2.3.1
+//
+// 9 7/09/09 5:01p Oleksiyy
+// Files clean-up
+//
+// 8 1/08/08 2:47p Robert
+//
+// 7 1/08/08 2:47p Robert
+//
+// 6 1/07/08 4:21p Robert
+// Updated for coding standard
+//
+// 5 4/25/07 12:44p Robert
+// updates for CHM and Coding Standard Compliance
+//
+// 3 4/24/05 12:45a Felixp
+// Definitions of SIGNATURE_TYPE_xxx macroses removed since they are
+// already defined in DevicePath.h
+//
+// 6 12/14/04 6:14p Robert
+// Added component name protocol support
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Partition.h
+//
+// Description: EFI Partition Generic Driver Header. This file
+// contains the GUIDs used by this driver. It also contains
+// Definitions and Data Structures needed by the generic portion of
+// the Partition driver.
+//
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#ifndef _PARTITION_H
+#define _PARTITION_H
+
+
+#include <AmiDxeLib.h>
+
+// protocols consumed
+#include <protocol\BlockIo.h>
+#include <protocol\DiskIo.h>
+#include <protocol\DevicePath.h>
+#include <protocol\DriverBinding.h>
+#include <Protocol\ComponentName2.h>
+
+extern EFI_BOOT_SERVICES *gBS;
+extern EFI_GUID gUnusedPartitionGuid;
+
+//=============================================================================
+// GUID Definitions
+
+#define EFI_PART_TYPE_UNUSED_GUID \
+ { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \
+ { 0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b}
+
+#define EFI_PART_TYPE_LEGACY_MBR_GUID \
+ { 0x024dee41, 0x33e7, 0x11d3, 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f}
+
+
+
+#define MBR_TYPE_PCAT 0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+#define EFI_SYSTEM_PARTITION 0xef
+
+
+//=============================================================================
+// Structure definitions
+
+//<AMI_STHDR_START>
+//============================================================================
+// Structure: OPCODE_CMD
+//
+// Description: Data Structure definition of the Private data for each instance
+// of the Partition Block I/O driver
+//
+// Fields:
+// BlockIo - EFI_BLOCK_IO_PROTOCOL - Pointer to the EFI_BLOCK_IO_PROTOCOL
+// protocol for this partition
+// Handle - EFI_HANDLE - child handle for this partition
+// ParentBlockIo - EFI_BLOCK_IO_PROTOCOL * - pointer to the
+// EFI_BLOCK_IO_PROTOCOL of the parent device
+// ParentDiskIo - EFI_DISK_IO_PROTOCOL * - pointer to the
+// EFI_DISK_IO_PROTOCOL of the parent device
+// DevPath - EFI_DEVICE_PATH_PROTOCOL * - pointer to the device path
+// for this device
+// StartingLba - EFI_LBA - The starting Lba of the current partition
+// EndingLba - EFI_LBA - The ending Lba of the current partition
+// PartGuid - EFI_GUID - The GUID assigned to the partition
+// ParentHandle - EFI_HANDLE - the handle assigned to the parent device
+//
+// Referral:
+// None
+//============================================================================
+//<AMI_STHDR_END>
+typedef struct _PARTITION_DATA
+{
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL *ParentBlockIo;
+ EFI_DISK_IO_PROTOCOL *ParentDiskIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ EFI_LBA StartingLba;
+ EFI_LBA EndingLba;
+ EFI_GUID PartGuid;
+
+ EFI_HANDLE ParentHandle;
+} PARTITION_DATA;
+
+
+//=============================================================================
+// Function Prototypes
+EFI_STATUS CreateChildHandle(EFI_DRIVER_BINDING_PROTOCOL *This, PARTITION_DATA *PData,
+ UINT32 BlockSize);
+
+EFI_STATUS GptDiscoverPartitions (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+);
+
+EFI_STATUS ElToritoCreateChildHandle (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+);
+
+EFI_STATUS MbrCreateChildHandle(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
+ IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HANDLE ControllerHandle
+);
+
+#endif
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/Partition/Partition.sdl b/Core/CORE_DXE/Partition/Partition.sdl
new file mode 100644
index 0000000..a846251
--- /dev/null
+++ b/Core/CORE_DXE/Partition/Partition.sdl
@@ -0,0 +1,4 @@
+PATH
+ Name = "PARTITION_DIR"
+End
+
diff --git a/Core/CORE_DXE/SetWatchdogTimer.c b/Core/CORE_DXE/SetWatchdogTimer.c
new file mode 100644
index 0000000..2146137
--- /dev/null
+++ b/Core/CORE_DXE/SetWatchdogTimer.c
@@ -0,0 +1,84 @@
+/*++
+
+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:
+
+ SetWatchdogTimer.c
+
+Abstract:
+
+ Tiano Miscellaneous Services SetWatchdogTimer service implementation
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSetWatchdogTimer (
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Sets the system's watchdog timer.
+
+Arguments:
+
+ Timeout The number of seconds. Zero disables the timer.
+
+ ///////following three parameters are left for platform specific using
+
+ WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware
+ DataSize Size of the optional data
+ WatchdogData Optional Null terminated unicode string followed by binary
+ data.
+
+Returns:
+
+ EFI_SUCCESS Timeout has been set
+ EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
+ EFI_UNSUPPORTED System does not have a timer (currently not used)
+ EFI_DEVICE_ERROR Could not complete due to hardware error
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Check our architectural protocol
+ //
+ if (gWatchdogTimer == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Attempt to set the timeout
+ //
+ Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));
+
+ //
+ // Check for errors
+ //
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/Stall.c b/Core/CORE_DXE/Stall.c
new file mode 100644
index 0000000..a87f894
--- /dev/null
+++ b/Core/CORE_DXE/Stall.c
@@ -0,0 +1,79 @@
+/*++
+
+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:
+
+ Stall.c
+
+Abstract:
+
+ Tiano Miscellaneous Services Stall service implementation
+
+--*/
+
+//
+// Include statements
+//
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Introduces a fine-grained stall.
+
+Arguments:
+
+ Microseconds The number of microseconds to stall execution
+
+Returns:
+
+ EFI_SUCCESS - Execution was stalled for at least the requested amount
+ of microseconds.
+
+ EFI_NOT_AVAILABLE_YET - gMetronome is not available yet
+
+--*/
+{
+ UINT32 Counter;
+ UINTN Remainder;
+
+ if (gMetronome == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Calculate the number of ticks by dividing the number of microseconds by
+ // the TickPeriod.
+ // Calcullation is based on 100ns unit.
+ //
+ Counter = (UINT32) DivU64x32 ((Microseconds * 10), (UINTN) gMetronome->TickPeriod, &Remainder);
+
+ //
+ // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
+ // periods, thus attempting to ensure Microseconds of stall time.
+ //
+ if (Remainder != 0) {
+ Counter++;
+ }
+
+ gMetronome->WaitForTick (gMetronome, Counter);
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/USFontPack.c b/Core/CORE_DXE/USFontPack.c
new file mode 100644
index 0000000..e4d86a0
--- /dev/null
+++ b/Core/CORE_DXE/USFontPack.c
@@ -0,0 +1,315 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/EDK/DxeMain/USFontPack.c 4 4/11/12 5:13p Artems $
+//
+// $Revision: 4 $
+//
+// $Date: 4/11/12 5:13p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/EDK/DxeMain/USFontPack.c $
+//
+// 4 4/11/12 5:13p Artems
+// [TAG] EIP81654
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Right arrow (>) is shown as junk in Bios setup when
+// Font.ffs is not used
+// [RootCause] Size of default font package was incorrect
+// [Solution] Changed value for size of font package
+// [Files] usfontpack.c
+//
+// 3 7/11/05 4:52p Felixp
+// minor bug fix: number of characters was invalid so the last character
+// was ignored
+//
+// 2 3/04/05 9:30a Mandal
+//
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: <This File Name>
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//Package for US Latin Glyps + Box Draw and Arrows
+unsigned char UsStdNarrowGlyphData[] = {
+ 0xc0, 0x14, 0x00, 0x00,//Header.Length
+ 0x01, 0x00, //Header.Type 1=Font
+ 0xf1, 0x00, //Number of Narrow Glyphs
+ 0x00, 0x00, //Number of Wide Glyphs
+ // Unicode glyphs from 0x20 to 0x7e are the same as ASCII characters 0x20 to 0x7e
+ 0x20, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x21, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0x22, 0x00, 0x00, 0x00,0x00,0x00,0x6C,0x6C,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x23, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
+ 0x24, 0x00, 0x00, 0x00,0x00,0x18,0x18,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,
+ 0x25, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x26, 0x00, 0x00, 0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x76,0xDC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0x27, 0x00, 0x00, 0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x28, 0x00, 0x00, 0x00,0x00,0x00,0x06,0x0C,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x0C,0x06,0x00,0x00,0x00,0x00,
+ 0x29, 0x00, 0x00, 0x00,0x00,0x00,0xC0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0x60,0xC0,0x00,0x00,0x00,0x00,
+ 0x2a, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0xFE,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2b, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2c, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
+ 0x2d, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x2e, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+ 0x2f, 0x00, 0x00, 0x00,0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC0,0xC0,0x00,0x00,0x00,0x00,
+ 0x30, 0x00, 0x00, 0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
+ 0x31, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
+ 0x32, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xFE,0x00,0x00,0x00,0x00,
+ 0x33, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x3C,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x34, 0x00, 0x00, 0x00,0x00,0x00,0x1C,0x1C,0x3C,0x3C,0x6C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
+ 0x35, 0x00, 0x00, 0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x36, 0x00, 0x00, 0x00,0x00,0x00,0x3C,0x60,0xC0,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x37, 0x00, 0x00, 0x00,0x00,0x00,0xFE,0xC6,0x06,0x06,0x06,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0x38, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x39, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
+ 0x3a, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+ 0x3b, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
+ 0x3c, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
+ 0x3d, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3e, 0x00, 0x00, 0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00,
+ 0x3f, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0x40, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0xC0,0x7E,0x00,0x00,0x00,0x00,
+ 0x41, 0x00, 0x00, 0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x42, 0x00, 0x00, 0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
+ 0x43, 0x00, 0x00, 0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
+ 0x44, 0x00, 0x00, 0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
+ 0x45, 0x00, 0x00, 0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0x46, 0x00, 0x00, 0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x64,0x7C,0x64,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+ 0x47, 0x00, 0x00, 0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xDE,0xC6,0xC6,0xC6,0x66,0x3C,0x00,0x00,0x00,0x00,
+ 0x48, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x49, 0x00, 0x00, 0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xFC,0x00,0x00,0x00,0x00,
+ 0x4a, 0x00, 0x00, 0x00,0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
+ 0x4b, 0x00, 0x00, 0x00,0x00,0x00,0xE6,0x66,0x6C,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+ 0x4c, 0x00, 0x00, 0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0x4d, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xEE,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x4e, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xE6,0xF6,0xF6,0xF6,0xDE,0xCE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x4f, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x50, 0x00, 0x00, 0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+ 0x51, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0x7C,0x1C,0x0E,0x00,0x00,
+ 0x52, 0x00, 0x00, 0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+ 0x53, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x60,0x38,0x0C,0x06,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x54, 0x00, 0x00, 0x00,0x00,0x00,0xFC,0xFC,0xB4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,
+ 0x55, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x56, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
+ 0x57, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
+ 0x58, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x6C,0x38,0x6C,0x6C,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x59, 0x00, 0x00, 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,
+ 0x5a, 0x00, 0x00, 0x00,0x00,0x00,0xFE,0xC6,0x86,0x0C,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
+ 0x5b, 0x00, 0x00, 0x00,0x00,0x00,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1E,0x00,0x00,0x00,0x00,
+ 0x5c, 0x00, 0x00, 0x00,0x00,0x00,0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x06,0x00,0x00,0x00,0x00,
+ 0x5d, 0x00, 0x00, 0x00,0x00,0x00,0xF0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xF0,0x00,0x00,0x00,0x00,
+ 0x5e, 0x00, 0x00, 0x00,0x00,0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5f, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,
+ 0x60, 0x00, 0x00, 0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x61, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0x62, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
+ 0x63, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x64, 0x00, 0x00, 0x00,0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0xCC,0x7E,0x00,0x00,0x00,0x00,
+ 0x65, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x66, 0x00, 0x00, 0x00,0x00,0x00,0x1E,0x33,0x30,0x30,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,
+ 0x67, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00,
+ 0x68, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+ 0x69, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0x6a, 0x00, 0x00, 0x00,0x00,0x00,0x0C,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x38,0x00,
+ 0x6b, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
+ 0x6c, 0x00, 0x00, 0x00,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0x6d, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xEE,0xFE,0xD6,0xD6,0xD6,0xD6,0xD6,0x00,0x00,0x00,0x00,
+ 0x6e, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+ 0x6f, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x70, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
+ 0x71, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
+ 0x72, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+ 0x73, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0x7C,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0x74, 0x00, 0x00, 0x00,0x00,0x00,0x10,0x30,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
+ 0x75, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0x76, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00,0x00,
+ 0x77, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
+ 0x78, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0x79, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
+ 0x7a, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x86,0x0C,0x18,0x30,0x60,0xC0,0xFE,0x00,0x00,0x00,0x00,
+ 0x7b, 0x00, 0x00, 0x00,0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x30,0x18,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
+ 0x7c, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0x7d, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x30,0x30,0x30,0x30,0x18,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00,0x00,0x00,
+ 0x7e, 0x00, 0x00, 0x00,0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xa0, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xa1, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
+ 0xa2, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x18,0x18,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0xa3, 0x00, 0x00, 0x00,0x00,0x00,0x38,0x6C,0x64,0x60,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
+ 0xa4, 0x00, 0x00, 0x00,0x00,0x18,0x00,0x00,0x00,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00,
+ 0xa5, 0x00, 0x00, 0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0xa6, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+ 0xa7, 0x00, 0x00, 0x00,0x00,0x18,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xa8, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xa9, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x7C,0x82,0x9A,0xA2,0xA2,0xA2,0x9A,0x82,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xaa, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x3C,0x6C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xab, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xac, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xad, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xae, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x7C,0x82,0xB2,0xAA,0xAA,0xB2,0xAA,0xAA,0x82,0x7C,0x00,0x00,0x00,0x00,0x00,
+ 0xaf, 0x00, 0x00, 0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb0, 0x00, 0x00, 0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb1, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,
+ 0xb2, 0x00, 0x00, 0x00,0x00,0x00,0x3C,0x66,0x0C,0x18,0x32,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb3, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0x06,0x3C,0x06,0x06,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb4, 0x00, 0x00, 0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb5, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,
+ 0xb6, 0x00, 0x00, 0x00,0x00,0x00,0x7F,0xDB,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
+ 0xb7, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xb8, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x78,0x00,0x00,0x00,
+ 0xb9, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xba, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xbb, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xbc, 0x00, 0x00, 0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00,
+ 0xbd, 0x00, 0x00, 0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,0x00,
+ 0xbe, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x30,0x62,0x36,0xEC,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00,
+ 0xbf, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xc0, 0x00, 0x00, 0x60,0x30,0x18,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc1, 0x00, 0x00, 0x18,0x30,0x60,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc2, 0x00, 0x00, 0x10,0x38,0x6C,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc3, 0x00, 0x00, 0x76,0xDC,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc4, 0x00, 0x00, 0xCC,0xCC,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc5, 0x00, 0x00, 0x38,0x6C,0x38,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xc6, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
+ 0xc7, 0x00, 0x00, 0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x18,0x70,0x00,0x00,
+ 0xc8, 0x00, 0x00, 0x60,0x30,0x18,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0xc9, 0x00, 0x00, 0x18,0x30,0x60,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0xca, 0x00, 0x00, 0x10,0x38,0x6C,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0xcb, 0x00, 0x00, 0xCC,0xCC,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+ 0xcc, 0x00, 0x00, 0x60,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xcd, 0x00, 0x00, 0x18,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xce, 0x00, 0x00, 0x10,0x38,0x6C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xcf, 0x00, 0x00, 0xCC,0xCC,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xd0, 0x00, 0x00, 0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0xF6,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
+ 0xd1, 0x00, 0x00, 0x76,0xDC,0x00,0x00,0xC6,0xE6,0xE6,0xF6,0xF6,0xDE,0xDE,0xCE,0xCE,0xC6,0xC6,0x00,0x00,0x00,0x00,
+ 0xd2, 0x00, 0x00, 0x60,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xd3, 0x00, 0x00, 0x18,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xd4, 0x00, 0x00, 0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xd5, 0x00, 0x00, 0x76,0xDC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xd6, 0x00, 0x00, 0xCC,0xCC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xd7, 0x00, 0x00, 0x10,0x28,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,
+ 0xd8, 0x00, 0x00, 0x00,0x00,0x00,0x7C,0xCE,0xCE,0xDE,0xD6,0xD6,0xD6,0xD6,0xF6,0xE6,0xE6,0x7C,0x40,0x00,0x00,0x00,
+ 0xd9, 0x00, 0x00, 0x60,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xda, 0x00, 0x00, 0x18,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xdb, 0x00, 0x00, 0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xdc, 0x00, 0x00, 0xCC,0xCC,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xdd, 0x00, 0x00, 0x18,0x30,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xde, 0x00, 0x00, 0x00,0x00,0x10,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00,
+ 0xdf, 0x00, 0x00, 0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00,
+ 0xe0, 0x00, 0x00, 0x00,0x30,0x30,0x60,0x30,0x18,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe1, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe2, 0x00, 0x00, 0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe3, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe4, 0x00, 0x00, 0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe5, 0x00, 0x00, 0x00,0x00,0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xe6, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0x36,0x36,0x7E,0xD8,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
+ 0xe7, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x70,0x00,0x00,
+ 0xe8, 0x00, 0x00, 0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xe9, 0x00, 0x00, 0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xea, 0x00, 0x00, 0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xeb, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xec, 0x00, 0x00, 0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xed, 0x00, 0x00, 0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xee, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xef, 0x00, 0x00, 0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+ 0xf0, 0x00, 0x00, 0x00,0x00,0x00,0x34,0x18,0x2C,0x0C,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
+ 0xf1, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+ 0xf2, 0x00, 0x00, 0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf3, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf4, 0x00, 0x00, 0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf5, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf6, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf7, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf8, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xCE,0xDE,0xD6,0xF6,0xE6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+ 0xf9, 0x00, 0x00, 0x00,0x00,0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xfa, 0x00, 0x00, 0x00,0x00,0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xfb, 0x00, 0x00, 0x00,0x00,0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xfc, 0x00, 0x00, 0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+ 0xfd, 0x00, 0x00, 0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
+ 0xfe, 0x00, 0x00, 0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
+ 0xff, 0x00, 0x00, 0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
+ 0x00, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x0c, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x10, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x14, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x18, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x1c, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x24, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x2c, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x34, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x3c, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x50, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x51, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x52, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x53, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x54, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x55, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x56, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x57, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x58, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x59, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5a, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5b, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5c, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5d, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5e, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x5f, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x60, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x61, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x62, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x63, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x64, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x65, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x66, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x67, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x68, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x69, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x6a, 0x25, 0x00, 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+ 0x6b, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x6c, 0x25, 0x00, 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+ 0x88, 0x25, 0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x91, 0x25, 0x00, 0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,
+ 0xba, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,
+ 0xc4, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00,
+ 0xb2, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xbc, 0x25, 0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91, 0x21, 0x00, 0x00,0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+ 0x93, 0x21, 0x00, 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
+ 0x90, 0x21, 0x00, 0x00,0x00,0x00,0x00,0x00,0x20,0x60,0x60,0xFE,0xFE,0x60,0x60,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x92, 0x21, 0x00, 0x00,0x00,0x00,0x00,0x00,0x08,0x0C,0x0C,0xFE,0xFE,0x0C,0x0C,0x08,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/CORE_DXE/UefiHii/HiAccessConfig.c b/Core/CORE_DXE/UefiHii/HiAccessConfig.c
new file mode 100644
index 0000000..d165a1e
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiAccessConfig.c
@@ -0,0 +1,322 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c 7 5/04/11 12:08p Artems $
+//
+// $Revision: 7 $
+//
+// $Date: 5/04/11 12:08p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c $
+//
+// 7 5/04/11 12:08p Artems
+// Bug fix: when variable is absent attribute state was undefined
+//
+// 6 1/25/11 4:03p Artems
+// EIP 51298: Fixed corruption in buffer size after passing it to
+// ConfigToBlock function
+// Added check for correct syntax of request string in ExtractConfig
+// function
+//
+// 5 9/30/10 6:12p Artems
+// Removed unnecessary service functions
+//
+// 3 2/19/10 4:01p Felixp
+// Debug messages are removed.
+//
+// 2 11/25/09 11:25a Felixp
+// Action parameter of the Callback function is updated based on UEFI
+// errata
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: HiiAccessConfig.c
+//
+// Description: Hii Config Access protocol implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#pragma warning (disable : 4090)
+
+#include <AmiDxeLib.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+
+#include "HiiPrivate.h"
+
+extern const NAME_PATTERN GuidPattern;
+extern const NAME_PATTERN NamePattern;
+extern const NAME_PATTERN PathPattern;
+extern const NAME_PATTERN AltCfgPattern;
+extern const NAME_PATTERN OffsetPattern;
+extern const NAME_PATTERN WidthPattern;
+extern const NAME_PATTERN ValuePattern;
+extern const CHAR16 HexDigit[];
+
+UINTN EfiStrLen (IN CHAR16 *String);
+UINTN EfiStrSize (IN CHAR16 *String);
+VOID EfiStrCat (IN CHAR16 *Destination, IN CHAR16 *Source);
+
+//**************************** Protocol functions implementation ***************************
+
+
+EFI_STATUS HiiAccessExtractConfig(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+)
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ EFI_GUID Guid;
+ CHAR16 Name[80];
+ CHAR16 *Pointer = Request;
+ UINT8 *Var = NULL;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
+ CHAR16 *ErrorMarker;
+
+ if(Request == NULL) {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting);
+ if(EFI_ERROR(Status))
+ return Status;
+
+//check syntax for guid
+ if(!CheckPattern(Request, &GuidPattern)) {
+ *Progress = Request;
+ return EFI_INVALID_PARAMETER;
+ }
+//extract guid
+ ErrorMarker = Pointer;
+ Pointer += 5; //skip "GUID=" pattern
+ Length = 32; //length of guid in symbols
+ StringToBlock(Pointer, Length, (UINT8 *)&Guid);
+ Pointer += Length;
+ if(*Pointer != L'&') {
+ TRACE((TRACE_DXE_CORE, "HII Extract Config: Guid extraction failed\n"));
+ *Progress = ErrorMarker;
+ return EFI_INVALID_PARAMETER;
+ }
+
+//check syntax for name
+ if(!CheckPattern(Pointer + 1, &NamePattern)) {
+ *Progress = Pointer;
+ return EFI_INVALID_PARAMETER;
+ }
+//extract name
+ ErrorMarker = Pointer;
+ Pointer += 6; //skip '&NAME=' pattern
+ Length = 80;
+ StringToChar16(Pointer, &Length, Name);
+ Pointer += (Length * 4);
+ if(*Pointer != L'&') {
+ TRACE((TRACE_DXE_CORE, "HII Extract Config: Name extraction failed\n"));
+ *Progress = ErrorMarker;
+ return EFI_INVALID_PARAMETER;
+ }
+
+//get variable by name and guid from nvram
+
+ Length = 0;
+ Status = GetEfiVariable(Name, &Guid, NULL, &Length, &Var);
+ if(EFI_ERROR(Status)) {
+ *Progress = Request;
+ return Status;
+ }
+
+//find start of OFFSET/WIDTH/VALUE block
+ Pointer++; //skip '&'
+ while((*Pointer != L'&') && (*Pointer != 0)) //skip PATH
+ Pointer++;
+
+ if(*Pointer == 0) { //OFFSET/WIDTH blocks are missed
+ UINTN TempSize;
+ CHAR16 *TempString;
+ CHAR16 *TempString2;
+
+ TempSize = (EfiStrLen(L"&OFFSET=0&WIDTH=") + sizeof(Length) + 1) * sizeof(CHAR16);
+ TempString = MallocZ(TempSize);
+ if(TempString == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ Swprintf_s(TempString, TempSize, L"&OFFSET=0&WIDTH=%x", Length);
+
+ TempSize += EfiStrSize(Request);
+ TempString2 = MallocZ(TempSize);
+ if(TempString2 == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ EfiStrCat(TempString2, Request);
+ EfiStrCat(TempString2, TempString);
+
+ Status = ConfigRouting->BlockToConfig(ConfigRouting, TempString2, Var, Length, Results, Progress);
+ *Progress = Request + EfiStrLen(Request); //set Progress to end of ConfigHdr
+ pBS->FreePool(TempString);
+ pBS->FreePool(TempString2);
+ } else { //OFFSET/WIDTH block found, let's check if it's correct
+ if(!CheckPattern(Pointer + 1, &OffsetPattern)) {
+ *Progress = Pointer;
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = ConfigRouting->BlockToConfig(ConfigRouting, Request, Var, Length, Results, Progress);
+ }
+
+ pBS->FreePool(Var);
+
+ return Status;
+}
+
+EFI_STATUS HiiAccessRouteConfig(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+)
+{
+ EFI_STATUS Status;
+ UINTN Length;
+ UINTN VarSize;
+ EFI_GUID Guid;
+ CHAR16 Name[80];
+ CHAR16 *Pointer = Configuration;
+ UINT8 *Var = NULL;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
+ EFI_HANDLE Handle;
+ UINT32 Attributes;
+
+ if(Configuration == NULL)
+ {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting);
+ if(EFI_ERROR(Status))
+ return Status;
+
+//check syntax for guid
+ if(!CheckPattern(Configuration, &GuidPattern))
+ {
+ *Progress = Configuration;
+ return EFI_INVALID_PARAMETER;
+ }
+
+//check proper device path
+ Status = FindDeviceHandle(Configuration, &Handle);
+ if(EFI_ERROR(Status))
+ return EFI_NOT_FOUND;
+
+//extract guid
+ Pointer += 5; //skip "GUID=" pattern
+ Length = 32; //length of guid in bytes
+ StringToBlock(Pointer, Length, (UINT8 *)&Guid);
+ Pointer += Length;
+ if(*Pointer != L'&')
+ {
+ TRACE((TRACE_DXE_CORE, "HII Route Config: Guid extraction failed\n"));
+ *Progress = Pointer;
+ return EFI_INVALID_PARAMETER;
+ }
+
+//check syntax for name
+ if(!CheckPattern(Pointer + 1, &NamePattern))
+ {
+ *Progress = Pointer;
+ return EFI_INVALID_PARAMETER;
+ }
+//extract name
+ Pointer += 6; //skip '&NAME=' pattern
+ Length = 80;
+ StringToChar16(Pointer, &Length, Name);
+ Pointer += (Length * 4);
+ if(*Pointer != L'&')
+ {
+ TRACE((TRACE_DXE_CORE, "HII Route Config: Name extraction failed\n"));
+ *Progress = Pointer;
+ return EFI_INVALID_PARAMETER;
+ }
+
+//get variable by name and guid from nvram
+
+ Length = 0;
+ Status = GetEfiVariable(Name, &Guid, &Attributes, &Length, &Var);
+ if(EFI_ERROR(Status)) //requested variable not found
+ {
+ Var = NULL;
+ Length = 0;
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+ }
+ VarSize = Length;
+
+ Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress);
+ while(Status == EFI_DEVICE_ERROR) //block not large enough
+ {
+ if(Var != NULL)
+ pBS->FreePool(Var);
+
+ Status = pBS->AllocatePool(EfiBootServicesData, Length, &Var);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ VarSize = Length;
+ Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress);
+ }
+
+ if(EFI_ERROR(Status))
+ return Status;
+
+ pRS->SetVariable(Name, &Guid, Attributes, VarSize, Var);
+
+ pBS->FreePool(Var);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiAccessFormCallback(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/UefiHii/Hii.chm b/Core/CORE_DXE/UefiHii/Hii.chm
new file mode 100644
index 0000000..b2affb3
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/Hii.chm
Binary files differ
diff --git a/Core/CORE_DXE/UefiHii/HiiConfig.c b/Core/CORE_DXE/UefiHii/HiiConfig.c
new file mode 100644
index 0000000..8a8b10a
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiConfig.c
@@ -0,0 +1,1263 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiConfig.c 10 6/16/11 12:52p Artems $
+//
+// $Revision: 10 $
+//
+// $Date: 6/16/11 12:52p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiConfig.c $
+//
+// 10 6/16/11 12:52p Artems
+// Bugfix: Handle situation when string passed to BlockToConfig function
+// doesn't have standard header
+//
+// 9 5/13/11 5:17p Artems
+// Function CompareGuid (native EdkII) renamed to HiiCompareGuid to avoid
+// collusion
+//
+// 8 5/09/11 6:40p Artems
+// Bugfix: Handle situation when config string passed to ConfigToBlock
+// function doesn't have standard header
+//
+// 7 1/25/11 3:26p Artems
+// EIP 47960 : Added functionality for ExportConfig function
+//
+// 6 11/05/10 5:17p Artems
+// EIP 46880: Fixed bug, where two functions referred to the same global
+// pointer
+//
+// 4 10/01/10 4:36p Artems
+// Added service function StripValuePattern
+//
+// 2 12/03/09 6:02p Artems
+// SCT test bug fix
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 2/27/09 3:55p Artems
+// Initial check-in
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: HiiConfig.c
+//
+// Description: Hii Config Routing protocol implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#pragma warning (disable : 4090)
+
+#include <AmiDxeLib.h>
+#include "HiiPrivate.h"
+
+
+extern HII_DATABASE_PRIVATE_DATA PrivateData;
+
+const NAME_PATTERN GuidPattern = { 10, L"GUID=" };
+const NAME_PATTERN NamePattern = { 10, L"NAME=" };
+const NAME_PATTERN PathPattern = { 10, L"PATH=" };
+const NAME_PATTERN AltCfgPattern = { 14, L"ALTCFG=" };
+const NAME_PATTERN OffsetPattern = { 14, L"OFFSET=" };
+const NAME_PATTERN WidthPattern = { 12, L"WIDTH=" };
+const NAME_PATTERN ValuePattern = { 12, L"VALUE=" };
+
+const CHAR16 HexDigit[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
+ L'8', L'9', L'a', L'b', L'c', L'd', L'e', L'f' };
+
+EFI_GUID HiiConfigAccessProtocolGuid = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
+
+#define INITIAL_RESULT_STRING_SIZE 0x1000
+
+
+
+//**************************** Protocol functions implementation ***************************
+
+EFI_STATUS HiiExtractConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Request1,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+)
+{
+ EFI_STRING ConfigString;
+ EFI_STRING ErrorPointer;
+ EFI_STRING ResultPointer;
+ BOOLEAN LastString = FALSE;
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE Handle;
+ UINTN ProgressMarker = 0;
+ UINTN Gap;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING Request = Request1;
+ RESULT_BLOCK Result;
+
+ if(Progress == NULL || Results == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(Request == NULL)
+ {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(!CheckPattern(Request, &GuidPattern))
+ {
+ *Progress = Request;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = InitResultBlock(&Result);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ do
+ {
+ Status = ExtractConfigString(Request, &Index, &ConfigString);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if(ConfigString != NULL)
+ {
+ Status = FindDeviceHandle(ConfigString, &Handle);
+ if(EFI_ERROR(Status)) //we failed to find corresponding driver handle
+ {
+ pBS->FreePool(ConfigString);
+ *Progress = &Request[ProgressMarker];
+ *Results = Result.ResultString;
+ return Status;
+ }
+
+ Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess);
+ if(EFI_ERROR(Status)) //we failed to find corresponding protocol
+ {
+ pBS->FreePool(ConfigString);
+ *Progress = &Request[ProgressMarker];
+ *Results = Result.ResultString;
+ return Status;
+ }
+
+ Status = ConfigAccess->ExtractConfig(ConfigAccess, ConfigString,
+ &ErrorPointer, &ResultPointer);
+ if(EFI_ERROR(Status))
+ {
+ Gap = (UINTN)(ErrorPointer - ConfigString); //determine offset of error
+ pBS->FreePool(ConfigString);
+ *Progress = &Request[ProgressMarker + Gap];
+ *Results = Result.ResultString;
+ return Status;
+ }
+
+ ProgressMarker += Index; //shift to next config string
+ Request += Index;
+ pBS->FreePool(ConfigString);
+ Status = CollectResults(ResultPointer, 0, &Result);
+ if (EFI_ERROR(Status))
+ return Status;
+ pBS->FreePool(ResultPointer);
+ }
+ else //now we process last request
+ {
+ LastString = TRUE;
+ Status = FindDeviceHandle(Request, &Handle);
+ if(EFI_ERROR(Status)) //we failed to find corresponding driver handle
+ {
+ *Progress = Request;
+ *Results = Result.ResultString;
+ return Status;
+ }
+
+ Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess);
+ if(EFI_ERROR(Status)) //we failed to find corresponding protocol
+ {
+ *Progress = Request;
+ *Results = Result.ResultString;
+ return Status;
+ }
+
+ Status = ConfigAccess->ExtractConfig(ConfigAccess, Request,
+ &ErrorPointer, &ResultPointer);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = ErrorPointer;
+ *Results = Result.ResultString;
+ return Status;
+ }
+ Status = CollectResults(ResultPointer, 0, &Result);
+ if (EFI_ERROR(Status))
+ return Status;
+ pBS->FreePool(ResultPointer);
+ }
+ } while(!LastString);
+
+ *Results = Result.ResultString;
+
+//set Progress to null-terminator
+ Index = StrSize16(Request) / 2;
+ *Progress = &Request[Index - 1];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS Hii21ExportConfigHelper (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+);
+
+EFI_STATUS HiiExportConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+)
+{
+ if(Results == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ return Hii21ExportConfigHelper (This, Results);
+}
+
+EFI_STATUS HiiRouteConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration1,
+ OUT EFI_STRING *Progress
+)
+{
+ EFI_STRING ConfigString;
+ EFI_STRING ErrorPointer;
+ BOOLEAN LastString = FALSE;
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_HANDLE Handle;
+ UINTN ProgressMarker = 0;
+ UINTN Gap;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING Configuration = Configuration1;
+
+ if(Progress == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(Configuration == NULL)
+ {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(!CheckPattern(Configuration, &GuidPattern))
+ {
+ *Progress = Configuration;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ do
+ {
+ Status = ExtractConfigString(Configuration, &Index, &ConfigString);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if(ConfigString != NULL)
+ {
+ Status = FindDeviceHandle(ConfigString, &Handle);
+ if(EFI_ERROR(Status)) //we failed to find corresponding driver handle
+ {
+ pBS->FreePool(ConfigString);
+ *Progress = &Configuration[ProgressMarker];
+ return Status;
+ }
+
+ Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess);
+ if(EFI_ERROR(Status)) //we failed to find corresponding protocol
+ {
+ pBS->FreePool(ConfigString);
+ *Progress = &Configuration[ProgressMarker];
+ return Status;
+ }
+
+ Status = ConfigAccess->RouteConfig(ConfigAccess, ConfigString, &ErrorPointer);
+ if(EFI_ERROR(Status))
+ {
+ Gap = (UINTN)(ErrorPointer - ConfigString); //determine offset of error
+ pBS->FreePool(ConfigString);
+ *Progress = &Configuration[ProgressMarker + Gap];
+ return Status;
+ }
+
+ ProgressMarker += Index; //shift to next config string
+ Configuration += Index;
+ pBS->FreePool(ConfigString);
+ }
+ else //now we process last cofiguration
+ {
+ LastString = TRUE;
+ Status = FindDeviceHandle(Configuration, &Handle);
+ if(EFI_ERROR(Status)) //we failed to find corresponding driver handle
+ {
+ *Progress = Configuration;
+ return Status;
+ }
+
+ Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess);
+ if(EFI_ERROR(Status)) //we failed to find corresponding protocol
+ {
+ *Progress = Configuration;
+ return Status;
+ }
+
+ Status = ConfigAccess->RouteConfig(ConfigAccess, Configuration, &ErrorPointer);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = ErrorPointer;
+ return Status;
+ }
+ }
+ } while(!LastString);
+
+//set Progress to null-terminator
+ Index = StrSize16(Configuration) / 2;
+ *Progress = &Configuration[Index - 1];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiBlockToConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigRequest,
+ IN CONST UINT8 *Block,
+ IN CONST UINTN BlockSize,
+ OUT EFI_STRING *Config,
+ OUT EFI_STRING *Progress
+)
+{
+ UINTN ProgressMarker;
+ UINTN i = 0;
+ UINTN Start;
+ UINT32 Offset;
+ UINT32 Width;
+ UINT32 ConfigStringSize;
+ EFI_STATUS Status;
+ RESULT_BLOCK Result;
+
+ if(Progress == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(ConfigRequest == NULL || Block == NULL || Config == NULL )
+ {
+ *Progress = ConfigRequest;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ConfigStringSize = StrSize16(ConfigRequest) / 2;
+
+//Prepare result buffer for output
+ Status = InitResultBlock(&Result);
+ if (EFI_ERROR(Status))
+ return Status;
+
+//find start of OFFSET/WIDTH/VALUE block
+ if(!CheckPattern(ConfigRequest, &OffsetPattern)) { //for BlockToConfig function ConfigResp is allowed not to have standard header GUID=...NAME=.
+ do
+ {
+ while((ConfigRequest[i] != L'&') && (ConfigRequest[i] != 0))
+ i++;
+
+ if(ConfigRequest[i] == 0)
+ {
+ *Progress = ConfigRequest;
+ pBS->FreePool(Result.ResultString);
+ return EFI_NOT_FOUND;
+ }
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigRequest[i], &OffsetPattern))
+ break;
+ } while(1);
+ }
+
+ Status = CollectResults(ConfigRequest, i, &Result); //copy header
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+
+ do
+ {
+ ProgressMarker = i - 1; //set ProgressMarker to '&'
+
+ Start = i;
+ Status = GetPatternValue(ConfigRequest, &i, &OffsetPattern, &Offset);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = &ConfigRequest[ProgressMarker];
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+ else
+ {
+ Status = CollectResults(&ConfigRequest[Start], i - Start, &Result); //copy header
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+ }
+
+ Start = i;
+ Status = GetPatternValue(ConfigRequest, &i, &WidthPattern, &Width);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = &ConfigRequest[ProgressMarker];
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+ else
+ {
+ Status = CollectResults(&ConfigRequest[Start], i - Start, &Result); //copy header
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+ }
+
+ if(BlockSize < (Offset + Width))
+ {
+ pBS->FreePool(Result.ResultString);
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CollectValueResults(&Block[Offset], Width, &Result);
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(Result.ResultString);
+ return Status;
+ }
+
+ } while(i < ConfigStringSize);
+
+ *Progress = &ConfigRequest[ConfigStringSize - 1]; //set Progress to null-terminator
+ *Config = Result.ResultString;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiConfigToBlock (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN OUT CONST UINT8 *Block,
+ IN OUT UINTN *BlockSize,
+ OUT EFI_STRING *Progress
+)
+{
+ UINTN ProgressMarker;
+ UINTN i = 0;
+ UINT32 Offset;
+ UINT32 Width;
+ UINT32 ConfigStringSize;
+ EFI_STATUS Status;
+
+ if(Progress == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(ConfigResp == NULL || BlockSize == NULL )
+ {
+ *Progress = ConfigResp;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if(Block == NULL && *BlockSize != NULL )
+ {
+ *Progress = ConfigResp;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ConfigStringSize = StrSize16(ConfigResp) / 2;
+
+//find start of OFFSET/WIDTH/VALUE block
+ if(!CheckPattern(ConfigResp, &OffsetPattern)) { //for ConfigToBlock function ConfigResp is allowed not to have standard header GUID=...NAME=.
+ do {
+ while((ConfigResp[i] != L'&') && (ConfigResp[i] != 0))
+ i++;
+
+ if(ConfigResp[i] == 0) {
+//TODO: should it be like this???
+//Intel's style - if there is no OFFSET/WIDTH/VALUE blocks - return EFI_SUCCESS
+/*
+ *Progress = ConfigResp;
+ return EFI_NOT_FOUND;
+*/
+ *Progress = &ConfigResp[i];
+ return EFI_SUCCESS;
+ }
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigResp[i], &OffsetPattern))
+ break;
+ } while(1);
+ }
+
+ do
+ {
+ ProgressMarker = i - 1; //set ProgressMarker to '&'
+
+ Status = GetPatternValue(ConfigResp, &i, &OffsetPattern, &Offset);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = &ConfigResp[ProgressMarker];
+ return Status;
+ }
+
+ Status = GetPatternValue(ConfigResp, &i, &WidthPattern, &Width);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = &ConfigResp[ProgressMarker];
+ return Status;
+ }
+
+//provided block is too small to accumulate value
+ if(*BlockSize < (Offset + Width))
+ {
+ *BlockSize = Offset + Width;
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = GetStringValue(ConfigResp, &i, &Block[Offset], Width);
+ if(EFI_ERROR(Status))
+ {
+ *Progress = &ConfigResp[ProgressMarker];
+ return Status;
+ }
+
+ } while(i < ConfigStringSize);
+
+ *BlockSize = Offset + Width - 1; //set index of last updated byte
+ *Progress = &ConfigResp[ConfigStringSize - 1]; //set Progress to null-terminator
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS HiiGetAltConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_STRING AltCfgId,
+ OUT EFI_STRING *AltCfgResp
+)
+{
+ BOOLEAN LastString = FALSE;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StrSize;
+ EFI_STRING ConfigString = ConfigResp;
+
+
+ if(ConfigResp == NULL || AltCfgResp == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(!CheckPattern(ConfigString, &GuidPattern))
+ return EFI_INVALID_PARAMETER;
+
+ do {
+ Status = ExtractConfigString(ConfigString, &Index, AltCfgResp);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if(*AltCfgResp != NULL) {
+ Status = CheckAltCfg(*AltCfgResp, Guid, Name, DevicePath, AltCfgId);
+ if(!EFI_ERROR(Status))
+ return Status;
+
+ ConfigString += Index;
+ pBS->FreePool(*AltCfgResp);
+ } else {
+ LastString = TRUE;
+ StrSize = StrSize16(ConfigString);
+ Status = pBS->AllocatePool(EfiBootServicesData, StrSize, AltCfgResp);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ MemCpy(*AltCfgResp, ConfigString, StrSize);
+ Status = CheckAltCfg(*AltCfgResp, Guid, Name, DevicePath, AltCfgId);
+ if(EFI_ERROR(Status))
+ pBS->FreePool(*AltCfgResp);
+
+ return Status;
+
+ }
+ } while(!LastString);
+
+ return EFI_NOT_FOUND;
+}
+
+// *************************** Service functions (not for public use) **********************
+
+VOID StringToBlock(
+ IN CHAR16 *String,
+ IN UINTN StringSize,
+ OUT UINT8 *Block)
+{
+ UINT8 LowNibble, HiNibble;
+ UINTN i, j;
+
+ j = 0;
+
+ for(i = 0; i < StringSize; i += 2)
+ {
+ if(i == StringSize - 1) { //odd number need to fill with zeroes
+ HiNibble = 0;
+ LowNibble = HexValue((UINT8)String[i]);
+ } else {
+ HiNibble = HexValue((UINT8)String[i]);
+ LowNibble = HexValue((UINT8)String[i + 1]);
+ }
+ Block[j] = (HiNibble << 4) | LowNibble;
+ j++;
+ }
+}
+
+BOOLEAN CheckIfHexDigit(CHAR16 Char)
+{
+ if(Char < 0x30 || Char > 0x66)
+ return FALSE;
+
+ if(Char > 0x39 && Char < 0x41)
+ return FALSE;
+
+ if(Char > 0x46 && Char < 0x61)
+ return FALSE;
+
+ return TRUE;
+}
+
+UINT8 HexValue(CHAR8 Char)
+{
+ if(Char >= 0x30 && Char <= 0x39) //symbols 0...9
+ return Char - 0x30;
+
+ if(Char >= 0x41 && Char <= 0x46) //symbols A...F
+ return Char - 0x37;
+
+ return Char - 0x57; //symbols a...f
+}
+
+
+UINT32 GetValue(CHAR16 *String, UINTN Start, UINTN End)
+{
+ UINT32 Result = 0;
+ UINTN i;
+ UINT8 Nibble;
+ UINT8 NibbleCount = 0;
+
+ for(i = Start; i < End; i++)
+ {
+ Nibble = HexValue((UINT8) String[i]);
+ if(Nibble == 0 && NibbleCount == 0) //skip leading zeros
+ continue;
+
+ if(NibbleCount >= 8) //provided value exceed 4 bytes
+ return 0xffffffff;
+
+ Result <<= 4;
+ Result |= Nibble;
+ NibbleCount++;
+ }
+ return Result;
+}
+
+EFI_STATUS GetStringValue(
+ CHAR16 *String,
+ UINTN *Index,
+ UINT8 *Output,
+ UINT32 Width)
+{
+ EFI_STATUS Status;
+ UINTN Start;
+ UINTN i;
+ UINT8 *Result;
+ UINTN HexSymbolsCount;
+ UINT8 SmallBuffer[20];
+ UINTN ResultBufferSize = 20;
+
+ Start = *Index;
+
+ if(!CheckPattern(&String[Start], &ValuePattern))
+ return EFI_INVALID_PARAMETER;
+
+ Start += ValuePattern.Length / 2;
+ i = Start;
+
+ while((String[i] != L'&') && (String[i] != 0)) {
+ if(!CheckIfHexDigit(String[i]))
+ return EFI_INVALID_PARAMETER;
+ i++;
+ }
+
+ HexSymbolsCount = i - Start;
+
+ if(Width > 20) {
+ Status = pBS->AllocatePool(EfiBootServicesData, Width, &Result);
+ if(EFI_ERROR(Status))
+ return Status;
+ ResultBufferSize = Width;
+ } else {
+ Result = SmallBuffer;
+ }
+
+ MemSet(Result, ResultBufferSize, 0);
+ StringToBlock(&String[Start], HexSymbolsCount, Result);
+
+//now write the result swapped(INTEL's style)
+ if(Width > 1)
+ WriteSwappedBuffer(Output, Result, Width);
+ else
+ *Output = *Result;
+
+ if(Width > 20)
+ pBS->FreePool(Result);
+
+ i++; //skip delimiter
+
+ *Index = i;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS GetPatternValue(
+ CHAR16 *String,
+ UINTN *Index,
+ NAME_PATTERN *Pattern,
+ UINT32 *Value)
+{
+ UINT32 Result;
+ UINTN Start;
+ UINTN i;
+ BOOLEAN EndPattern = FALSE;
+
+ if(Pattern->Tag[0] == L'V' || Pattern->Tag[0] == L'W')
+ EndPattern = TRUE;
+
+ Start = *Index;
+
+ if(!CheckPattern(&String[Start], Pattern))
+ return EFI_INVALID_PARAMETER;
+
+ Start += Pattern->Length / 2;
+ i = Start;
+
+ while((String[i] != L'&') && (String[i] != 0))
+ {
+ if(!CheckIfHexDigit(String[i]))
+ return EFI_INVALID_PARAMETER;
+ i++;
+ }
+
+ if(String[i] == 0 && !EndPattern) //unexpected end of string
+ return EFI_INVALID_PARAMETER;
+
+ Result = GetValue(String, Start, i);
+ i++; //skip delimiter
+
+ *Value = Result;
+ *Index = i;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS FindDeviceHandle(
+ IN CHAR16 *ConfigString,
+ OUT EFI_HANDLE *Handle)
+{
+ UINTN i = 0;
+ UINTN DpLength;
+ UINT8 *DevicePath;
+ EFI_STATUS Status;
+
+//scan config string to find PATH pattern
+ do
+ {
+ while((ConfigString[i] != L'&') && (ConfigString[i] != 0))
+ i++;
+
+ if(ConfigString[i] == 0)
+ return EFI_NOT_FOUND;
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigString[i], &PathPattern))
+ break;
+ } while(1);
+
+//if we get here, we have pointer set on PATH pattern
+ Status = ExtractDevicePath(&ConfigString[i], &DevicePath, &DpLength);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Status = SearchDevicePath(DevicePath, DpLength, Handle);
+ pBS->FreePool(DevicePath);
+
+ return Status;
+}
+
+EFI_STATUS ExtractDevicePath(CHAR16 *ConfigString, UINT8 **DevicePath, UINTN *DpLength)
+{
+ EFI_STATUS Status;
+ UINTN Length = 0;
+ UINTN i = 5; //set pointer to skip first four symbols "PATH="
+
+ while(CheckIfHexDigit(ConfigString[i])) //determine device path length in characters
+ {
+ Length++;
+ i++;
+ }
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ (Length / 2),
+ DevicePath);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ StringToBlock(&ConfigString[5], Length, *DevicePath);
+ *DpLength = Length / 2;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS SearchDevicePath(UINT8 *DevicePath, UINTN DpLength, EFI_HANDLE *Handle)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) PrivateData.PackList.pHead;
+ PACKAGE_LINK *PackageLink;
+
+ while(Record != NULL)
+ {
+ PackageLink = (PACKAGE_LINK *) Record->PackageList.pHead;
+ while(PackageLink != NULL)
+ {
+ if(PackageLink->Package.Type == EFI_HII_PACKAGE_DEVICE_PATH)
+ {
+ if(CheckDevicePath(DevicePath, DpLength, &PackageLink->Package))
+ {
+ *Handle = Record->DriverHandle;
+ return EFI_SUCCESS;
+ }
+ }
+ PackageLink = (PACKAGE_LINK *)PackageLink->Link.pNext;
+ }
+ Record = (PACKAGE_LIST_RECORD *)Record->Link.pNext;
+ }
+ return EFI_NOT_FOUND;
+}
+
+static BOOLEAN CheckDevicePath(
+ IN UINT8 *DevicePath,
+ IN UINTN DpLength,
+ IN EFI_HII_PACKAGE_HEADER *Package)
+{
+ UINTN Length;
+ UINT8 *Dp = (UINT8 *)Package;
+
+ Dp += sizeof(EFI_HII_PACKAGE_HEADER);
+
+ Length = Package->Length - sizeof(EFI_HII_PACKAGE_HEADER);
+ if(Length != DpLength)
+ return FALSE;
+ if(MemCmp(DevicePath, Dp, Length))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+EFI_STATUS ExtractConfigString(CHAR16 *String, UINTN *NextIndex, CHAR16 **NewString)
+{
+ EFI_STATUS Status;
+ UINTN i = 0;
+ CHAR16 *Eos;
+
+//scan config string to find next GUID pattern
+ do
+ {
+ while((String[i] != L'&') && (String[i] != 0))
+ i++;
+
+ if(String[i] == 0)
+ {
+ *NewString = NULL; //config string contains only one string
+ return EFI_SUCCESS;
+ }
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&String[i], &GuidPattern))
+ break;
+ } while(1);
+
+//as we are here i points to next config string
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * i,
+ NewString);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ MemCpy(*NewString, String, (i - 1) * 2);
+ Eos = *NewString;
+ Eos[i - 1] = 0; //put null terminator
+
+ *NextIndex = i;
+ return EFI_SUCCESS;
+}
+
+BOOLEAN CheckPattern(CHAR16 *String, NAME_PATTERN *Pattern)
+{
+ if(MemCmp(String, Pattern->Tag, Pattern->Length))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+EFI_STATUS CollectResults(CHAR16 *Result, UINTN Symbols, RESULT_BLOCK *ResultBlock)
+{
+ EFI_STATUS Status;
+ UINTN StrSize;
+ CHAR16 *Helper;
+
+ StrSize = (Symbols != 0) ? Symbols : StrSize16(Result) / 2; //we need size in CHAR16, not bytes
+
+ if(ResultBlock->MaxResultStringSize < (StrSize + ResultBlock->CurrentSize))
+ {
+ Status = ReallocResultString((StrSize + ResultBlock->CurrentSize) * 2, ResultBlock);
+ if (EFI_ERROR(Status))
+ return Status;
+ }
+
+ Helper = ResultBlock->ResultString;
+ if(ResultBlock->CurrentSize != 0) //we have to change null-terminator to '&' symbol
+ Helper[ResultBlock->CurrentSize - 1] = L'&';
+
+ MemCpy(&Helper[ResultBlock->CurrentSize], Result, StrSize * sizeof(CHAR16));
+ ResultBlock->CurrentSize += StrSize;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS ReallocResultString(UINTN NewSize, RESULT_BLOCK *ResultBlock)
+{
+ CHAR16 *Pointer;
+ EFI_STATUS Status;
+
+ ResultBlock->MaxResultStringSize = NewSize;
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * ResultBlock->MaxResultStringSize,
+ &Pointer);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ MemCpy(Pointer, ResultBlock->ResultString, ResultBlock->CurrentSize * sizeof(CHAR16));
+ pBS->FreePool(ResultBlock->ResultString);
+ ResultBlock->ResultString = Pointer;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS CollectValueResults(UINT8* Value, UINT32 Width, RESULT_BLOCK *ResultBlock)
+{
+ CHAR16 ValueHeader[] = L"VALUE=";
+ UINT32 i;
+ UINT8 Nibble;
+ EFI_STATUS Status;
+ CHAR16 *ValueString;
+ CHAR16 *Ptr;
+ UINTN StringSize;
+
+//first determine necessary string size, including null-terminator in CHAR16 symbols
+ StringSize = Width * 2 + 6 + 1; //each byte requires two symbols plus &VALUE= size plus null terminator
+
+ Status = pBS->AllocatePool(EfiBootServicesData, StringSize * 2, &ValueString);
+ if(EFI_ERROR(Status))
+ return Status;
+
+//copy header
+ MemCpy(ValueString, ValueHeader, 12);
+ Ptr = ValueString + 6;
+
+//write value in reversed order
+ for(i = 0; i < Width; i++)
+ {
+ Nibble = Value[Width - i - 1] >> 4;
+ *Ptr++ = HexDigit[Nibble];
+ Nibble = Value[Width - i - 1] & 0xf;
+ *Ptr++ = HexDigit[Nibble];
+ }
+
+//set null-terminator
+ *Ptr = 0;
+ Status = CollectResults(ValueString, 0, ResultBlock);
+ pBS->FreePool(ValueString);
+ return Status;
+}
+
+VOID WriteSwappedBuffer(
+ OUT UINT8 *Output,
+ IN UINT8 *Input,
+ IN UINTN Size)
+{
+ UINTN i;
+
+ for(i = 0; i < Size; i++)
+ Output[i] = Input[Size - i - 1];
+}
+
+EFI_STATUS CheckAltCfg (
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_STRING AltCfgId
+)
+{
+ EFI_STATUS Status;
+ UINTN i = 0;
+ UINTN j;
+ UINT32 Size;
+ UINT32 CfgId;
+
+//scan config string to find ALTCFG pattern
+ do {
+ while((ConfigString[i] != L'&') && (ConfigString[i] != 0))
+ i++;
+
+ if(ConfigString[i] == 0) //ALTCFG pattern not found
+ break;
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigString[i], &AltCfgPattern))
+ break;
+ } while(1);
+
+ if(ConfigString[i] == 0 && AltCfgId != NULL) //we have current config but needed alt one
+ return EFI_NOT_FOUND;
+
+ if(ConfigString[i] != 0 && AltCfgId == NULL) //we have alt config but needed current one
+ return EFI_NOT_FOUND;
+
+ if(ConfigString[i] != 0 && AltCfgId != NULL) {
+ j = i;
+ Status = GetPatternValue(ConfigString, &j, &AltCfgPattern, &CfgId);
+ if(EFI_ERROR(Status) || *AltCfgId != (UINT16)CfgId)
+ return EFI_NOT_FOUND; //we have alt config, but it's not matched
+
+//if we're here alt config is matched
+//we need to remove "ALTCFG=XXXX" from string as per spec but SCT expects "ALTCFG=" pattern in output string
+
+ //j already points to the next pattern
+ Size = StrSize16(&ConfigString[j]);
+ MemCpy(&ConfigString[i], &ConfigString[j], Size);
+
+ }
+
+ if(Guid != NULL && !HiiCompareGuid(ConfigString, Guid))
+ return EFI_NOT_FOUND; //guid not matched
+
+ if(Name != NULL && !CompareName(ConfigString, Name))
+ return EFI_NOT_FOUND; //name not matched
+
+ if(DevicePath != NULL && !CompareDevicePath(ConfigString, DevicePath))
+ return EFI_NOT_FOUND; //DevicePath not matched
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN HiiCompareGuid(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_GUID *Guid
+)
+{
+ CHAR16 *Pointer = ConfigString;
+ UINTN Length;
+ EFI_GUID AltGuid;
+ EFI_GUID *VarGuid = Guid;
+
+ if(!CheckPattern(ConfigString, &GuidPattern))
+ return FALSE;
+
+ Pointer += 5; //skip "GUID=" pattern
+ Length = 32; //length of guid in symbols
+ StringToBlock(Pointer, Length, (UINT8 *)&AltGuid);
+
+ return !guidcmp(VarGuid, &AltGuid);
+}
+
+BOOLEAN CompareName(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_STRING Name
+)
+{
+ CHAR16 *Pointer = ConfigString;
+ UINTN Length;
+ CHAR16 AltName[80];
+ EFI_STRING VarName = Name;
+ UINTN i = 0;
+
+ do {
+ while((ConfigString[i] != L'&') && (ConfigString[i] != 0))
+ i++;
+
+ if(ConfigString[i] == 0) //NAME pattern not found
+ return FALSE;
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigString[i], &NamePattern))
+ break;
+ } while(1);
+
+ Pointer = &ConfigString[i];
+ Pointer += 5; //skip "NAME=" pattern
+ Length = 80; //length of name buffer
+ StringToChar16(Pointer, &Length, AltName);
+
+ return !StrCmp16(VarName, AltName);
+}
+
+BOOLEAN CompareDevicePath(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+)
+{
+ UINTN Length;
+ EFI_DEVICE_PATH_PROTOCOL *AltDevicePath;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *VarDp = DevicePath;
+ BOOLEAN Result;
+ UINTN i = 0;
+
+ do {
+ while((ConfigString[i] != L'&') && (ConfigString[i] != 0))
+ i++;
+
+ if(ConfigString[i] == 0) //PATH pattern not found
+ return FALSE;
+
+ i++; //shift pointer to next symbol
+ if(CheckPattern(&ConfigString[i], &PathPattern))
+ break;
+ } while(1);
+
+ Status = ExtractDevicePath(&ConfigString[i], (UINT8 **)&AltDevicePath, &Length);
+ if(EFI_ERROR(Status))
+ return FALSE;
+
+ Result = !DPCmp(VarDp, AltDevicePath);
+ pBS->FreePool(AltDevicePath);
+ return Result;
+}
+
+VOID StringToChar16(
+ IN CHAR16 *String,
+ IN OUT UINTN *Size,
+ OUT CHAR16 *Block
+)
+{
+ UINTN i, j;
+
+ i = 0;
+ j = 0;
+
+ while( CheckIfHexDigit(String[i]) && CheckIfHexDigit(String[i + 1]) &&
+ CheckIfHexDigit(String[i + 2]) && CheckIfHexDigit(String[i + 3]) &&
+ j < *Size - 1 )
+ {
+ Block[j] = HexValue((UINT8)String[i]) & 0x000f;
+ Block[j] <<= 4;
+ Block[j] |= HexValue((UINT8)String[i + 1]);
+ Block[j] <<= 4;
+ Block[j] |= HexValue((UINT8)String[i + 2]);
+ Block[j] <<= 4;
+ Block[j] |= HexValue((UINT8)String[i + 3]);
+
+ i += 4;
+ j++;
+ }
+ *Size = j; //number of words processed
+ Block[j] = 0; //put null-terminator
+}
+
+VOID StripValuePattern(
+ IN OUT EFI_STRING String,
+ IN UINTN Size
+)
+{
+ EFI_STATUS Status;
+ EFI_STRING NewString;
+ UINTN i = 0;
+ UINTN j = 0;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, Size, &NewString);
+
+ while(String[i] != 0) {
+ if(String[i] == L'&') {
+ if(CheckPattern(&String[i + 1], &ValuePattern)) {
+ i++;
+ while((String[i] != L'&') && (String[i] != 0))
+ i++;
+ if(String[i] == 0)
+ break;
+ }
+ }
+
+ NewString[j++] = String[i++];
+ }
+
+ NewString[j] = 0;
+ MemCpy(String, NewString, (j + 1) * 2);
+ pBS->FreePool(NewString);
+}
+
+EFI_STATUS InitResultBlock(
+ IN OUT RESULT_BLOCK *ResultBlock
+)
+{
+ EFI_STATUS Status;
+ ResultBlock->MaxResultStringSize = INITIAL_RESULT_STRING_SIZE;
+ ResultBlock->CurrentSize = 0;
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * ResultBlock->MaxResultStringSize,
+ &(ResultBlock->ResultString));
+ return Status;
+}
+
+#pragma warning (default : 4090)
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/UefiHii/HiiDatabase.c b/Core/CORE_DXE/UefiHii/HiiDatabase.c
new file mode 100644
index 0000000..fef10c6
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiDatabase.c
@@ -0,0 +1,1814 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiDatabase.c 14 5/21/12 4:55p Artems $
+//
+// $Revision: 14 $
+//
+// $Date: 5/21/12 4:55p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiDatabase.c $
+//
+// 14 5/21/12 4:55p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio
+// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c
+//
+// 13 1/05/12 5:05p Artems
+// EIP 76735: Font FFS file is not loaded in framework mode, when in
+// nested FV
+//
+// 12 5/13/11 6:14p Artems
+// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and
+// AmiHiiSetString
+// to avoid collusion with EdkII native library functions
+//
+// 11 5/05/11 4:13p Artems
+// Add signal "layout changed" event if current layout is deleted
+//
+// 10 1/05/11 12:41p Artems
+// EIP 50995: Added checking of driver handle before adding packages to
+// HII database
+//
+// 9 6/23/10 5:06p Artems
+// Restored fix killed by previous check-in
+//
+// 8 6/10/10 4:35p Artems
+// EIP 39692 fix - call notification after adding package
+//
+// 7 3/09/10 6:41p Artems
+// EIP 35698: Removed DeleteSimpleFonts call
+//
+// 6 2/03/10 10:28a Artems
+// Fixed bug in HiiExportPacks function
+//
+// 5 1/29/10 5:43p Artems
+// EIP 34553 Updated function ExportPackageLists to support NULL pointer
+// as input
+//
+// 4 1/07/10 12:29p Felixp
+// Code updated to use library instances of the Protocol GUID variables.
+//
+// 3 12/04/09 11:16a Artems
+// Remove keyboard layout functionality added
+//
+// 2 11/09/09 11:51a Felixp
+// New package list function is updated to report error when package list
+// with existing GUID is passed.
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 2/27/09 3:55p Artems
+// Initial check-in
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HiiDatabase.c
+//
+// Description: Hii database protocol functions implementation
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#pragma warning (disable : 4090)
+
+#include <AmiDxeLib.h>
+#include "HiiPrivate.h"
+#include <Protocol/DevicePath.h>
+#include <Protocol/HiiUtilities.h>
+
+extern HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol;
+extern DBE_KEY_FIELD StringDbKeyField;
+
+EFI_GUID NullGuid = NULL_GUID;
+
+SIMPLE_FONT DefaultFont[0x10000];
+
+HII_DATABASE_PRIVATE_DATA PrivateData =
+{
+//Database protocol members
+ {
+ HiiNewPack,
+ HiiRemovePack,
+ HiiUpdatePack,
+ HiiListPacks,
+ HiiExportPacks,
+ HiiRegisterNotify,
+ HiiUnregisterNotify,
+ HiiFindKeyboardLayouts,
+ HiiGetKeyboardLayout,
+ HiiSetKeyboardLayout,
+ HiiGetPackageListHandle
+ },
+//String protocol members
+ {
+ HiiNewString,
+ AmiHiiGetString, //EdkII compatibility library already has function HiiGetString
+ AmiHiiSetString, //EdkII compatibility library already has function HiiSetString
+ HiiGetLanguages,
+ HiiGetSecondLanguages
+ },
+//Font protocol members
+ {
+ HiiStringToImage,
+ HiiStringIdToImage,
+ HiiGetGlyph,
+ HiiGetFontInfo
+ },
+//Config Routing protocol members
+ {
+ HiiExtractConfig,
+ HiiExportConfig,
+ HiiRouteConfig,
+ HiiBlockToConfig,
+ HiiConfigToBlock,
+ HiiGetAltConfig
+ },
+// Linked list of package lists
+ {
+ 0,
+ NULL,
+ NULL
+ },
+//Linked list of notify functions
+ {
+ 0,
+ NULL,
+ NULL
+ },
+//Linked list of keyboard layouts
+ {
+ 0,
+ NULL,
+ NULL
+ },
+//Linked list of global fonts
+ {
+ 0,
+ NULL,
+ NULL
+ },
+//Current KeyLayout
+ NULL
+};
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiDatabaseEntryPoint
+//
+// Description:
+// This function is HII driver entry point
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully, HII protocols installed
+// EFI_ERROR - Some error occured during execution
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiDriverEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE HiiHandle = NULL;
+
+ InitAmiLib(ImageHandle,SystemTable);
+
+ pBS = SystemTable->BootServices;
+
+ //install HII Protocols
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &HiiHandle,
+ &gEfiHiiDatabaseProtocolGuid,
+ &(PrivateData.DatabaseProtocol),
+ &gEfiHiiStringProtocolGuid,
+ &(PrivateData.StringProtocol),
+ &gEfiHiiFontProtocolGuid,
+ &(PrivateData.FontProtocol),
+ &gEfiHiiConfigRoutingProtocolGuid,
+ &(PrivateData.ConfigRoutingProtocol),
+ &gHiiUtilitiesProtocolGuid,
+ &HiiUtilitiesProtocol,
+ NULL);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiBdsEntryPoint
+//
+// Description:
+// This function is HII driver BDS entry point
+//
+// Input:
+// IN EFI_HANDLE ImageHandle - Image handle
+// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully, system font is loaded
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiBdsEntryPoint(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE HiiHandle = NULL;
+
+ InitAmiLib(ImageHandle,SystemTable);
+ Status = LoadSystemFont();
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetPackHandle
+//
+// Description:
+// This function is HII Database protocol function GetPackageHandle implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HII_HANDLE PackageListHandle - PackageList handle
+// OUT EFI_HANDLE *DriverHandle - Pointer, where to store found Driver handle
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - PackageListHandle is invalid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetPackageListHandle (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle)
+{
+ PACKAGE_LIST_RECORD *Record;
+
+ Record = (PACKAGE_LIST_RECORD *) PackageListHandle;
+
+ if (DriverHandle == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ *DriverHandle = Record->DriverHandle;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiRegisterNotify
+//
+// Description:
+// This function is HII Database protocol function RegisterPackageNotify implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN UINT8 PackageType - Package type
+// IN EFI_GUID *PackageGuid - Pointer to Package guid
+// IN EFI_HII_DATABASE_NOTIFY PackageNotifyFn - Function to be called
+// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notify type
+// OUT EFI_HANDLE *NotifyHandle - Pointer, where to store created Notify handle
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - PackageGuid is not NULL and PackageType is not Guid package
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiRegisterNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ OUT EFI_HANDLE *NotifyHandle)
+{
+ NOTIFY_RECORD *NewRecord;
+
+ if (NotifyHandle == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL))
+ return EFI_INVALID_PARAMETER;
+
+ NewRecord = NewNotifyRecord();
+ if (NewRecord == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ if(PackageType == EFI_HII_PACKAGE_TYPE_GUID)
+ NewRecord->PackageGuid = *PackageGuid;
+ else
+ NewRecord->PackageGuid = NullGuid;
+
+ NewRecord->PackageType = PackageType;
+ NewRecord->NotifyType = NotifyType;
+ NewRecord->PackageNotifyFn = PackageNotifyFn;
+
+ DListAdd(&(PrivateData.NotifyList), (DLINK *) NewRecord);
+
+ if(NotifyHandle != NULL)
+ *NotifyHandle = NewRecord;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiUnregisterNotify
+//
+// Description:
+// This function is HII Database protocol function UnregisterPackageNotify implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HANDLE NotificationHandle - Notify handle
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - NotificationHandle is not valid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiUnregisterNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle)
+{
+ NOTIFY_RECORD *Record;
+
+ Record = (NOTIFY_RECORD *) NotificationHandle;
+
+ if (Record->Signature != NOTIFY_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ DListDelete(&(PrivateData.NotifyList), (DLINK *) Record);
+ Record->Signature = 0xffffffff; //invalidate signature to avoid future use of this memory
+ pBS->FreePool(Record);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiRemovePack
+//
+// Description:
+// This function is HII Database protocol function RemovePackageList implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HII_HANDLE Handle - Handle of package list to be removed from database
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - Handle is not valid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiRemovePack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle;
+ PACKAGE_LINK *Package;
+ PACKAGE_LINK *Link;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ Package = (PACKAGE_LINK *) Record->PackageList.pHead;
+
+ while(Package != NULL)
+ {
+ Link = Package;
+ Package = (PACKAGE_LINK *) Package->Link.pNext;
+ RemovePackage(Handle, Link);
+ }
+
+ DListDelete(&(PrivateData.PackList), (DLINK *) Record);
+ Record->Signature = 0xffffffff; //invalidate signature to avoid future collisions
+ pBS->FreePool(Record);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiNewPack
+//
+// Description:
+// This function is HII Database protocol function NewPackageList implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to package list to be added to database
+// IN EFI_HANDLE DriverHandle - Driver handle
+// OUT EFI_HII_HANDLE *Handle - Pointer to EFI_HII_HANDLE where to store created handle
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - Handle or PackageList is NULL
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiNewPack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN CONST EFI_HANDLE DriverHandle,
+ OUT EFI_HII_HANDLE *Handle)
+{
+ PACKAGE_LIST_RECORD *NewRecord;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DpProtocol;
+ UINT32 DpPackageSize;
+ EFI_HII_PACKAGE_HEADER *Buffer;
+
+ if((PackageList == NULL) || (Handle == NULL))
+ return EFI_INVALID_PARAMETER;
+
+ // Check the Package list GUID and DriverHandle to guarantee this GUID is unique in database.
+ if(CheckIfPresent(&(PackageList->PackageListGuid), DriverHandle))
+ return EFI_ALREADY_STARTED; //package list already present
+
+ NewRecord = NewPackageListRecord();
+ if(NewRecord == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ NewRecord->DriverHandle = DriverHandle;
+ NewRecord->Guid = PackageList->PackageListGuid;
+
+ Status = AddPackages((EFI_HII_HANDLE)NewRecord, PackageList, FALSE);
+ if(EFI_ERROR(Status) && (NewRecord->PackageList.Size != 0))
+ {
+ DeleteList(&(NewRecord->PackageList));
+ pBS->FreePool(NewRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+
+ Status = pBS->HandleProtocol(DriverHandle, &gEfiDevicePathProtocolGuid, &DpProtocol);
+ if(!EFI_ERROR(Status))
+ {
+ DpPackageSize = (UINT32)DPLength(DpProtocol);
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ DpPackageSize + sizeof(EFI_HII_PACKAGE_HEADER),
+ &Buffer);
+ if (EFI_ERROR(Status))
+ {
+ DeleteList(&(NewRecord->PackageList));
+ pBS->FreePool(NewRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer->Type = EFI_HII_PACKAGE_DEVICE_PATH;
+ Buffer->Length = DpPackageSize + sizeof(EFI_HII_PACKAGE_HEADER);
+
+ (UINT8 *)Buffer += sizeof(EFI_HII_PACKAGE_HEADER);
+ MemCpy(Buffer, DpProtocol, DpPackageSize);
+ (UINT8 *)Buffer -= sizeof(EFI_HII_PACKAGE_HEADER);
+
+ Status = AddPackage((EFI_HII_HANDLE)NewRecord, Buffer, EFI_HII_DATABASE_NOTIFY_NEW_PACK);
+ if (EFI_ERROR(Status))
+ {
+ DeleteList(&(NewRecord->PackageList));
+ pBS->FreePool(NewRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ pBS->FreePool(Buffer);
+ }
+
+ DListAdd(&(PrivateData.PackList), (DLINK *)NewRecord);
+ *Handle = NewRecord;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiListPacks
+//
+// Description:
+// This function is HII Database protocol function ListPackageLists implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN UINT8 PackageType - Package type
+// IN EFI_GUID *PackageGuid - Pointer to package guid
+// IN OUT UINTN *HandleBufferLength - Pointer to allocated buffer size value
+// OUT EFI_HII_HANDLE *Handle - Pointer to EFI_HII_HANDLE buffer where to store found handles
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - HandleBufferLength is NULL
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+// EFI_NOT_FOUND - No handles found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiListPacks (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN OUT UINTN *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle)
+{
+ UINTN RequiredSize = 0;
+ UINT32 i, Count = 0;
+ EFI_STATUS Status;
+ PACKAGE_LIST_RECORD *List;
+ BOOLEAN InternalBuffer = TRUE;
+ BOOLEAN Found;
+ EFI_HII_HANDLE *MatchedHandles;
+
+ if(HandleBufferLength == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (*HandleBufferLength > 0 && Handle == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL))
+ return EFI_INVALID_PARAMETER;
+
+ List = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead);
+
+ if(PackageType == EFI_HII_PACKAGE_TYPE_ALL)
+ {
+ RequiredSize = sizeof(EFI_HII_HANDLE) * PrivateData.PackList.Size;
+
+ if(*HandleBufferLength < RequiredSize)
+ {
+ *HandleBufferLength = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ for(i = 0; i < PrivateData.PackList.Size; i++)
+ {
+ Handle[i] = List;
+ List = (PACKAGE_LIST_RECORD *)List->Link.pNext;
+ }
+ }
+ else
+ {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_HII_HANDLE) * PrivateData.PackList.Size,
+ (VOID **)&MatchedHandles);
+ if(EFI_ERROR(Status))
+ InternalBuffer = FALSE;
+
+ //parsing package lists to find matches. If internal buffer present found handles will be
+ //stored to avoid repeat parsing
+ for(i = 0; i < PrivateData.PackList.Size; i++)
+ {
+ Found = FindAndRemovePackages(
+ (EFI_HII_HANDLE)List,
+ PackageType,
+ PackageGuid,
+ TRUE);
+ if(Found)
+ {
+ if(InternalBuffer)
+ MatchedHandles[Count] = (EFI_HII_HANDLE)List;
+ Count++;
+ }
+ List = (PACKAGE_LIST_RECORD *) List->Link.pNext;
+ }
+
+ if(Count == 0)
+ return EFI_NOT_FOUND;
+
+ RequiredSize = Count * sizeof(EFI_HII_HANDLE);
+
+ if(*HandleBufferLength < RequiredSize)
+ {
+ *HandleBufferLength = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if(InternalBuffer)
+ {
+ for(i = 0; i < Count; i++)
+ Handle[i] = MatchedHandles[i];
+ pBS->FreePool(MatchedHandles);
+ }
+ else
+ {
+ Count = 0;
+ for(i = 0; i < PrivateData.PackList.Size; i++)
+ {
+ Found = FindAndRemovePackages(
+ (EFI_HII_HANDLE)List,
+ PackageType,
+ PackageGuid,
+ TRUE);
+ if(Found)
+ {
+ Handle[Count] = (EFI_HII_HANDLE)List;
+ Count++;
+ }
+ List = (PACKAGE_LIST_RECORD *) List->Link.pNext;
+ }
+ }
+ }
+
+ *HandleBufferLength = RequiredSize;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiUpdatePack
+//
+// Description:
+// This function is HII Database protocol function UpdatePackageList implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HII_HANDLE Handle - Handle of package list to be updated
+// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to new Package list
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - Handle is invalid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiUpdatePack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle;
+ EFI_STATUS Status;
+
+ if (PackageList == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ Status = AddPackages(Handle, PackageList, TRUE);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiExportPacks
+//
+// Description:
+// This function is HII Database protocol function ExportPackageLists implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_HII_HANDLE Handle - Handle of package list to be exported
+// IN OUT UINTN *BufferSize - Pointer to export buffer size value
+// OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer - Pointer to buffer where to export package lists
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - Handle is invalid
+// EFI_BUFFER_TOO_SMALL - Export buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiExportPacks (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer)
+{
+ EFI_STATUS Status;
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle;
+ UINT32 Size = 0;
+ UINTN PackageListSize;
+ UINTN RequiredSize = 0;
+ UINTN MaxPackageListSize = 0;
+ VOID *IntBuffer;
+
+//Conformance check, as required by SCT
+ if (BufferSize == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (*BufferSize > 0 && Buffer == NULL)
+ return EFI_INVALID_PARAMETER;
+//End of conformace check
+
+ if (Record != NULL) //we need to export only specific package list
+ return ExportPack(Handle, BufferSize, Buffer, TRUE);
+
+//we need to return all package lists
+ Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead);
+
+ while(Record != NULL) {
+ //first determine required buffer size
+ PackageListSize = 0;
+ Status = ExportPack((EFI_HII_HANDLE)Record, &PackageListSize, NULL, TRUE);
+ if(Status == EFI_BUFFER_TOO_SMALL) {
+ RequiredSize += PackageListSize;
+ MaxPackageListSize = (MaxPackageListSize > PackageListSize) ? MaxPackageListSize : PackageListSize;
+ }
+ Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext);
+ }
+
+ if(*BufferSize < RequiredSize) {
+ *BufferSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Status = pBS->AllocatePool(EfiBootServicesData, MaxPackageListSize, &IntBuffer);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead);
+
+ while(Record != NULL) {
+ //export all package lists one by one
+ PackageListSize = MaxPackageListSize;
+ Status = ExportPack((EFI_HII_HANDLE)Record, &PackageListSize, IntBuffer, FALSE);
+ if(!EFI_ERROR(Status)) {
+ MemCpy(Buffer, IntBuffer, PackageListSize);
+ (UINT8 *)Buffer += PackageListSize;
+ }
+ Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext);
+ }
+
+ pBS->FreePool(IntBuffer);
+ *BufferSize = RequiredSize;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiFindKeyboardLayouts
+//
+// Description:
+// This function is HII Database protocol function FindKeyboardLayouts implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN OUT UINT16 *KeyGuidBufferLength - Pointer to allocated buffer size value
+// OUT EFI_GUID *KeyGuidBuffer - Pointer to EFI_GUID buffer where to store found layouts
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - KeyGuidBufferLength or KeyGuidBuffer is NULL
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+// EFI_NOT_FOUND - No layouts found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiFindKeyboardLayouts (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_GUID *KeyGuidBuffer)
+{
+ UINT16 RequiredSize;
+ KEY_LAYOUT_LINK *Link;
+ UINT16 i;
+
+ if(KeyGuidBufferLength == NULL || KeyGuidBuffer == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(PrivateData.KeyLayoutList.Size == 0)
+ return EFI_NOT_FOUND;
+
+ RequiredSize = (UINT16) PrivateData.KeyLayoutList.Size * sizeof(EFI_GUID);
+ if(RequiredSize > *KeyGuidBufferLength)
+ {
+ *KeyGuidBufferLength = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead;
+ for(i = 0; i < PrivateData.KeyLayoutList.Size; i++)
+ {
+ KeyGuidBuffer[i] = Link->Layout.Guid;
+ Link = (KEY_LAYOUT_LINK *) Link->Link.pNext;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiSetKeyboardLayout
+//
+// Description:
+// This function is HII Database protocol function SetKeyboardLayout implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_GUID *KeyGuid - Pointer to EFI_GUID of layout to set
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - KeyGuid is NULL
+// EFI_NOT_FOUND - Given layout not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+//dummy function for signal event procedure
+VOID SetKbLayoutNotifyFn(IN EFI_EVENT Event, IN VOID *Context) {}
+
+EFI_STATUS HiiSetKeyboardLayout (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_GUID *KeyGuid)
+{
+ EFI_HII_KEYBOARD_LAYOUT* Layout;
+ EFI_STATUS Status;
+
+ if(KeyGuid == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ Layout = FindLayoutByGuid(KeyGuid);
+ if(Layout == NULL)
+ return EFI_NOT_FOUND;
+
+ PrivateData.CurrentLayout = Layout;
+ Status = SignalKbLayoutChangedEvent();
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetKeyboardLayout
+//
+// Description:
+// This function is HII Database protocol function GetKeyboardLayout implementation
+//
+// Input:
+// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure
+// IN EFI_GUID *KeyGuid - Pointer to EFI_GUID of layout to set
+// IN OUT UINT16 *KeyGuidBufferLength - Pointer to allocated buffer size value
+// OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout - Pointer to EFI_HII_KEYBOARD_LAYOUT where to store layout
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - KeyboardLayout or KeyGuidBufferLength is NULL
+// EFI_NOT_FOUND - Given layout not found
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetKeyboardLayout (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_GUID *KeyGuid,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout)
+{
+ EFI_HII_KEYBOARD_LAYOUT *Layout;
+
+ if(KeyGuidBufferLength == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(*KeyGuidBufferLength != 0 && KeyboardLayout == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if(KeyGuid == NULL)
+ Layout = PrivateData.CurrentLayout;
+ else
+ Layout = FindLayoutByGuid(KeyGuid);
+
+ if(Layout == NULL)
+ return EFI_NOT_FOUND;
+
+ if(Layout->LayoutLength > *KeyGuidBufferLength)
+ {
+ *KeyGuidBufferLength = Layout->LayoutLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ MemCpy(KeyboardLayout, Layout, Layout->LayoutLength);
+ return EFI_SUCCESS;
+}
+
+//********************** Service functions implementation ***************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddPackages
+//
+// Description:
+// This function adds packages from PackageList to package list with given handle
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list where to add packages
+// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to package list which packages to add
+// IN BOOLEAN Update - Flag which defines packages should be added or updated
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_ERROR - Some error occured during execution
+//
+// Notes:
+// If Update is TRUE control flow goes as described in UpdatePackageList function definition (see UEFI
+// specification v2.1) Otherwise control flow goes as described in NewPackageList function definition
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddPackages(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ BOOLEAN Update)
+{
+ UINT8 Passes;
+ EFI_GUID *Guid;
+ UINT8 PackageType;
+ EFI_STATUS Status;
+ EFI_HII_DATABASE_NOTIFY_TYPE NotifyType;
+ EFI_HII_PACKAGE_LIST_HEADER *SavePointer;
+ UINT32 ControlSize;
+
+ SavePointer = PackageList;
+ ControlSize = PackageList->PackageLength;
+
+ if(Update)
+ {
+ Passes = 2; //set number of passes
+ NotifyType = EFI_HII_DATABASE_NOTIFY_ADD_PACK;
+ }
+ else
+ {
+ Passes = 1; //set number of passes
+ NotifyType = EFI_HII_DATABASE_NOTIFY_NEW_PACK;
+ }
+
+ while(Passes--)
+ {
+ (UINT8 *)PackageList += sizeof(EFI_HII_PACKAGE_LIST_HEADER);
+ ControlSize -= sizeof(EFI_HII_PACKAGE_LIST_HEADER);
+
+ while(((EFI_HII_PACKAGE_HEADER *)PackageList)->Type != EFI_HII_PACKAGE_END && ControlSize > 0)
+ {
+ if(Update)
+ {
+ PackageType = ((EFI_HII_PACKAGE_HEADER *)PackageList)->Type;
+ if(PackageType == EFI_HII_PACKAGE_TYPE_GUID)
+ Guid = (EFI_GUID *) &(((EFI_HII_GUID_PACKAGE_HDR *)PackageList)->Guid);
+ else
+ Guid = NULL;
+ FindAndRemovePackages(Handle, PackageType, Guid, FALSE);
+ }
+ else
+ {
+ Status = AddPackage(Handle, (EFI_HII_PACKAGE_HEADER *)PackageList, NotifyType);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ ControlSize -= ((EFI_HII_PACKAGE_HEADER *)PackageList)->Length;
+ (UINT8 *)PackageList += ((EFI_HII_PACKAGE_HEADER *)PackageList)->Length;
+ }
+ Update = FALSE;
+ PackageList = SavePointer;
+ ControlSize = PackageList->PackageLength;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddPackage
+//
+// Description:
+// This function adds package to package list with given handle
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list where to add package
+// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to add
+// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notify type to be signalled
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_ERROR - Some error occured during execution
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddPackage(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ EFI_HII_DATABASE_NOTIFY_TYPE NotifyType)
+{
+ PACKAGE_LINK *NewLink;
+ UINT32 Size;
+ DLIST *PackageList;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList);
+
+ Size = Package->Length;
+ NewLink = (PACKAGE_LINK *) CreateNewLink(Size);
+ if(NewLink == NULL)
+ return EFI_OUT_OF_RESOURCES;
+ MemCpy(&(NewLink->Package), Package, Size);
+
+ switch(Package->Type)
+ {
+ case EFI_HII_PACKAGE_STRINGS:
+ Status = ParseStringsPackage(
+ (PACKAGE_LIST_RECORD *)Handle,
+ (EFI_HII_STRING_PACKAGE_HDR *)Package);
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ Status = ParseSimpleFontsPackage((EFI_HII_SIMPLE_FONT_PACKAGE_HDR *)Package);
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ Status = ParseFontsPackage((EFI_HII_FONT_PACKAGE_HDR *)Package);
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Status = ParseKeyLayoutPackage((EFI_HII_KEYBOARD_PACKAGE_HDR *)Package);
+ break;
+ default:
+ break;
+ }
+
+ if(EFI_ERROR(Status))
+ return Status;
+
+ DListAdd(PackageList, (DLINK *)NewLink);
+
+ if(PrivateData.NotifyList.Size > 0)
+ InvokeRegisteredNotify(Package, Handle, NotifyType);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindAndRemovePackages
+//
+// Description:
+// This function finds or removes packages from package list with given handle
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list where to find package
+// IN UINT8 PackageType - Package type to find
+// IN EFI_GUID *PackageGuid - Pointer to package guid to find
+// IN BOOLEAN FindOnly - Flag, which determines should package be found or removed
+//
+// Output:
+// TRUE - Package of given type found
+//
+// Notes:
+// If FindOnly is TRUE, function returns TRUE when first package of given type is found. Otherwise
+// function removes all packages of given type from package list and returns FALSE
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN FindAndRemovePackages (
+ IN EFI_HII_HANDLE Handle,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN BOOLEAN FindOnly )
+{
+ DLIST *PackageList;
+ PACKAGE_LINK *Link;
+ PACKAGE_LINK *FoundLink;
+
+
+ PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList);
+ Link = (PACKAGE_LINK *)(PackageList->pHead);
+
+ while(Link != NULL)
+ {
+ if(MatchPackage(PackageType, PackageGuid, &(Link->Package)))
+ {
+ if(FindOnly)
+ return TRUE;
+ else
+ {
+ FoundLink = Link;
+ Link = (PACKAGE_LINK *)Link->Link.pPrev;
+ RemovePackage(Handle, FoundLink);
+ }
+ }
+ if(Link == NULL) //we removed first element from list
+ Link = (PACKAGE_LINK *)(PackageList->pHead);
+ else
+ Link = (PACKAGE_LINK *)Link->Link.pNext;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RemovePackage
+//
+// Description:
+// This function removes package from package list with given handle
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list where to add package
+// IN PACKAGE_LINK *Package - Pointer to package to remove
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID RemovePackage (
+ IN EFI_HII_HANDLE Handle,
+ IN PACKAGE_LINK *Package )
+{
+ DLIST *PackageList;
+
+ PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList);
+
+ if(PrivateData.NotifyList.Size > 0)
+ InvokeRegisteredNotify(&(Package->Package), Handle, EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
+
+ switch(Package->Package.Type)
+ {
+ case EFI_HII_PACKAGE_STRINGS:
+ DeleteStringsFromDatabase(&(((PACKAGE_LIST_RECORD *)Handle)->StringDb));
+ DeleteList(&(((PACKAGE_LIST_RECORD *)Handle)->LanguageList));
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+// DeleteSimpleFonts((EFI_HII_SIMPLE_FONT_PACKAGE_HDR *)&(Package->Package));
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+// DeleteFonts((EFI_HII_FONT_PACKAGE_HDR *)&(Package->Package));
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ DeleteKeyboardLayout((EFI_HII_KEYBOARD_PACKAGE_HDR *)&(Package->Package));
+ break;
+ default:
+ break;
+ }
+ DListDelete(PackageList, (DLINK *)Package);
+ pBS->FreePool(Package);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InvokeRegisteredNotify
+//
+// Description:
+// This function invokes registered notify function if package types match
+//
+// Input:
+// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to match
+// IN EFI_HII_HANDLE Handle - Handle of package list to whom given package belongs
+// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notification type
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InvokeRegisteredNotify (
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType)
+{
+ NOTIFY_RECORD *Record;
+
+ Record = (NOTIFY_RECORD *)(PrivateData.NotifyList.pHead);
+
+ while(Record != NULL)
+ {
+ if(MatchPackage(Record->PackageType, &(Record->PackageGuid), Package) &&
+ (NotifyType & Record->NotifyType))
+ Record->PackageNotifyFn(Record->PackageType,
+ &(Record->PackageGuid),
+ Package,
+ Handle,
+ NotifyType);
+ Record = (NOTIFY_RECORD *)(Record->Link.pNext);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: NewPackageListRecord
+//
+// Description:
+// This function creates new PACKAGE_LIST_RECORD structure and returns pointer to it
+//
+// Input:
+// None
+//
+// Output:
+// PACKAGE_LIST_RECORD* - pointer to newly created structure
+// NULL - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+PACKAGE_LIST_RECORD* NewPackageListRecord( VOID )
+{
+ EFI_STATUS Status;
+ PACKAGE_LIST_RECORD *Record;
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(PACKAGE_LIST_RECORD),
+ &Record);
+ if (EFI_ERROR(Status))
+ return NULL;
+
+ Record->Signature = PACKAGE_LIST_RECORD_SIGNATURE;
+
+ DListInit(&(Record->PackageList));
+ DListInit(&(Record->LanguageList));
+ DListInit(&(Record->StringFontList));
+
+ Record->StringDb.InitialCount = 20;
+ Record->StringDb.RecordCount = 0;
+ Record->StringDb.KeyField = &StringDbKeyField;
+ Record->StringDb.MemoryType = EfiBootServicesData;
+ Record->StringDb.KeyCount = 1;
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(VOID *) * 20,
+ &(Record->StringDb.IndexArray));
+
+ if (EFI_ERROR(Status))
+ {
+ pBS->FreePool(Record);
+ return NULL;
+ }
+
+ return Record;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: NewNotifyRecord
+//
+// Description:
+// This function creates new NOTIFY_RECORD structure and returns pointer to it
+//
+// Input:
+// None
+//
+// Output:
+// NOTIFY_RECORD* - pointer to newly created structure
+// NULL - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+NOTIFY_RECORD* NewNotifyRecord( VOID )
+{
+ EFI_STATUS Status;
+ NOTIFY_RECORD *Record;
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(NOTIFY_RECORD),
+ &Record);
+ if (EFI_ERROR(Status))
+ return NULL;
+
+ Record->Signature = NOTIFY_LIST_RECORD_SIGNATURE;
+
+ return Record;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateNewLink
+//
+// Description:
+// This function creates new link structure for linked list and returns pointer to it
+//
+// Input:
+// IN UINT32 Size - size of the link stucture in bytes
+//
+// Output:
+// VOID* - pointer to newly created structure
+// NULL - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID* CreateNewLink(UINT32 Size)
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ Size + sizeof(DLINK),
+ &Buffer);
+ if (EFI_ERROR(Status))
+ return NULL;
+
+ return Buffer;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteList
+//
+// Description:
+// This function deletes linked list and frees allocated memory
+//
+// Input:
+// IN DLIST *List - Pointer to linked list to be deleted
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DeleteList(DLIST *List)
+{
+ DLINK *Current;
+ DLINK *Next;
+
+ Current = List->pHead;
+
+ while(Current != NULL)
+ {
+ Next = Current->pNext;
+ pBS->FreePool(Current);
+ Current = Next;
+ }
+
+ List->pHead = NULL;
+ List->pTail = NULL;
+ List->Size = 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchPackage
+//
+// Description:
+// This function checks if given package matches given type and guid
+//
+// Input:
+// IN UINT8 PackageType - Package type to match
+// IN EFI_GUID *PackageGuid - Pointer to package guid to match
+// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to check
+//
+// Output:
+// TRUE - package matches given type and guid
+// FALSE - package don't match
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchPackage(
+ IN UINT8 PackageType,
+ IN EFI_GUID *PackageGuid,
+ IN EFI_HII_PACKAGE_HEADER *Package)
+{
+ if(PackageType != Package->Type)
+ return FALSE;
+
+ if(PackageType == EFI_HII_PACKAGE_TYPE_GUID)
+ {
+ if(guidcmp(PackageGuid, &(((EFI_HII_GUID_PACKAGE_HDR *)Package)->Guid)))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckIfPresent
+//
+// Description:
+// This function checks if package list with given guid already in database
+//
+// Input:
+// IN EFI_GUID *Guid - Pointer to package list guid to check
+// IN EFI_HANDLE DriverHandle - Driver handle
+//
+// Output:
+// TRUE - package list already present in database
+// FALSE - package list with given guid not found in database
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN CheckIfPresent(
+ IN EFI_GUID *Guid,
+ IN EFI_HANDLE DriverHandle)
+{
+ PACKAGE_LIST_RECORD *Record;
+
+ Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead);
+
+ while(Record != NULL)
+ {
+ if((!guidcmp(Guid, &(Record->Guid))) && (DriverHandle == Record->DriverHandle))
+ return TRUE;
+ Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext);
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseKeyLayoutPackage
+//
+// Description:
+// This function extracts keyboard layout from package and saves it in private area
+//
+// Input:
+// IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package - Pointer to keyboard layout package
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseKeyLayoutPackage(
+ IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package)
+{
+ KEY_LAYOUT_LINK *Link;
+ UINT16 i;
+ UINT8 *Pointer;
+ UINT32 Size;
+
+ Pointer = (UINT8 *)Package;
+ Pointer += sizeof(EFI_HII_KEYBOARD_PACKAGE_HDR);
+
+ for(i = 0; i < Package->LayoutCount; i++)
+ {
+ Size = ((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->LayoutLength;
+ Link = (KEY_LAYOUT_LINK *) CreateNewLink(Size);
+ if(Link == NULL)
+ return EFI_OUT_OF_RESOURCES;
+ MemCpy(&(Link->Layout), Pointer, Size);
+ DListAdd(&(PrivateData.KeyLayoutList), (DLINK *)Link);
+ Pointer += Size;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteKeyboardLayout
+//
+// Description:
+// This function removes keyboard layouts existing in package from HII database
+//
+// Input:
+// IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package - Pointer to keyboard layout package
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DeleteKeyboardLayout(
+ IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package)
+{
+ KEY_LAYOUT_LINK *Link;
+ UINT16 i;
+ UINT8 *Pointer;
+ UINT32 Size;
+
+ Pointer = (UINT8 *)Package;
+ Pointer += sizeof(EFI_HII_KEYBOARD_PACKAGE_HDR);
+
+ for(i = 0; i < Package->LayoutCount; i++)
+ {
+ Size = ((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->LayoutLength;
+ Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead;
+ while(Link != NULL)
+ {
+ if(!guidcmp(&(((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->Guid), &(Link->Layout.Guid)))
+ break;
+ Link = (KEY_LAYOUT_LINK *)Link->Link.pNext;
+ }
+
+ if(Link != NULL) {
+ if(PrivateData.CurrentLayout == &(Link->Layout)) {
+ PrivateData.CurrentLayout = NULL;
+ SignalKbLayoutChangedEvent();
+ }
+
+ DListDelete(&(PrivateData.KeyLayoutList), (DLINK *)Link);
+ }
+ Pointer += Size;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindLayoutByGuid
+//
+// Description:
+// This function finds keyboard layout in private area by given guid
+//
+// Input:
+// IN EFI_GUID *Guid - Pointer to guid of keyboard layout
+//
+// Output:
+// EFI_HII_KEYBOARD_LAYOUT* - Pointer to found layout
+// NULL - layout not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_HII_KEYBOARD_LAYOUT* FindLayoutByGuid(
+ IN EFI_GUID *Guid)
+{
+ KEY_LAYOUT_LINK *Link;
+
+ Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead;
+ while(Link != NULL)
+ {
+ if(!guidcmp(Guid, &(Link->Layout.Guid)))
+ return &(Link->Layout);
+ Link = (KEY_LAYOUT_LINK *)Link->Link.pNext;
+ }
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseSimpleFontsPackage
+//
+// Description:
+// This function extracts simple fonts from package and saves in private area
+//
+// Input:
+// IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package - Pointer to simple font package
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseSimpleFontsPackage(
+ IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package)
+{
+ EFI_STATUS Status;
+ UINT16 i;
+ UINT16 Symbol;
+ EFI_NARROW_GLYPH *NGlyph;
+ EFI_WIDE_GLYPH *WGlyph;
+
+ NGlyph = Package->NarrowGlyphs;
+ WGlyph = (EFI_WIDE_GLYPH *)NGlyph;
+ (UINT8 *)WGlyph += Package->NumberOfNarrowGlyphs * sizeof(EFI_NARROW_GLYPH);
+
+ for(i = 0; i < Package->NumberOfNarrowGlyphs; i++)
+ {
+ Symbol = NGlyph[i].UnicodeWeight;
+ if(DefaultFont[Symbol].NarrowGlyph == NULL)
+ {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_NARROW_GLYPH),
+ &(DefaultFont[Symbol].NarrowGlyph));
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ DefaultFont[Symbol].NarrowGlyph[0] = NGlyph[i];
+ }
+ }
+
+ for(i = 0; i < Package->NumberOfWideGlyphs; i++)
+ {
+ Symbol = WGlyph[i].UnicodeWeight;
+ if(DefaultFont[Symbol].WideGlyph == NULL)
+ {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_WIDE_GLYPH),
+ &(DefaultFont[Symbol].WideGlyph));
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+ DefaultFont[Symbol].WideGlyph[0] = WGlyph[i];
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteStringsFromDatabase
+//
+// Description:
+// This function removes HII strings from private storage and frees allocated memory
+//
+// Input:
+// IN DBE_DATABASE *Database - Pointer to private strings storage
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DeleteStringsFromDatabase(DBE_DATABASE *Database)
+{
+ VOID *FreeLink;
+ UINTN *Pointer;
+ UINTN i;
+
+ if(Database->RecordCount == 0)
+ return;
+
+ Pointer = (UINTN *)(Database->IndexArray);
+
+ for(i = 0; i < Database->RecordCount; i++)
+ {
+ FreeLink = (VOID *)(UINTN)(*Pointer);
+ pBS->FreePool(FreeLink);
+ Pointer++;
+ }
+
+ MemSet(Database->IndexArray, Database->RecordCount * Database->KeyCount, 0);
+ Database->RecordCount = 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteSimpleFonts
+//
+// Description:
+// This function removes simple fonts from private area and frees allocated memory
+//
+// Input:
+// IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package - Pointer to simple font package which fonts
+// should be removed
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DeleteSimpleFonts(IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package)
+{
+ UINT16 i;
+ UINT16 Symbol;
+ EFI_NARROW_GLYPH *NGlyph;
+ EFI_WIDE_GLYPH *WGlyph;
+
+ NGlyph = Package->NarrowGlyphs;
+ WGlyph = (EFI_WIDE_GLYPH *)NGlyph;
+ (UINT8 *)WGlyph += Package->NumberOfNarrowGlyphs * sizeof(EFI_NARROW_GLYPH);
+
+ for(i = 0; i < Package->NumberOfNarrowGlyphs; i++)
+ {
+ Symbol = NGlyph[i].UnicodeWeight;
+ if(DefaultFont[Symbol].NarrowGlyph != NULL)
+ {
+ pBS->FreePool(DefaultFont[Symbol].NarrowGlyph);
+ DefaultFont[Symbol].NarrowGlyph = NULL;
+ }
+ }
+
+ for(i = 0; i < Package->NumberOfWideGlyphs; i++)
+ {
+ Symbol = WGlyph[i].UnicodeWeight;
+ if(DefaultFont[Symbol].WideGlyph != NULL)
+ {
+ pBS->FreePool(DefaultFont[Symbol].WideGlyph);
+ DefaultFont[Symbol].WideGlyph = NULL;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExportPack
+//
+// Description:
+// This function exports the package list with given handle into provided buffer
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list to be exported
+// IN OUT UINTN *BufferSize - Pointer to export buffer size value
+// OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer - Pointer to buffer where to export package lists
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_BUFFER_TOO_SMALL - Export buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ExportPack (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer,
+ IN BOOLEAN FirstCall )
+{
+ EFI_STATUS Status;
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle;
+ PACKAGE_LINK *Link;
+ UINT32 Size = 0;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) //handle is not valid, return NOT FOUND as SCT requirement
+ return EFI_NOT_FOUND;
+
+ if(FirstCall) {
+ //on the subsequent call we don't need to update string packages again
+ Status = UpdateStringPackages(Handle);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ Link = (PACKAGE_LINK *)Record->PackageList.pHead;
+ while(Link != NULL)
+ {
+ Size += Link->Package.Length;
+ Link = (PACKAGE_LINK *)Link->Link.pNext;
+ }
+
+ Size += sizeof(EFI_HII_PACKAGE_LIST_HEADER);
+
+ if(Size > *BufferSize)
+ {
+ *BufferSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = Size;
+ Buffer->PackageListGuid = Record->Guid;
+ Buffer->PackageLength = Size;
+ (UINT8 *)Buffer += sizeof(EFI_HII_PACKAGE_LIST_HEADER);
+
+ Link = (PACKAGE_LINK *)Record->PackageList.pHead;
+ while(Link != NULL)
+ {
+ Size = Link->Package.Length;
+ MemCpy(Buffer, &(Link->Package), Size);
+ (UINT8 *)Buffer += Size;
+ Link = (PACKAGE_LINK *)Link->Link.pNext;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS SignalKbLayoutChangedEvent(
+ VOID)
+{
+ EFI_EVENT Event;
+ EFI_GUID SetKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;
+ EFI_STATUS Status;
+
+ Status = pBS->CreateEventEx(
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ SetKbLayoutNotifyFn,
+ NULL,
+ &SetKeyboardLayoutEventGuid,
+ &Event);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ pBS->SignalEvent(Event);
+ pBS->CloseEvent(Event);
+
+ return EFI_SUCCESS;
+}
+
+#pragma warning (default : 4090)
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2007, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/UefiHii/HiiFont.c b/Core/CORE_DXE/UefiHii/HiiFont.c
new file mode 100644
index 0000000..739520c
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiFont.c
@@ -0,0 +1,1035 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFont.c 3 3/18/13 8:31a Thomaschen $
+//
+// $Revision: 3 $
+//
+// $Date: 3/18/13 8:31a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFont.c $
+//
+// 3 3/18/13 8:31a Thomaschen
+// Update to rev.16.
+//
+// 16 3/11/13 4:40p Artems
+// [TAG] EIP110240
+// [Category] Improvement
+// [Description] Raise the TPL of StringToImage function to TPL_NOTIFY
+// to protect internal global data
+// [Files] HiiFont.c
+//
+// 15 1/24/13 11:12a Artems
+// [TAG] EIP112874
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System displays output in wrong colors
+// [RootCause] If system failed to find font, described in passed font
+// info structure it also ignored passed colors
+// [Solution] Preserve passed colors even if font not found
+// [Files] HiiFont.c
+//
+// 14 12/26/12 1:40p Artems
+// [TAG] EIP109050
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Memory leal in call to GetGlyph function
+// [RootCause] GetGlyph function called GetFontInfo function to obtain
+// proper font and didn't release font info buffer
+// [Solution] Fixed GetGlyph function
+// [Files] HiiFont.c
+//
+// 13 11/14/12 5:58p Artems
+// [TAG] EIP105534
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] system hangs during SCT execution
+// [RootCause] Incorrect handling of FORM_FEED escape character in
+// StringToImage function
+// [Solution] Graphics console - added flag to ignore line breaks
+// HiiFont - fixed multiline drawing logic
+// [Files] Gc.c HiiFont.c HiiFontEx.c
+//
+// 12 9/25/12 5:46p Artems
+// [TAG] EIP101224
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] System freezes
+// [RootCause] Memory leak in StringToImage function. When called many
+// times may lead to memory exhaustion
+// [Solution] Fixed memory leak
+// [Files] HiiFont.c
+//
+// 11 6/27/12 4:16p Artems
+// [TAG] EIP93526
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Aptio 4 - Proportional Font EFI_HII_OUT_FLAG_WRAP issue
+// [RootCause] Passed drawing flags contained both Clip and Wrap. Clip
+// gets analyzed first so clipping control flow was enacted
+// [Solution] Changed order of drawind flags analysis
+// [Files] HiiFont.c
+//
+// 10 6/15/12 12:19p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] project doesn't build in 32-bit mode
+// [RootCause] Signed/Unsigned mismatch reported by 32-bit compiler
+// [Solution] typecasted one parameter to signed
+// [Files] HiiFont.c HiiFontEx.c
+//
+// 9 6/14/12 6:31p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio fixed SCT reported
+// bugs
+// [Files] HiiFont.c HiiFontEx.c
+//
+// 8 5/24/12 2:58p Artems
+// [TAG] EIP83593
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] No symbols are shown in GSE
+// [RootCause] Incorrect BaseLineOffset was set. Transparent drawing was
+// not supported
+// [Solution] Set correct BaseLineOffset. Add check for transparency
+// flag
+// [Files] HiiFont.c
+//
+// 7 5/22/12 4:14p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio. Removed unused
+// functions
+// [Files] HiiFont.c
+//
+// 6 5/21/12 6:28p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio
+// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c
+//
+// 5 10/25/11 7:04p Artems
+// EIP 70530: Fixed bugs reported by SCT 2.3.1
+//
+// 4 5/17/11 4:05p Artems
+// EIP 59787: Bug fix - when drawing multi-line string X position wasn't
+// updated to start of new line
+//
+// 3 5/13/11 6:14p Artems
+// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and
+// AmiHiiSetString
+// to avoid collusion with EdkII native library functions
+//
+// 2 12/03/09 6:04p Artems
+// SCT bug fix
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 2/27/09 3:55p Artems
+// Initial check-in
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HiiFont.c
+//
+// Description: Hii font protocol functions implementation
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiDxeLib.h>
+#include "HiiPrivate.h"
+
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black = { 0, 0, 0, 0 };
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL White = { 0xff, 0xff, 0xff, 0 };
+
+extern HII_DATABASE_PRIVATE_DATA PrivateData;
+extern SIMPLE_FONT DefaultFont[0x10000];
+
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefForegroundColor;
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefBackgroundColor;
+
+static UINTN TextStartX;
+static UINTN TextStartY;
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ImageBlt; //buffer, where to draw
+
+EFI_FONT_HANDLE CurFont; //font to use
+CHAR16 *DrawString; //string to draw
+EFI_HII_OUT_FLAGS DrawFlags = 0;
+DLIST DrawLines = {0, NULL, NULL};
+UINTN ImageWidth;
+UINTN ImageHeight;
+
+#pragma optimize( "", off )
+EFI_STATUS CheckParameters(VOID *One, VOID *Two)
+{
+ return (One == NULL || Two == NULL) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
+}
+#pragma optimize( "", on )
+
+//**************************** Protocol functions implementation ***************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiStringToImage
+//
+// Description:
+// This function is HII Font protocol function StringToImage implementation
+//
+// Input:
+// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure
+// IN EFI_HII_OUT_FLAGS Flags - Drawing flags
+// IN EFI_STRING String - String to draw
+// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info
+// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer
+// IN UINTN BltX - start horizontal position
+// IN UINTN BltY - start vertical position
+// OUT EFI_HII_ROW_INFO **RowInfoArray - Pointer to returned row info array
+// OUT UINTN *RowInfoArraySize - Pointer to store row info array size
+// OUT UINTN *ColumnInfoArray - Pointer to returned column info array
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiStringToImage(
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL)
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewBlt = NULL;
+ EFI_IMAGE_OUTPUT *Io = *Blt;
+ EFI_HII_ROW_INFO *RowInfo;
+ UINTN i, j;
+ UINTN Offset;
+ DRAW_LINE *Link;
+ UINTN Delta = 0;
+ EFI_FONT_DISPLAY_INFO *Info = NULL;
+ EFI_TPL OldTpl;
+
+ Status = CheckParameters(String, Blt);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if (Io == NULL) {
+ //
+ // These two flag cannot be used if Blt is NULL upon entry.
+ //
+ if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT)
+ return EFI_INVALID_PARAMETER;
+
+ if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP)
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X)
+ return EFI_INVALID_PARAMETER;
+
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)
+ return EFI_INVALID_PARAMETER;
+ //
+ // This flag cannot be used with EFI_HII_OUT_FLAG_CLIP_CLEAN_X.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X))
+ return EFI_INVALID_PARAMETER;
+
+//check string size - if two bytes - means empty string - do nothing
+ i = StrSize16(String);
+
+ if(i <= 2)
+ return EFI_SUCCESS;
+
+ OldTpl = pBS->RaiseTPL(TPL_NOTIFY);
+
+//first initialize global variables and split string
+/* SCT assumes that EFI_HII_OUT_FLAG_CLIP flag is implied when direct to screen output is performed
+ unless EFI_HII_OUT_FLAG_WRAP flag is set */
+ DrawFlags = Flags;
+ if(Flags & EFI_HII_IGNORE_LINE_BREAK ||
+ (Flags & EFI_HII_DIRECT_TO_SCREEN && !(Flags & EFI_HII_OUT_FLAG_WRAP)))
+ DrawFlags |= EFI_HII_OUT_FLAG_CLIP;
+
+ DrawString = String;
+ TextStartX = BltX;
+ TextStartY = BltY;
+ CurFont = NULL;
+ Status = HiiGetFontInfo(This, &CurFont, StringInfo, &Info, NULL);
+ if(EFI_ERROR(Status)) {
+ CurFont = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE;
+ Info = NULL;
+ }
+
+ if (Info != NULL) {
+ DefForegroundColor = Info->ForegroundColor;
+ DefBackgroundColor = Info->BackgroundColor;
+ pBS->FreePool(Info); //it's no longer needed
+ } else {
+ if(StringInfo != NULL) { //even though correct font not found we preserve passed colors if any
+ DefForegroundColor = StringInfo->ForegroundColor;
+ DefBackgroundColor = StringInfo->BackgroundColor;
+ } else {
+ DefForegroundColor = White;
+ DefBackgroundColor = Black;
+ }
+ }
+
+ Status = SplitByLineBreaks(DrawString);
+ if(EFI_ERROR(Status)) {
+ pBS->RestoreTPL(OldTpl);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if(Io != NULL) {
+ if(!(Flags & EFI_HII_DIRECT_TO_SCREEN)) {
+ //if we're drawing on given bitmap - take its size
+ ImageWidth = Io->Width;
+ ImageHeight = Io->Height;
+ NewBlt = Io->Image.Bitmap;
+ } else {
+ //make sure we fit in screen resolution
+ ImageWidth = Io->Width - BltX;
+ ImageHeight = Io->Height - BltY;
+
+ //clear TextStartX and TextStartY
+ TextStartX = 0;
+ TextStartY = 0;
+ }
+ /* since bitmap size is fixed we have to adjust text to fit in */
+ Status = AdjustLineSize();
+ if(EFI_ERROR(Status)) {
+ pBS->RestoreTPL(OldTpl);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //calculate size of the image
+ GetDrawImageSize(&ImageWidth, &ImageHeight);
+ //add to required image size initial offset
+ ImageWidth += BltX;
+ ImageHeight += BltY;
+ }
+
+ if(NewBlt == NULL) {
+ /* buffer not initialized because of DirectToScreen flag or Io == NULL */
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ImageWidth * ImageHeight,
+ &NewBlt);
+ if (EFI_ERROR(Status)) {
+ pBS->RestoreTPL(OldTpl);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ MemSet(NewBlt, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ImageWidth * ImageHeight, 0);
+ }
+
+ ImageBlt = NewBlt;
+ Draw();
+
+ if(Flags & EFI_HII_DIRECT_TO_SCREEN)
+ {
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Screen;
+
+ if(ImageWidth < Io->Width) //we need to draw a subrectange, calculate Delta
+ Delta = ImageWidth * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+
+ Screen = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)(Io->Image.Screen);
+ Status = Screen->Blt(Screen, ImageBlt, EfiBltBufferToVideo,
+ 0, 0, BltX, BltY, ImageWidth, ImageHeight, Delta);
+ pBS->FreePool(ImageBlt);
+ }
+
+//Prepare return info if needed
+ Link = (DRAW_LINE *)(DrawLines.pHead);
+ if(RowInfoArray != NULL && Link->LineHeight != 0) {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_HII_ROW_INFO) * DrawLines.Size,
+ &RowInfo);
+ if (EFI_ERROR(Status)) {
+ pBS->RestoreTPL(OldTpl);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ i = 0;
+ while(Link != NULL) {
+ RowInfo[i].BaselineOffset = 0; //I'm still confused with this one, but SCT is happy
+ RowInfo[i].EndIndex = Link->EndIndex;
+ RowInfo[i].LineHeight = Link->LineHeight;
+ RowInfo[i].LineWidth = Link->LineWidth;
+ RowInfo[i].StartIndex = Link->StartIndex;
+
+ i++;
+ Link = (DRAW_LINE *)Link->Link.pNext;
+ }
+ *RowInfoArray = RowInfo;
+ if(RowInfoArraySize != NULL)
+ *RowInfoArraySize = DrawLines.Size;
+ } else {
+ if(RowInfoArray != NULL)
+ *RowInfoArray = NULL;
+ if(RowInfoArraySize != NULL)
+ *RowInfoArraySize = 0;
+ }
+
+ if(Io == NULL) {
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_IMAGE_OUTPUT), &Io);
+ if (EFI_ERROR(Status)) {
+ pBS->RestoreTPL(OldTpl);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Io->Height = (UINT16)ImageHeight;
+ Io->Width = (UINT16)ImageWidth;
+ Io->Image.Bitmap = NewBlt;
+
+ *Blt = Io;
+ }
+
+ if(ColumnInfoArray != NULL) {
+ i = 0;
+ Link = (DRAW_LINE *)(DrawLines.pHead);
+ while(Link != NULL)
+ {
+ Offset = TextStartX;
+ for(j = Link->StartIndex; j <= Link->EndIndex; j++)
+ {
+ BOOLEAN Dummy;
+ EFI_HII_GLYPH_INFO Cell;
+ ColumnInfoArray[i] = Offset;
+ IntGetGlyph(CurFont, DrawString[j], &Cell, NULL, &Dummy);
+ i++;
+ Offset += Cell.AdvanceX;
+ }
+ Link = (DRAW_LINE *)Link->Link.pNext;
+ }
+ }
+
+//clean up
+ DeleteList(&DrawLines);
+ pBS->RestoreTPL(OldTpl);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiStringIdToImage
+//
+// Description:
+// This function is HII Font protocol function StringIdToImage implementation
+//
+// Input:
+// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure
+// IN EFI_HII_OUT_FLAGS Flags - Drawing flags
+// IN EFI_HII_HANDLE PackageList - Handle of package list where string resides
+// IN EFI_STRING_ID StringId - String Id
+// IN CHAR8 *Language - Language Id
+// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info
+// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer
+// IN UINTN BltX - start horizontal position
+// IN UINTN BltY - start vertical position
+// OUT EFI_HII_ROW_INFO **RowInfoArray - Pointer to returned row info array
+// OUT UINTN *RowInfoArraySize - Pointer to store row info array size
+// OUT UINTN *ColumnInfoArray - Pointer to returned column info array
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiStringIdToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8* Language,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL)
+{
+ CHAR16 String[0x100];
+ UINTN StringSize = 0x100;
+ EFI_STATUS Status;
+
+ Status = AmiHiiGetString(NULL, Language, PackageList, StringId, String, &StringSize, NULL);
+
+ if(EFI_ERROR(Status))
+ {
+ if(Status == EFI_BUFFER_TOO_SMALL)
+ {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * StringSize,
+ (VOID **)&String);
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+ }
+ else
+ return Status;
+
+ Status = AmiHiiGetString(NULL, Language, PackageList, StringId, String, &StringSize, NULL);
+ }
+
+ Status = HiiStringToImage(This, Flags, String, StringInfo, Blt, BltX, BltY,
+ RowInfoArray, RowInfoArraySize, ColumnInfoArray);
+
+ if(StringSize > 0x100)
+ pBS->FreePool(String);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetGlyph
+//
+// Description:
+// This function is HII Font protocol function GetGlyph implementation
+//
+// Input:
+// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure
+// IN CHAR16 Char - Symbol, which glyph to return
+// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info
+// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer
+// OUT UINTN *Baseline - Pointer to baseline placeholder
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetGlyph (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN CHAR16 Char,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_IMAGE_OUTPUT **Blt,
+ OUT UINTN *Baseline OPTIONAL
+)
+{
+ EFI_STATUS Status;
+ BOOLEAN GlyphNotFound = FALSE;
+ EFI_IMAGE_OUTPUT *Output;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap;
+ EFI_FONT_HANDLE Font;
+ EFI_FONT_DISPLAY_INFO *Info = NULL;
+ EFI_HII_GLYPH_INFO Cell;
+ UINT8 *GlyphBlock;
+ BOOLEAN Free;
+
+ if(Blt == NULL || *Blt != NULL)
+ return EFI_INVALID_PARAMETER;
+
+ Font = NULL;
+ Status = HiiGetFontInfo(This, &Font, StringInfo, &Info, NULL);
+ if(EFI_ERROR(Status)) {
+ Font = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE;
+ Info = NULL;
+ }
+
+//prepare global data values, used in drawing
+ if(Info != NULL) {
+ DefForegroundColor = Info->ForegroundColor;
+ DefBackgroundColor = Info->BackgroundColor;
+ pBS->FreePool(Info);
+ } else {
+ if(StringInfo != NULL) {
+ DefForegroundColor = StringInfo->ForegroundColor;
+ DefBackgroundColor = StringInfo->BackgroundColor;
+ } else {
+ DefForegroundColor = White;
+ DefBackgroundColor = Black;
+ }
+ }
+
+ Status = IntGetGlyph(Font, Char, &Cell, &GlyphBlock, &Free);
+ if(EFI_ERROR(Status))
+ return Status;
+ if(Status == EFI_WARN_UNKNOWN_GLYPH)
+ GlyphNotFound = TRUE;
+
+//allocate memory for output bitmap
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Cell.Width * Cell.Height,
+ &Bitmap);
+ if (EFI_ERROR(Status))
+ return EFI_OUT_OF_RESOURCES;
+
+//allocate memory for output data
+ Status = pBS->AllocatePool(EfiBootServicesData,
+ sizeof(EFI_IMAGE_OUTPUT),
+ &Output);
+ if (EFI_ERROR(Status)) {
+ pBS->FreePool(Bitmap);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Output->Width = Cell.Width;
+ Output->Height = Cell.Height;
+ Output->Image.Bitmap = Bitmap;
+
+ ImageWidth = Output->Width;
+ ImageHeight = Output->Height;
+
+//now we are ready to draw the glyph
+ DrawGlyph(0, 0, ImageWidth, ImageHeight, GlyphBlock, FALSE, Bitmap, Cell.Width);
+ if(Free)
+ pBS->FreePool(GlyphBlock);
+
+ *Blt = Output;
+
+ if(Baseline != NULL) {
+ if((UINTN)Font == DEFAULT_FONT_HANDLE)
+ *Baseline = (Cell.Width == EFI_GLYPH_WIDTH) ? 4 : 5; //fixed value for system font
+ else
+ *Baseline = (Cell.OffsetY < 0) ? -(Cell.OffsetY) : 0;
+ }
+
+ return (GlyphNotFound) ? EFI_WARN_UNKNOWN_GLYPH : EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetFontInfo
+//
+// Description:
+// This function is HII Font protocol function GetFontInfo implementation
+//
+// Input:
+// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure
+// IN OUT EFI_FONT_HANDLE *FontHandle - Pointer to font handle
+// IN EFI_FONT_DISPLAY_INFO *StringInfoIn - Pointer to display info
+// OUT EFI_FONT_DISPLAY_INFO *StringInfoOut - Pointer to output display info
+// IN EFI_STRING *String - Pointer to string to test
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetFontInfo (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
+ IN CONST EFI_STRING String OPTIONAL
+)
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fg;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Bg;
+ EFI_HII_FONT_STYLE FStyle;
+ UINT16 FSize;
+ CHAR16 *FName;
+ FONT_MATCH_MASK Fm;
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO FdInfo;
+
+ if (StringInfoIn == NULL) {
+ /* use default values */
+ FdInfo.FontInfoMask = EFI_FONT_INFO_SYS_FONT |
+ EFI_FONT_INFO_SYS_SIZE |
+ EFI_FONT_INFO_SYS_STYLE |
+ EFI_FONT_INFO_SYS_FORE_COLOR |
+ EFI_FONT_INFO_SYS_BACK_COLOR;
+ } else {
+ FdInfo = *StringInfoIn;
+ FName = (CHAR16 *)StringInfoIn->FontInfo.FontName;
+ }
+ //
+ // Check the font information mask to make sure it is valid.
+ //
+ if (((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==
+ (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||
+ ((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
+ ((FdInfo.FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((FdInfo.FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)))
+ return EFI_INVALID_PARAMETER;
+
+/* first deal with color attributes */
+ Fg = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) ? White : StringInfoIn->ForegroundColor;
+ Bg = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) ? Black : StringInfoIn->BackgroundColor;
+
+/* retrieve supplied information */
+ FStyle = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_STYLE) ? EFI_HII_FONT_STYLE_NORMAL : StringInfoIn->FontInfo.FontStyle;
+ FSize = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_SIZE) ? EFI_GLYPH_HEIGHT : StringInfoIn->FontInfo.FontSize;
+
+ if(FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_FONT) {
+ if(*FontHandle == (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE) {
+ /* we already returned system font, so no other matches for system font present */
+ *FontHandle = NULL;
+ return EFI_NOT_FOUND;
+ }
+ /* return system font information and handle */
+ *FontHandle = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE;
+ if(StringInfoOut != NULL) {
+ Status = FillFontInfo(*FontHandle, StringInfoOut);
+ if(EFI_ERROR(Status))
+ return Status;
+ (*StringInfoOut)->ForegroundColor = Fg;
+ (*StringInfoOut)->BackgroundColor = Bg;
+ (*StringInfoOut)->FontInfoMask = FdInfo.FontInfoMask;
+ }
+ return EFI_SUCCESS;
+ }
+
+ Fm.MatchName = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_FONT) ? MATCH_INGNORE : MATCH_STRICT;
+ Fm.MatchStyle = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_STYLE) ? MATCH_INGNORE :
+ (FdInfo.FontInfoMask & EFI_FONT_INFO_RESTYLE) ? MATCH_LOOSE : MATCH_STRICT;
+ Fm.MatchSize = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_SIZE) ? MATCH_INGNORE :
+ (FdInfo.FontInfoMask & EFI_FONT_INFO_RESIZE) ? MATCH_LOOSE : MATCH_STRICT;
+
+ Status = FindFont(FontHandle, FName, FStyle, FSize, Fm, String);
+ if(!EFI_ERROR(Status) && (StringInfoOut != NULL)) {
+ /* font found, prepare font info */
+ Status = FillFontInfo(*FontHandle, StringInfoOut);
+ if(EFI_ERROR(Status))
+ return Status;
+ (*StringInfoOut)->ForegroundColor = Fg;
+ (*StringInfoOut)->BackgroundColor = Bg;
+ (*StringInfoOut)->FontInfoMask = FdInfo.FontInfoMask;
+ }
+
+ return Status;
+}
+
+
+
+// *************************** Service functions (not for public use) **********************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsLineBreak
+//
+// Description:
+// This function checks if given symbol is a line break
+//
+// Input:
+// IN CHAR16 Char - Symbol to test
+//
+// Output:
+// TRUE - Symbol is a linebreak
+// FALSE - Symbol is not a linebreak
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsLineBreak(CHAR16 Char)
+{
+ switch(Char)
+ {
+ case 0x000c:
+ case 0x000d:
+ case 0x2028:
+ case 0x2029:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsLineBreakOpp
+//
+// Description:
+// This function checks if given symbol is a line break opportunity
+//
+// Input:
+// IN CHAR16 Char - Symbol to test
+//
+// Output:
+// TRUE - Symbol is a linebreak opportunity
+// FALSE - Symbol is not a linebreak opportunity
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsLineBreakOpp(CHAR16 Char)
+{
+ if(IsLineBreak(Char))
+ return TRUE;
+
+ if(Char >= 0x2000 && Char <= 0x200a)
+ return TRUE;
+
+ switch (Char)
+ {
+ case 0x0020:
+ case 0x1680:
+ case 0x2013:
+ case 0x205f:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SplitByLineBreaks
+//
+// Description:
+// This function splits given string into lines on linebreaks
+//
+// Input:
+// IN EFI_STRING String - string to split
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS SplitByLineBreaks(EFI_STRING String)
+{
+ UINT32 Size;
+ UINT32 i;
+ DRAW_LINE *Link;
+
+ Size = StrSize16(String) / 2; //size in symbols
+ Link = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5);
+ if(Link == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ Link->StartIndex = 0;
+ if(DrawFlags & EFI_HII_IGNORE_LINE_BREAK)
+ {
+ Link->EndIndex = Size - 2; //ignore null terminator
+ UpdateLineSize(Link);
+ DListAdd(&DrawLines, (DLINK *)Link);
+ return EFI_SUCCESS;
+ }
+
+ for(i = 0; i < (Size - 1); i++)
+ {
+ if(IsLineBreak(String[i]))
+ {
+ Link->EndIndex = i;
+ UpdateLineSize(Link);
+ DListAdd(&DrawLines, (DLINK *)Link);
+ Link = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5);
+ if(Link == NULL)
+ return EFI_OUT_OF_RESOURCES;
+ i++;
+ Link->StartIndex = i;
+ }
+ }
+ Link->EndIndex = Size - 2;
+ UpdateLineSize(Link);
+ DListAdd(&DrawLines, (DLINK *)Link);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AdjustLineSize
+//
+// Description:
+// This function analyzes lines of the string and makes them fit into drawing area size
+//
+// Input:
+// None
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AdjustLineSize(VOID)
+{
+ DRAW_LINE *Link;
+ UINTN TextHeight = ImageHeight - TextStartY;
+ UINTN TextWidth = ImageWidth - TextStartX;
+ EFI_STATUS Status;
+
+ Link = (DRAW_LINE *)(DrawLines.pHead);
+ while(Link != NULL) {
+//first detect line height
+ if(TextHeight >= Link->LineHeight) {
+ /* line is visible entirely */
+ TextHeight -= Link->LineHeight;
+ } else {
+ /* line is visible partially */
+ if(DrawFlags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y || TextHeight == 0) {
+ Link->LineHeight = 0; //mark line as invisible and stop adjusting - all subsequent lines will be invisible
+ return EFI_SUCCESS;
+ } else {
+ Link->LineHeight = TextHeight;
+ TextHeight = 0;
+ }
+ }
+
+//second detect line width
+ if(Link->LineWidth > TextWidth) {
+ /* line needs clipping of wrapping */
+ if(DrawFlags & EFI_HII_OUT_FLAG_WRAP) {
+ /* wrapping mode */
+ Status = WrapLine(Link, TextWidth);
+ if(EFI_ERROR(Status))
+ return Status;
+ } else {
+ /* clipping mode */
+ ClipLine(Link, TextWidth, ((DrawFlags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) ? TRUE : FALSE));
+ }
+ }
+//proceed to next line
+ Link = (DRAW_LINE *)Link->Link.pNext;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: Draw
+//
+// Description:
+// This function draws lines of the string
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID Draw(VOID)
+{
+ DRAW_LINE *Link;
+ UINTN i;
+ CHAR16 CurrentSymbol;
+ BOOLEAN Transparent = FALSE;
+ EFI_STATUS Status;
+
+ EFI_HII_GLYPH_INFO Cell;
+ UINT8 *GlyphBlock;
+ BOOLEAN Free;
+
+ POINT_COORD gl_st;
+ POINT_COORD gl_size;
+ RECT_COORD glyph;
+
+ POINT_COORD ln_st;
+ POINT_COORD ln_size;
+ RECT_COORD line;
+
+ POINT_COORD origin;
+
+ glyph.st = &gl_st;
+ glyph.size = &gl_size;
+
+ line.st = &ln_st;
+ line.size = &ln_size;
+ ln_st.y = TextStartY; //line start coordinate Y
+
+ if(DrawFlags & EFI_HII_OUT_FLAG_TRANSPARENT)
+ Transparent = TRUE;
+
+ Link = (DRAW_LINE *)(DrawLines.pHead);
+ while(Link != NULL && Link->LineHeight != 0) //loop by strings
+ {
+ /* init line rectangle */
+ ln_st.x = TextStartX; //line start coordinate X
+ ln_size.x = Link->LineWidth; //line width
+ ln_size.y = Link->LineHeight; //line height
+
+ origin.x = ln_st.x;
+ origin.y = ln_st.y + Link->BaseLineOffset;
+
+ for(i = Link->StartIndex; i <= Link->EndIndex; i++)
+ {
+ CurrentSymbol = DrawString[i];
+ if((DrawFlags & EFI_HII_IGNORE_LINE_BREAK) && IsLineBreak(CurrentSymbol))
+ continue;
+
+ Status = IntGetGlyph(CurFont, CurrentSymbol, &Cell, &GlyphBlock, &Free);
+ if(EFI_ERROR(Status))
+ return;
+
+ if(Status == EFI_WARN_UNKNOWN_GLYPH && (DrawFlags & EFI_HII_IGNORE_IF_NO_GLYPH)) {
+ if(Free)
+ pBS->FreePool(GlyphBlock);
+ continue;
+ }
+ /* init glyph rectangle */
+ gl_st.x = origin.x + Cell.OffsetX;
+ gl_st.y = origin.y - (Cell.Height + Cell.OffsetY);
+ gl_size.x = Cell.Width;
+ gl_size.y = Cell.Height;
+
+ if(CheckVisible(&glyph, &line)) {
+ /* symbol is visible at least partially */
+ /* at this point symbol rect coordinates were adjusted to fit visible area */
+ DrawGlyph(gl_st.x, gl_st.y, gl_size.x, gl_size.y, GlyphBlock, Transparent, ImageBlt, Cell.Width);
+ }
+
+ ln_st.x += Cell.AdvanceX;
+ ln_size.x = ((INTN)ln_size.x <= Cell.AdvanceX) ? 0 : ln_size.x - Cell.AdvanceX;
+ origin.x += Cell.AdvanceX;
+
+ if(Free)
+ pBS->FreePool(GlyphBlock);
+ } //end of drawing line
+
+ ln_st.y += ln_size.y;
+ Link = (DRAW_LINE *)Link->Link.pNext;
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/UefiHii/HiiFontEx.c b/Core/CORE_DXE/UefiHii/HiiFontEx.c
new file mode 100644
index 0000000..32557da
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiFontEx.c
@@ -0,0 +1,1332 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c 2 9/17/13 10:19p Thomaschen $
+//
+// $Revision: 2 $
+//
+// $Date: 9/17/13 10:19p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c $
+//
+// 2 9/17/13 10:19p Thomaschen
+// Update for EIP105534 and EIP126176.
+//
+// 1 11/21/12 4:08a Wesleychen
+// Update rev.6 for EIP105534.
+// 11 5/16/13 5:01p Artems
+// [TAG] EIP123904
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] HiiFont and HiiConfig SCT tests are failed
+// [RootCause] Regression bugs when implementing new features or spec
+// updates
+// [Solution] Fixed code logic
+// [Files] HiiConfig.c HiiFontEx.c
+//
+// 10 5/02/13 1:52p Artems
+// [TAG] EIP121673
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Incorrect line width returned by function StringToImage
+// [RootCause] When determine line width function ignored flag
+// "IGNORE_IF_NO_GLYPH"
+// so line width was bigger if some glyphs were absent
+// [Solution] Modified code logic to not count width of absent glyphs
+// [Files] HiiFontEx.c
+//
+// 9 5/02/13 1:43p Artems
+// [TAG] EIP113105
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Wording for proportional font display was vague. After
+// clarification
+// code logic was slightly changed
+// [Files] HiiFontEx.c HiiPrivate.h
+//
+// 8 3/26/13 3:18p Artems
+// [TAG] EIP119250
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hang on Setup entry
+// [RootCause] Incorrect boundaries checking in HiiFontEx.c function
+// CheckVisible()
+// [Solution] Changed checking condition
+// [Files] HiiFontEx.c
+//
+// 7 2/25/13 4:44p Artems
+// [TAG] EIP101673
+// [Category] New Feature
+// [Description] Add support for AMI custom large fixed font
+// [Files] HiiDatabase.c HiiFontEx.c HiiPrivate.h UefiHiiUtils.c GC.c
+// new LargeFont Core modulePart
+//
+// 6 11/14/12 6:03p Artems
+// [TAG] EIP105534
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] system hangs during SCT execution
+// [RootCause] Incorrect handling of FORM_FEED escape character in
+// StringToImage function
+// [Solution] Graphics console - added flag to ignore line breaks
+// HiiFont - fixed multiline drawing logic
+// [Files] Gc.c HiiFont.c HiiFontEx.c
+//
+// 5 8/24/12 5:34p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] One character is not displayed properly
+// [RootCause] Never accounted for the case, where character is
+// completely below base line
+// [Solution] added check that character height is less than OffsetY
+// [Files] HiiFontEx.c
+//
+// 4 6/15/12 12:21p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] doesn't build in 32-bit mode
+// [RootCause] Signed/Unsigned mismatch reported by 32-bit compiler
+// [Solution] typecasted one parameter to INTN
+// [Files] HiiFont.c HiiFontEx.c
+//
+// 3 6/14/12 6:32p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio fixed SCT reported
+// bugs
+// [Files] HiiFont.c HiiFontEx.c
+//
+// 2 5/24/12 3:00p Artems
+// [TAG] EIP83593
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] system dead loops in HiiGetFontInfo function
+// [RootCause] When loop through linked list of installed fonts pointer
+// was not updated
+// [Solution] Added pointer update
+// [Files] HiiFontEx.c
+//
+// 1 5/22/12 3:29p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support
+// [Files] HiiFontEx.c HiiFont.c HiiDatabase.c HiiString.c HiiPrivate.h
+// UefiHii.h
+//
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HiiFontEx.c
+//
+// Description: Proportional font support
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <UefiHii.h>
+#include <AmiDxeLib.h>
+#include "HiiPrivate.h"
+
+#define LOOSE_SIZE_MARGIN 4
+
+extern HII_DATABASE_PRIVATE_DATA PrivateData;
+extern SIMPLE_FONT DefaultFont[];
+extern EFI_FONT_HANDLE CurFont; //font to use
+extern CHAR16 *DrawString; //string to draw
+extern EFI_HII_OUT_FLAGS DrawFlags;
+extern DLIST DrawLines;
+extern UINTN ImageWidth;
+extern UINTN ImageHeight;
+extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefForegroundColor;
+extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefBackgroundColor;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DuplicateGlyph
+//
+// Description:
+// This function duplicates glyph from Origin and assigns it to the Char
+//
+// Input:
+// IN OUT FONT_LINK *Font - pointer to current font
+// IN CHAR16 Char - character to assign glyph to
+// IN CHAR16 Origin - character to assign glyph from
+//
+// Output:
+// EFI_NOT_FOUND - glyph for Origin character not found
+// EFI_SUCCESS - glyph created successfully
+// EFI_OUT_OF_RESOURCES - not enough memory to duplicate glyph
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DuplicateGlyph(
+ IN OUT FONT_LINK *Font,
+ IN CHAR16 Char,
+ IN CHAR16 Origin
+)
+{
+ EFI_STATUS Status;
+ GLYPH_LINK *Link = (GLYPH_LINK *)Font->Glyphs.pHead;
+ GLYPH_LINK *New;
+
+ while(Link != NULL) {
+ if(Link->Char == Origin)
+ break;
+ Link = (GLYPH_LINK *) Link->Link.pNext;
+ }
+
+ if(Link == NULL)
+ return EFI_NOT_FOUND;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &New);
+ if(!EFI_ERROR(Status)) {
+ New->Char = Char;
+ New->Cell = Link->Cell;
+ New->GlyphBlock = Link->GlyphBlock;
+ DListAdd(&(Font->Glyphs), (DLINK *)New);
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddGlyphs
+//
+// Description:
+// This function adds glyphs to specified font
+//
+// Input:
+// IN OUT FONT_LINK *Font - pointer to current font
+// IN EFI_HII_GLYPH_INFO Cell - variable that contains font dimensions
+// IN UINT8 *GlyphBlock - pointer to glyph block
+// IN UINT16 Count - number of glyphs to add
+// IN CHAR16 Char - first character to assign glyph to
+// OUT UINTN *BytesProcessed - number of bytes from glyph block that were assigned
+//
+// Output:
+// EFI_SUCCESS - glyph created successfully
+// EFI_OUT_OF_RESOURCES - not enough memory to add glyphs
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddGlyphs(
+ IN OUT FONT_LINK *Font,
+ IN EFI_HII_GLYPH_INFO Cell,
+ IN UINT8 *GlyphBlock,
+ IN UINT16 Count,
+ IN CHAR16 Char,
+ OUT UINTN *BytesProcessed
+)
+{
+ EFI_STATUS Status;
+ GLYPH_LINK *Glyph;
+ UINTN Bytes = ((Cell.Width + 7) / 8) * Cell.Height;
+ UINTN i;
+
+ for(i = 0; i < Count; i++) {
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &Glyph);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Glyph->Cell = Cell;
+ Glyph->Char = Char;
+ Char++;
+ Glyph->GlyphBlock = GlyphBlock;
+ GlyphBlock += Bytes;
+ DListAdd(&(Font->Glyphs), (DLINK *)Glyph);
+ }
+
+ *BytesProcessed = Bytes * Count;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseGlyphs
+//
+// Description:
+// This function parses packed glyphs and creates glyphs for characters
+//
+// Input:
+// IN OUT FONT_LINK *Font - pointer to current font
+//
+// Output:
+// EFI_ERROR - some error was encountered during parsing
+// EFI_SUCCESS - glyph created successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseGlyphs(
+ IN OUT FONT_LINK *Font
+)
+{
+ EFI_STATUS Status;
+ CHAR16 Current = 1;
+ EFI_HII_GLYPH_INFO Default = Font->FontPackage->Cell;
+ EFI_HII_GLYPH_INFO CurCell;
+ UINT8 *Walker = (UINT8 *)Font->FontPackage;
+ UINT8 *EndMarker;
+ UINTN Bytes;
+ UINT16 CurCount;
+ static const EFI_HII_GLYPH_INFO ZeroCell = { 0, 0, 0, 0, 0 };
+ EFI_HII_GLYPH_INFO ChangeCell;
+ UINTN BelowBaseLine;
+ UINTN AboveBaseLine;
+ UINTN MaxBelowBaseLine = 0;
+ UINTN MaxAboveBaseLine = 0;
+
+ EndMarker = Walker + Font->FontPackage->Header.Length;
+ Walker += Font->FontPackage->GlyphBlockOffset;
+ ChangeCell = Default;
+
+ do {
+ switch (*Walker) {
+ case EFI_HII_GIBT_SKIP1:
+ Current += ((EFI_HII_GIBT_SKIP1_BLOCK *)Walker)->SkipCount;
+ Walker += sizeof(EFI_HII_GIBT_SKIP1_BLOCK);
+ break;
+ case EFI_HII_GIBT_SKIP2:
+ Current += ((EFI_HII_GIBT_SKIP2_BLOCK *)Walker)->SkipCount;
+ Walker += sizeof(EFI_HII_GIBT_SKIP2_BLOCK);
+ break;
+ case EFI_HII_GIBT_EXT1:
+ Walker += sizeof(EFI_HII_GIBT_EXT1_BLOCK);
+ break;
+ case EFI_HII_GIBT_EXT2:
+ Walker += sizeof(EFI_HII_GIBT_EXT2_BLOCK);
+ break;
+ case EFI_HII_GIBT_EXT4:
+ Walker += sizeof(EFI_HII_GIBT_EXT4_BLOCK);
+ break;
+ case EFI_HII_GIBT_DEFAULTS:
+ Default = ((EFI_HII_GIBT_DEFAULTS_BLOCK *)Walker)->Cell;
+ ChangeCell = Default;
+ Walker += sizeof(EFI_HII_GIBT_DEFAULTS_BLOCK);
+ break;
+ case EFI_HII_GIBT_END:
+ break;
+ case EFI_HII_GIBT_GLYPH:
+ CurCell = ((EFI_HII_GIBT_GLYPH_BLOCK *)Walker)->Cell;
+ ChangeCell = CurCell;
+ Walker += sizeof(EFI_HII_GIBT_GLYPH_BLOCK);
+ Status = AddGlyphs(Font, CurCell, Walker, 1, Current, &Bytes);
+ if(EFI_ERROR(Status))
+ return Status;
+ Walker += Bytes;
+ Current++;
+ break;
+ case EFI_HII_GIBT_GLYPH_DEFAULT:
+ Walker += sizeof(EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK);
+ Status = AddGlyphs(Font, Default, Walker, 1, Current, &Bytes);
+ if(EFI_ERROR(Status))
+ return Status;
+ Walker += Bytes;
+ Current++;
+ break;
+ case EFI_HII_GIBT_GLYPHS:
+ CurCell = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Cell;
+ CurCount = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Count;
+ ChangeCell = CurCell;
+ Walker += sizeof(EFI_HII_GIBT_GLYPHS_BLOCK);
+ Status = AddGlyphs(Font, CurCell, Walker, CurCount, Current, &Bytes);
+ if(EFI_ERROR(Status))
+ return Status;
+ Walker += Bytes;
+ Current += CurCount;
+ break;
+ case EFI_HII_GIBT_GLYPHS_DEFAULT:
+ CurCount = ((EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK *)Walker)->Count;
+ Walker += sizeof(EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK);
+ Status = AddGlyphs(Font, Default, Walker, CurCount, Current, &Bytes);
+ if(EFI_ERROR(Status))
+ return Status;
+ Walker += Bytes;
+ Current += CurCount;
+ break;
+ case EFI_HII_GIBT_DUPLICATE:
+ Status = DuplicateGlyph(Font, Current, ((EFI_HII_GIBT_DUPLICATE_BLOCK *)Walker)->CharValue);
+ if(EFI_ERROR(Status))
+ return Status;
+ Walker += sizeof(EFI_HII_GIBT_DUPLICATE_BLOCK);
+ Current++;
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ if(MemCmp(&ChangeCell, (VOID *)&ZeroCell, sizeof(EFI_HII_GLYPH_INFO))) {
+ if(ChangeCell.OffsetY < 0) {
+ BelowBaseLine = (UINTN)(0 - ChangeCell.OffsetY);
+ AboveBaseLine = (ChangeCell.Height > BelowBaseLine) ? (ChangeCell.Height - BelowBaseLine) : 0;
+ } else {
+ AboveBaseLine = ChangeCell.Height + ChangeCell.OffsetY;
+ BelowBaseLine = 0;
+ }
+ MaxBelowBaseLine = (MaxBelowBaseLine >= BelowBaseLine) ? MaxBelowBaseLine : BelowBaseLine;
+ MaxAboveBaseLine = (MaxAboveBaseLine >= AboveBaseLine) ? MaxAboveBaseLine : AboveBaseLine;
+ ChangeCell = ZeroCell;
+ }
+
+ } while(*Walker != 0 && Walker <= EndMarker);
+
+ Font->FontHeight = MaxBelowBaseLine + MaxAboveBaseLine;
+ Font->FontBaseLine = MaxAboveBaseLine;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: RepackGlyphBlock
+//
+// Description:
+// This function repacks glyph block of AMI custom font package to be similar
+// to proportional font glyph block for easier processing
+//
+// Input:
+// IN OUT FONT_LINK *Font - pointer to current font
+//
+// Output:
+// EFI_ERROR - some error was encountered during parsing
+// EFI_SUCCESS - glyph created successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RepackGlyphBlock(
+ IN UINT8 *GlyphBlock,
+ IN UINT16 Width,
+ IN UINT16 Height
+)
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT8 *Tmp;
+ UINT16 Line;
+ UINT16 i, j, k = 0;
+
+ Line = (Width + 7) / 8; //how many bytes describe one line of glyph
+ Size = Line * Height;
+ Status = pBS->AllocatePool(EfiBootServicesData, Size, &Tmp);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ for(i = 0; i < Height; i++) {
+ for(j = 0; j < Line; j++) {
+ Tmp[k] = GlyphBlock[i + j * Height];
+ k++;
+ }
+ }
+ MemCpy(GlyphBlock, Tmp, Size);
+ pBS->FreePool(Tmp);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseAmiGlyphs
+//
+// Description:
+// This function parses custom AMI packed glyphs and creates glyphs for characters
+//
+// Input:
+// IN OUT FONT_LINK *Font - pointer to current font
+//
+// Output:
+// EFI_ERROR - some error was encountered during parsing
+// EFI_SUCCESS - glyph created successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseAmiGlyphs(
+ IN OUT FONT_LINK *Font
+)
+{
+ EFI_STATUS Status;
+ EFI_NARROW_GLYPH *Walker;
+ EFI_HII_GLYPH_INFO CurCell;
+ AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *AmiHdr;
+ UINT16 i;
+ UINTN Bytes;
+
+ AmiHdr = (AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage;
+ CurCell.Width = AmiHdr->Width;
+ CurCell.Height = AmiHdr->Height;
+ CurCell.OffsetX = 0;
+ CurCell.OffsetY = 0;
+ Walker = (EFI_NARROW_GLYPH *)(AmiHdr + 1);
+ for(i = 0; i < AmiHdr->NumberOfNarrowGlyphs; i++) {
+ CurCell.AdvanceX = (Walker->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : CurCell.Width;
+ Status = RepackGlyphBlock(Walker->GlyphCol1, CurCell.Width, CurCell.Height);
+ if(EFI_ERROR(Status))
+ return Status;
+ Status = AddGlyphs(Font, CurCell, Walker->GlyphCol1, 1, Walker->UnicodeWeight, &Bytes);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Walker = (EFI_NARROW_GLYPH *)(Walker->GlyphCol1 + Bytes);
+ }
+
+ Font->FontHeight = AmiHdr->Height;
+ Font->FontBaseLine = AmiHdr->Height;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseFontsPackage
+//
+// Description:
+// This function parses font package
+//
+// Input:
+// IN EFI_HII_FONT_PACKAGE_HDR *Package - pointer to font package
+//
+// Output:
+// EFI_ERROR - some error was encountered during parsing
+// EFI_SUCCESS - glyph created successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseFontsPackage(
+ IN EFI_HII_FONT_PACKAGE_HDR *Package
+)
+{
+ EFI_STATUS Status;
+ EFI_HII_FONT_PACKAGE_HDR *Copy;
+ FONT_LINK *Font;
+
+/* first make global copy of the package */
+ Status = pBS->AllocatePool(EfiBootServicesData, Package->Header.Length, &Copy);
+ if(EFI_ERROR(Status))
+ return Status;
+ MemCpy(Copy, Package, Package->Header.Length);
+
+/* create Font link */
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(FONT_LINK), &Font);
+ if(EFI_ERROR(Status))
+ return Status;
+
+/* initialize font link */
+ Font->FontPackage = Copy;
+ DListInit(&(Font->Glyphs));
+
+ if(Package->Header.Type == AMI_HII_PACKAGE_FONTS)
+ Status = ParseAmiGlyphs(Font);
+ else
+ Status = ParseGlyphs(Font);
+
+ if(!EFI_ERROR(Status))
+ DListAdd(&(PrivateData.FontList), (DLINK *)Font);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchName
+//
+// Description:
+// This function checks whether passed name matches name of the passed font
+//
+// Input:
+// IN FONT_LINK *Font - pointer to font
+// IN CHAR16 *FontName - pointer to font name to match with
+// IN FONT_MATCH_MASK Mask - matching rules
+//
+// Output:
+// TRUE - names are matched
+// FALSE - names are not matched
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchName(
+ IN FONT_LINK *Font,
+ IN CHAR16 *FontName,
+ IN FONT_MATCH_MASK Mask
+)
+{
+ UINT8 *Walker;
+
+ if(Mask.MatchName == MATCH_INGNORE)
+ return TRUE;
+
+ if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS &&
+ !Wcscmp(FontName, L"Ami font"))
+ return TRUE;
+
+ Walker = (UINT8 *)Font->FontPackage;
+ Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR);
+ /* now Walker points to font name */
+ if(Wcscmp(FontName, (CHAR16 *)Walker))
+ return FALSE;
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchStyle
+//
+// Description:
+// This function checks whether passed style matches style of the passed font
+//
+// Input:
+// IN FONT_LINK *Font - pointer to font
+// IN EFI_HII_FONT_STYLE FontStyle - font style to match with
+// IN FONT_MATCH_MASK Mask - matching rules
+//
+// Output:
+// TRUE - styles are matched
+// FALSE - styles are not matched
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchStyle(
+ IN FONT_LINK *Font,
+ IN EFI_HII_FONT_STYLE FontStyle,
+ IN FONT_MATCH_MASK Mask
+)
+{
+ EFI_HII_FONT_STYLE Cur;
+
+ if(Mask.MatchStyle == MATCH_INGNORE)
+ return TRUE;
+
+ if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS)
+ Cur = EFI_HII_FONT_STYLE_NORMAL;
+ else
+ Cur = Font->FontPackage->FontStyle;
+
+ if(FontStyle == Cur)
+ return TRUE;
+
+/* when restyle is ordered we support interchange between Normal, Bold and Italic styles */
+ if(Mask.MatchStyle == MATCH_LOOSE &&
+ FontStyle <= 3 &&
+ Cur <= 3)
+ return TRUE;
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchSize
+//
+// Description:
+// This function checks whether passed size matches size of the passed font
+//
+// Input:
+// IN FONT_LINK *Font - pointer to font
+// IN UINT16 FontSize - font size to match with
+// IN FONT_MATCH_MASK Mask - matching rules
+//
+// Output:
+// TRUE - sizes are matched
+// FALSE - sizes are not matched
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchSize(
+ IN FONT_LINK *Font,
+ IN UINT16 FontSize,
+ IN FONT_MATCH_MASK Mask
+)
+{
+ UINT16 Cur;
+
+ if(Mask.MatchSize == MATCH_INGNORE)
+ return TRUE;
+
+ if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS)
+ Cur = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height;
+ else
+ Cur = Font->FontPackage->Cell.Height;
+
+ if(FontSize == Cur)
+ return TRUE;
+
+/* when resize is ordered we support interchange sizes within +/- LOOSE_SIZE_MARGIN from given size */
+ if(Mask.MatchSize == MATCH_LOOSE &&
+ Cur <= FontSize + LOOSE_SIZE_MARGIN &&
+ Cur >= FontSize - LOOSE_SIZE_MARGIN)
+ return TRUE;
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindGlyph
+//
+// Description:
+// This function checks whether glyph for passed character is present, and returns it
+// if necessary
+//
+// Input:
+// IN DLIST Glyphs - linked list of glyphs to search within
+// IN CHAR16 Char - character value to return glyph for
+// OUT GLYPH_LINK **Match OPTIONAL - pointer to store returned glyph
+//
+// Output:
+// TRUE - glyph found
+// FALSE - glyph not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN FindGlyph(
+ IN DLIST Glyphs,
+ IN CHAR16 Char,
+ OUT GLYPH_LINK **Match OPTIONAL
+)
+{
+ GLYPH_LINK *Link = (GLYPH_LINK *)Glyphs.pHead;
+
+ while(Link != NULL) {
+ if(Link->Char == Char) {
+ if(Match != NULL)
+ *Match = Link;
+ return TRUE;
+ }
+ Link = (GLYPH_LINK *)Link->Link.pNext;
+ }
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MatchString
+//
+// Description:
+// This function checks whether all character glyphs are present for given string
+//
+// Input:
+// IN FONT_LINK *Font - pointer to the font
+// IN CONST EFI_STRING String - pointer to the string to check
+//
+// Output:
+// TRUE - all glyphs are present
+// FALSE - some glyphs are missing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN MatchString(
+ IN FONT_LINK *Font,
+ IN CONST EFI_STRING String
+)
+{
+ CHAR16 *Tst;
+
+ if(String == NULL)
+ return TRUE;
+
+ Tst = String;
+
+ while(*Tst != 0) {
+ if(!FindGlyph(Font->Glyphs, *Tst, NULL))
+ return FALSE;
+ Tst++;
+ }
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindFont
+//
+// Description:
+// This function tries to find font in database, that meets the criteria
+//
+// Input:
+// IN OUT EFI_FONT_HANDLE *FontHandle - handle in database to start search from
+// IN CHAR16 *FontName - pointer to the font name
+// IN EFI_HII_FONT_STYLE FontStyle - font style
+// IN UINT16 FontSize - font size
+// IN FONT_MATCH_MASK Mask - matching rules
+// IN CONST EFI_STRING String - pointer to string to verify glyphs presence
+//
+// Output:
+// EFI_SUCCESS - font found
+// EFI_NOT_FOUND - font not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindFont(
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CHAR16 *FontName,
+ IN EFI_HII_FONT_STYLE FontStyle,
+ IN UINT16 FontSize,
+ IN FONT_MATCH_MASK Mask,
+ IN CONST EFI_STRING String
+)
+{
+ FONT_LINK *Font;
+
+ if(PrivateData.FontList.Size == 0)
+ /* no fonts in database */
+ return EFI_NOT_FOUND;
+
+ Font = (FONT_LINK *)PrivateData.FontList.pHead;
+
+/* check if handle passed is not NULL or dummy default font handle */
+ if((UINTN)(*FontHandle) != NULL && (UINTN)(*FontHandle) != DEFAULT_FONT_HANDLE) {
+ while(Font != NULL) {
+ if((VOID *)Font == *FontHandle)
+ break;
+ Font = (FONT_LINK *)Font->Link.pNext;
+ }
+ if(Font == NULL) {
+ /* end of font list - no matches */
+ *FontHandle = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ /* match found, it was last returned font, move to the next */
+ Font = (FONT_LINK *)Font->Link.pNext;
+ if(Font == NULL) {
+ /* end of font list, last returned font was last indeed */
+ *FontHandle = NULL;
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ while(Font != NULL) {
+ /* loop through font list to find the match */
+ if(MatchName(Font, FontName, Mask) &&
+ MatchStyle(Font, FontStyle, Mask) &&
+ MatchSize(Font, FontSize, Mask) &&
+ MatchString(Font, String)) {
+ /* match is found */
+ *FontHandle = (EFI_FONT_HANDLE)Font;
+ return EFI_SUCCESS;
+ }
+ Font = (FONT_LINK *)Font->Link.pNext;
+ }
+ *FontHandle = NULL;
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FillFontInfo
+//
+// Description:
+// This function returns EFI_FONT_DISPLAY_INFO data for given font
+//
+// Input:
+// IN EFI_FONT_HANDLE FontHandle - font handle to return info about
+// OUT EFI_FONT_DISPLAY_INFO **StringInfoOut - pointer where to store returned info
+//
+// Output:
+// EFI_SUCCESS - info returned
+// EFI_OUT_OF_RESOURCES - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FillFontInfo(
+ IN EFI_FONT_HANDLE FontHandle,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut
+)
+{
+ UINTN NameSize;
+ EFI_FONT_DISPLAY_INFO *Ret;
+ FONT_LINK *Font;
+ UINT8 *Walker;
+ EFI_STATUS Status;
+ static CHAR16 DefaultFontName[] = L"System font";
+
+ Font = (FONT_LINK *)FontHandle;
+ if((UINTN)Font != DEFAULT_FONT_HANDLE) {
+ Walker = (UINT8 *)Font->FontPackage;
+ Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR);
+ } else {
+ Walker = (UINT8 *)DefaultFontName;
+ }
+
+ NameSize = Wcslen((CHAR16 *)Walker) * sizeof(CHAR16);
+
+/* font display info structure includes font info structure, where one CHAR16 already reserved
+ that's why Wcslen used instead fo Wcssize - null-terminator already accounted for */
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_FONT_DISPLAY_INFO) + NameSize, &Ret);
+ if(!EFI_ERROR(Status)) {
+ if((UINTN)Font != DEFAULT_FONT_HANDLE) {
+ if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) {
+ Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL;
+ Ret->FontInfo.FontSize = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height;
+ } else {
+ Ret->FontInfo.FontStyle = Font->FontPackage->FontStyle;
+ Ret->FontInfo.FontSize = Font->FontPackage->Cell.Height;
+ }
+ } else {
+ Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL;
+ Ret->FontInfo.FontSize = EFI_GLYPH_HEIGHT;
+ }
+ Wcscpy(Ret->FontInfo.FontName, (CHAR16 *)Walker);
+ *StringInfoOut = Ret;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IntGetGlyph
+//
+// Description:
+// This function returns glyph for given charactef from given font
+//
+// Input:
+// IN EFI_FONT_HANDLE FontHandle - font handle of the desired font
+// IN CHAR16 Char - character to return glyph for
+// OUT EFI_HII_GLYPH_INFO *Cell - pointer to store info about glyph dimensions
+// OUT UINT8 **GlyphBlock OPTIONAL - pointer to store glyph
+// OUT BOOLEAN *Free - pointer to return flag was memory allocated for glyph and
+// should be freed by caller
+//
+// Output:
+// EFI_SUCCESS - glyph returned
+// EFI_NOT_FOUND - glyph not found
+// EFI_OUT_OF_RESOURCES - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS IntGetGlyph(
+ IN EFI_FONT_HANDLE FontHandle,
+ IN CHAR16 Char,
+ OUT EFI_HII_GLYPH_INFO *Cell,
+ OUT UINT8 **GlyphBlock OPTIONAL,
+ OUT BOOLEAN *Free
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS AllocStatus;
+ FONT_LINK *Font;
+ GLYPH_LINK *GlyphLink;
+ BOOLEAN Found;
+ SIMPLE_FONT Glyph;
+ UINT8 *WideGlyphBlock;
+ UINTN i;
+
+ *Free = FALSE;
+ Font = (FONT_LINK *)FontHandle;
+
+ if((UINTN)Font != DEFAULT_FONT_HANDLE) {
+ Found = FindGlyph(Font->Glyphs, Char, &GlyphLink);
+ if(!Found) {
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ Found = FindGlyph(Font->Glyphs, 0xfffd, &GlyphLink);
+ }
+ if(Found) {
+ *Cell = GlyphLink->Cell;
+ if(GlyphBlock)
+ *GlyphBlock = GlyphLink->GlyphBlock;
+ return Status;
+ }
+ Glyph = DefaultFont[0xfffd];
+ } else {
+ /* Default font requested */
+ Glyph = DefaultFont[(UINTN)Char];
+ if(Glyph.NarrowGlyph == NULL && Glyph.WideGlyph == NULL) {
+ Glyph = DefaultFont[0xfffd];
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ }
+/* if we're here we use system font - either because it was requested, or
+because supplied font doesn't have requested character or 0xfffd character
+!!!! It is assumed that system font always have 0xfffd character font */
+ Cell->Height = EFI_GLYPH_HEIGHT;
+ Cell->OffsetX = 0;
+ Cell->OffsetY = 0;
+ if(Glyph.NarrowGlyph != NULL) {
+ Cell->Width = EFI_GLYPH_WIDTH;
+ Cell->AdvanceX = ((Glyph.NarrowGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDTH;
+ if(GlyphBlock)
+ *GlyphBlock = (Glyph.NarrowGlyph)->GlyphCol1;
+ } else if(Glyph.WideGlyph != NULL) {
+ Cell->Width = EFI_GLYPH_WIDE_WIDTH;
+ Cell->AdvanceX = ((Glyph.WideGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDE_WIDTH;
+ if(GlyphBlock) {
+ AllocStatus = pBS->AllocatePool(EfiBootServicesData, sizeof(UINT8) * 2 * EFI_GLYPH_HEIGHT, &WideGlyphBlock);
+ if(EFI_ERROR(AllocStatus))
+ return AllocStatus;
+ for(i = 0; i < EFI_GLYPH_HEIGHT; i++) {
+ WideGlyphBlock[2 * i] = (Glyph.WideGlyph)->GlyphCol1[i];
+ WideGlyphBlock[2 * i + 1] = (Glyph.WideGlyph)->GlyphCol2[i];
+ }
+ *GlyphBlock = WideGlyphBlock;
+ *Free = TRUE;
+ }
+ } else {
+ Cell->AdvanceX = 0;
+ return EFI_NOT_FOUND;
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateLineSize
+//
+// Description:
+// This function updates dimensions in pixels of given line based on glyphs of current font
+//
+// Input:
+// IN OUT DRAW_LINE *Line - pointer to the line structure
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateLineSize(
+ IN OUT DRAW_LINE *Line
+)
+{
+ EFI_STATUS Status;
+ UINTN Width = 0;
+ UINTN i;
+ EFI_HII_GLYPH_INFO Cell;
+ BOOLEAN Dummy;
+
+ for(i = Line->StartIndex; i <= Line->EndIndex; i++) {
+ if((DrawFlags & EFI_HII_IGNORE_LINE_BREAK) && IsLineBreak(DrawString[i]))
+ continue;
+
+ Status = IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy);
+ if(Status == EFI_WARN_UNKNOWN_GLYPH && (DrawFlags & EFI_HII_IGNORE_IF_NO_GLYPH))
+ continue;
+
+ Width = (Cell.AdvanceX < 0) ? Width : Width + (UINT16)Cell.AdvanceX;
+ }
+ Line->LineWidth = Width;
+ Line->LineHeight = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontHeight;
+ Line->BaseLineOffset = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontBaseLine;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ClipLine
+//
+// Description:
+// This function updates dimensions in pixels of given line to fit given width
+//
+// Input:
+// IN OUT DRAW_LINE *Line - pointer to the line structure
+// IN UINTN Width - width to fit
+// IN BOOLEAN ClipClean - clipping mode
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ClipLine(
+ IN OUT DRAW_LINE *Line,
+ IN UINTN Width,
+ IN BOOLEAN ClipClean
+)
+{
+ UINTN Excess;
+ UINTN i;
+ EFI_HII_GLYPH_INFO Cell;
+ BOOLEAN Dummy;
+
+ Excess = Line->LineWidth - Width;
+
+ for(i = Line->EndIndex; i >= Line->StartIndex; i--) {
+ IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy);
+ if ((INTN)Excess <= Cell.AdvanceX)
+ break;
+ Excess -= Cell.AdvanceX;
+ Line->LineWidth -= Cell.AdvanceX;
+ }
+
+ if(Excess == Cell.AdvanceX || ClipClean) {
+ /* remove excess character */
+ i--;
+ Line->LineWidth -= Cell.AdvanceX;
+ IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy);
+ if(Cell.AdvanceX == 0)
+ /* the previous character is non-spacing -remove it also */
+ i--;
+ } else {
+ /* perform partial clipping */
+ Line->LineWidth -= Excess;
+ }
+ Line->EndIndex = i;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WrapLine
+//
+// Description:
+// This function updates dimensions in pixels of given line to fit given width
+// and creates additional line if necessary
+//
+// Input:
+// IN OUT DRAW_LINE *Line - pointer to the line structure
+// IN UINTN Width - width to fit
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WrapLine(
+ IN OUT DRAW_LINE *Line,
+ IN UINTN Width
+)
+{
+ UINTN Excess;
+ UINTN i;
+ UINTN NewEnd;
+ UINTN NewStart;
+ DRAW_LINE *NewLine;
+ EFI_HII_GLYPH_INFO Cell;
+ BOOLEAN Dummy;
+ UINTN Save;
+
+ Excess = Line->LineWidth - Width;
+
+ for(i = Line->EndIndex; (i >= Line->StartIndex && i != 0); i--) {
+ IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy);
+ if ((INTN)Excess <= Cell.AdvanceX)
+ break;
+ Excess -= Cell.AdvanceX;
+ }
+ if(i == 0 || i == Line->StartIndex) {
+ Line->EndIndex = i;
+ Line->LineWidth = 0;
+ return EFI_SUCCESS;
+ } else {
+ Save = i; //save index of first excess character
+ } //we will you it if no break opp arises for clip_clean operation
+
+/* we skipped excessed characters - start search for line break opp */
+ for(; (i >= Line->StartIndex && i != 0); i--) {
+ if(IsLineBreakOpp(DrawString[i])) {
+ /* we found line break opportunity */
+ NewEnd = Line->EndIndex;
+ NewStart = i + 1;
+ Line->EndIndex = i;
+ UpdateLineSize(Line);
+ if(Line->LineWidth > Width)
+ /* case when line-break opp character is partially visible - skip it */
+ Line->EndIndex--;
+ /* add a new line */
+ NewLine = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5);
+ if(NewLine == NULL)
+ return EFI_OUT_OF_RESOURCES;
+ NewLine->StartIndex = NewStart;
+ NewLine->EndIndex = NewEnd;
+ UpdateLineSize(NewLine);
+ DListInsert(&DrawLines, (DLINK *)NewLine, (DLINK *)Line);
+ return EFI_SUCCESS;
+ }
+ }
+/* if we're here, no line break opp present, use clip clean */
+ Line->EndIndex = Save - 1;
+ UpdateLineSize(Line);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetDrawImageSize
+//
+// Description:
+// This function returns size of image necessary to fit processing string
+// including all wraps and clips
+//
+// Input:
+// OUT UINTN *Width - pointer to store required width
+// OUT UINTN *Height - pointer to store required height
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetDrawImageSize(
+ OUT UINTN *Width,
+ OUT UINTN *Height
+)
+{
+ DRAW_LINE *Link;
+ UINTN MaxWidth = 0;
+ UINTN MaxHeight = 0;
+
+ Link = (DRAW_LINE *)(DrawLines.pHead);
+ while(Link != NULL)
+ {
+ MaxWidth = (MaxWidth < Link->LineWidth) ? Link->LineWidth : MaxWidth;
+ MaxHeight += Link->LineHeight;
+ Link = (DRAW_LINE *)Link->Link.pNext;
+ }
+ *Width = MaxWidth;
+ *Height = MaxHeight;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PixelSet
+//
+// Description:
+// This function checks whether pixel with given coordinates is set in given glyph
+//
+// Input:
+// IN UINTN PosX - X coordinate of pixel
+// IN UINTN PosY - Y coordinate of pixel
+// IN UINT8 *GlyphBlock - pointer to glyph array
+// IN UINT16 CharWidth - width of character described by glyph
+//
+// Output:
+// TRUE - pixel is set
+// FALSE - pixel is not set
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN PixelSet(
+ IN UINTN PosX,
+ IN UINTN PosY,
+ IN UINT8 *GlyphBlock,
+ IN UINT16 CharWidth
+)
+{
+ UINTN Step;
+ UINTN Index;
+ UINT8 Bit;
+
+ Step = (CharWidth + 7) / 8;
+ Index = (PosY * Step) + (PosX / 8);
+
+ Bit = (0x80 >> (PosX % 8));
+
+ return (Bit & GlyphBlock[Index]);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DrawGlyph
+//
+// Description:
+// This function draws given glyph on given bitmap
+//
+// Input:
+// IN UINTN StartX - start X coordinate of glyph
+// IN UINTN StartY - start Y coordinate of glyph
+// IN UINTN SizeX - width of glyph
+// IN UINTN SizeY - height of glyph
+// IN UINT8 *GlyphBlock - pointer to glyph array
+// IN BOOLEAN Transparent - flag if image should be transparent
+// IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt - bitmap to draw on
+// IN UINT16 CharWidth - width of character described by glyph
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DrawGlyph(
+ IN UINTN StartX,
+ IN UINTN StartY,
+ IN UINTN SizeX,
+ IN UINTN SizeY,
+ IN UINT8 *GlyphBlock,
+ IN BOOLEAN Transparent,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt,
+ IN UINT16 CharWidth
+)
+{
+ UINTN i;
+ UINTN j;
+ UINTN Index;
+ UINTN Base;
+
+ Base = StartX + StartY * ImageWidth;
+ for(i = 0; i < SizeY; i++ ) {
+ for(j = 0; j < SizeX; j++) {
+ Index = Base + i * ImageWidth + j;
+ if(PixelSet(j, i, GlyphBlock, CharWidth)) {
+ Blt[Index] = DefForegroundColor;
+ } else if (!Transparent) {
+ Blt[Index] = DefBackgroundColor;
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CheckVisible
+//
+// Description:
+// This function checks whether glyph is withing given image rectangle,
+// and clips glyph rectangle if necessary
+//
+// Input:
+// IN OUT RECT_COORD *Glyph - pointer to glyph rectangle
+// IN RECT_COORD *Image - pointer to image rectangle
+//
+// Output:
+// TRUE - glyph is visible (at least partially)
+// FALSE - glyph is out of image boundaries
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN CheckVisible(
+ IN OUT RECT_COORD *Glyph,
+ IN RECT_COORD *Image
+)
+{
+ UINTN delta_x;
+ UINTN delta_y;
+
+/* check whether glyph within given image rectangle */
+ if(Glyph->st->x >= (Image->st->x + Image->size->x) ||
+ Glyph->st->y >= (Image->st->y + Image->size->y))
+ return FALSE;
+
+/* clip glyph size if necessary */
+ delta_x = (Image->st->x < Glyph->st->x) ? Glyph->st->x - Image->st->x : 0;
+ delta_y = (Image->st->y < Glyph->st->y) ? Glyph->st->y - Image->st->y : 0;
+
+ if(Glyph->size->x > (Image->size->x - delta_x))
+ Glyph->size->x = Image->size->x - delta_x;
+
+ if(Glyph->size->y > (Image->size->y - delta_y))
+ Glyph->size->y = Image->size->y - delta_y;
+ return TRUE;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/UefiHii/HiiPrivate.h b/Core/CORE_DXE/UefiHii/HiiPrivate.h
new file mode 100644
index 0000000..9023189
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiPrivate.h
@@ -0,0 +1,885 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiPrivate.h 2 9/18/13 1:41a Thomaschen $
+//
+// $Revision: 2 $
+//
+// $Date: 9/18/13 1:41a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiPrivate.h $
+//
+// 2 9/18/13 1:41a Thomaschen
+// Update for EIP126176.
+//
+// 16 5/02/13 1:48p Artems
+// [TAG] EIP113105
+// [Category] Spec Update
+// [Severity] Important
+// [Description] Wording for proportional font display was vague. After
+// clarification
+// code logic was slightly changed
+// [Files] HiiFontEx.c HiiPrivate.h
+//
+// 14 2/25/13 4:45p Artems
+// [TAG] EIP101673
+// [Category] New Feature
+// [Description] Add support for AMI custom large fixed font
+// [Files] HiiDatabase.c HiiFontEx.c HiiPrivate.h UefiHiiUtils.c GC.c
+// new LargeFont Core modulePart
+//
+// 13 8/15/12 3:36p Artems
+// [TAG] EIP96755
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Strings in new language added at runtime lost during export
+// [RootCause] Every language represented by its own string package.
+// When
+// strings of new language added at runtime, they're added to database,
+// but not to the list of packages. Export function is working with
+// list of packages, so new language strings will be missed
+// [Solution] Added code to create new string package at runtime when
+// new string
+// of new language is added to database
+// [Files] HiiPrivate.h HiiString.c
+//
+// 12 5/22/12 4:16p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio
+// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c
+// UefiHii.h
+//
+// 11 1/05/12 5:05p Artems
+// EIP 76735: Font FFS file is not loaded in framework mode, when in
+// nested FV
+//
+// 10 5/13/11 6:14p Artems
+// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and
+// AmiHiiSetString
+// to avoid collusion with EdkII native library functions
+//
+// 9 5/13/11 5:17p Artems
+// Function CompareGuid (native EdkII) renamed to HiiCompareGuid to avoid
+// collusion
+//
+// 8 5/05/11 4:14p Artems
+// Add signal "layout changed" event if current layout is deleted
+//
+// 7 1/05/11 12:41p Artems
+// EIP 50995: Added checking of driver handle before adding packages to
+// HII database
+//
+// 6 11/05/10 5:17p Artems
+// EIP 46880: Fixed bug, where two functions referred to the same global
+// pointer
+//
+// 5 9/30/10 6:11p Artems
+// EIP 44657 Added GetAltConfig functionality
+//
+// 4 1/29/10 5:43p Artems
+// EIP 34553 Updated function ExportPackageLists to support NULL pointer
+// as input
+//
+// 3 12/04/09 11:16a Artems
+// Remove keyboard layout functionality added
+//
+// 2 12/03/09 6:04p Artems
+// SCT bug fix
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 2/27/09 3:55p Artems
+// Initial check-in
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: HiiPrivate.h
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __HII_PRIVATE__H__
+#define __HII_PRIVATE__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <AmiDxeLib.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiConfigRouting.h>
+
+#define NULL_GUID \
+ { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
+
+#define PACKAGE_LIST_RECORD_SIGNATURE 0x53524c80 //"PLRS"
+#define NOTIFY_LIST_RECORD_SIGNATURE 0x53524c4e //"NLRS"
+
+#define DEFAULT_FONT_HANDLE 0xDEADF000
+#define AMI_HII_PACKAGE_FONTS 0xE1
+
+#pragma pack (push,1)
+
+typedef struct _PACKAGE_LIST_RECORD {
+ DLINK Link;
+ UINT32 Signature;
+ EFI_GUID Guid;
+ EFI_HANDLE DriverHandle;
+ DLIST PackageList;
+ DLIST LanguageList;
+ DLIST StringFontList;
+ DBE_DATABASE StringDb;
+} PACKAGE_LIST_RECORD;
+
+typedef struct _NOTIFY_RECORD {
+ DLINK Link;
+ UINT32 Signature;
+ UINT8 PackageType;
+ EFI_GUID PackageGuid;
+ EFI_HII_DATABASE_NOTIFY PackageNotifyFn;
+ EFI_HII_DATABASE_NOTIFY_TYPE NotifyType;
+} NOTIFY_RECORD;
+
+typedef struct _HII_DATABASE_PRIVATE_DATA {
+ EFI_HII_DATABASE_PROTOCOL DatabaseProtocol;
+ EFI_HII_STRING_PROTOCOL StringProtocol;
+ EFI_HII_FONT_PROTOCOL FontProtocol;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRoutingProtocol;
+ DLIST PackList;
+ DLIST NotifyList;
+ DLIST KeyLayoutList;
+ DLIST FontList;
+ EFI_HII_KEYBOARD_LAYOUT *CurrentLayout;
+} HII_DATABASE_PRIVATE_DATA;
+
+typedef struct _PACKAGE_LINK {
+ DLINK Link;
+ EFI_HII_PACKAGE_HEADER Package;
+} PACKAGE_LINK;
+
+typedef struct _KEY_LAYOUT_LINK {
+ DLINK Link;
+ EFI_HII_KEYBOARD_LAYOUT Layout;
+} KEY_LAYOUT_LINK;
+
+typedef struct _SIMPLE_FONT {
+ EFI_NARROW_GLYPH *NarrowGlyph;
+ EFI_WIDE_GLYPH *WideGlyph;
+} SIMPLE_FONT;
+
+typedef struct _FONT_LINK {
+ DLINK Link;
+ EFI_HII_FONT_PACKAGE_HDR *FontPackage;
+ UINTN FontHeight;
+ UINTN FontBaseLine;
+ DLIST Glyphs;
+} FONT_LINK;
+
+typedef struct _STRING_FONT_LINK {
+ DLINK Link;
+ UINT16 FontId;
+ UINT32 FontInfoSize;
+// EFI_FONT_INFO FontInfo;
+} STRING_FONT_LINK;
+
+typedef struct _GLYPH_LINK {
+ DLINK Link;
+ CHAR16 Char;
+ EFI_HII_GLYPH_INFO Cell;
+ UINT8 *GlyphBlock;
+} GLYPH_LINK;
+
+typedef struct _LANGUAGE_LINK {
+ DLINK Link;
+ UINT16 LastStringId;
+ CHAR8 Language[1];
+} LANGUAGE_LINK;
+
+typedef struct _STRING_RECORD {
+ UINT16 StringId;
+ UINT16 LanguageId;
+ UINT16 FontId;
+ CHAR16 String[1];
+} STRING_RECORD;
+
+typedef struct _DRAW_LINE {
+ DLINK Link;
+ UINTN StartIndex;
+ UINTN EndIndex;
+ UINTN LineHeight;
+ UINTN LineWidth;
+ UINTN BaseLineOffset;
+} DRAW_LINE;
+
+typedef struct _NAME_PATTERN
+{
+ UINTN Length;
+ CHAR16 *Tag;
+} NAME_PATTERN;
+
+typedef struct {
+ CHAR16 *ResultString;
+ UINTN MaxResultStringSize;
+ UINTN CurrentSize;
+} RESULT_BLOCK;
+
+#define MATCH_INGNORE 0
+#define MATCH_STRICT 1
+#define MATCH_LOOSE 2
+
+typedef struct {
+ UINT32 MatchName : 1;
+ UINT32 MatchSize : 2;
+ UINT32 MatchStyle : 2;
+ UINT32 Reserved : 1;
+} FONT_MATCH_MASK;
+
+typedef struct {
+ UINTN x;
+ UINTN y;
+} POINT_COORD;
+
+typedef struct {
+ POINT_COORD *st;
+ POINT_COORD *size;
+} RECT_COORD;
+
+typedef struct {
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT16 NumberOfNarrowGlyphs;
+ UINT8 Height;
+ UINT8 Width;
+// EFI_NARROW_GLYPH NarrowGlyphs[]; //based on height and width given
+} AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR;
+
+#pragma pack (pop)
+
+//************ Database Protocol functions definition **************************
+
+EFI_STATUS HiiNewPack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN CONST EFI_HANDLE DriverHandle,
+ OUT EFI_HII_HANDLE *Handle
+);
+
+EFI_STATUS HiiRemovePack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+);
+
+EFI_STATUS HiiUpdatePack (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
+);
+
+EFI_STATUS HiiListPacks (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN OUT UINTN *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+);
+
+EFI_STATUS HiiExportPacks (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+);
+
+EFI_STATUS HiiRegisterNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ OUT EFI_HANDLE *NotifyHandle
+);
+
+EFI_STATUS HiiUnregisterNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+);
+
+EFI_STATUS HiiFindKeyboardLayouts (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_GUID *KeyGuidBuffer
+);
+
+EFI_STATUS HiiGetKeyboardLayout (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_GUID *KeyGuid,
+ IN OUT UINT16 *KeyGuidBufferLength,
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
+);
+
+EFI_STATUS HiiSetKeyboardLayout (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_GUID *KeyGuid
+);
+
+EFI_STATUS HiiGetPackageListHandle (
+ IN EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle
+);
+
+//************************* String protocol functions definition **********
+
+EFI_STATUS HiiNewString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_STRING_ID *StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST CHAR16 *LanguageName OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo
+);
+
+EFI_STATUS AmiHiiGetString(
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN CONST CHAR8 *Language,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+);
+
+EFI_STATUS AmiHiiSetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
+);
+
+EFI_STATUS HiiGetLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN OUT CHAR8 *Languages,
+ IN OUT UINTN *LanguagesSize
+);
+
+EFI_STATUS HiiGetSecondLanguages(
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8* FirstLanguage,
+ IN OUT CHAR8 *SecondLanguages,
+ IN OUT UINTN *SecondLanguagesSize
+);
+
+//************************* Font protocol functions definition ****************
+
+EFI_STATUS HiiStringToImage(
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+);
+
+EFI_STATUS HiiStringIdToImage (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN EFI_HII_OUT_FLAGS Flags,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8* Language,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,
+ IN OUT EFI_IMAGE_OUTPUT **Blt,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,
+ OUT UINTN *RowInfoArraySize OPTIONAL,
+ OUT UINTN *ColumnInfoArray OPTIONAL
+);
+
+EFI_STATUS HiiGetGlyph (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN CHAR16 Char,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_IMAGE_OUTPUT **Blt,
+ OUT UINTN *Baseline OPTIONAL
+);
+
+EFI_STATUS HiiGetFontInfo (
+ IN CONST EFI_HII_FONT_PROTOCOL *This,
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,
+ IN CONST EFI_STRING String OPTIONAL
+);
+
+//************************* Config Routing protocol functions definition ******
+
+EFI_STATUS HiiExtractConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+);
+
+EFI_STATUS HiiExportConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+);
+
+EFI_STATUS HiiRouteConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+);
+
+EFI_STATUS HiiBlockToConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigRequest,
+ IN CONST UINT8 *Block,
+ IN CONST UINTN BlockSize,
+ OUT EFI_STRING *Config,
+ OUT EFI_STRING *Progress
+);
+
+EFI_STATUS HiiConfigToBlock (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN OUT CONST UINT8 *Block,
+ IN OUT UINTN *BlockSize,
+ OUT EFI_STRING *Progress
+);
+
+EFI_STATUS HiiGetAltConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigResp,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_STRING AltCfgId,
+ OUT EFI_STRING *AltCfgResp
+);
+
+//*************************Service functions (not for public use)**************
+
+VOID InvokeRegisteredNotify (
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+);
+
+BOOLEAN FindAndRemovePackages (
+ IN EFI_HII_HANDLE Handle,
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN BOOLEAN FindOnly
+);
+
+VOID RemovePackage (
+ IN EFI_HII_HANDLE Handle,
+ IN PACKAGE_LINK *Package
+);
+
+EFI_STATUS AddPackage(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+);
+
+EFI_STATUS AddPackages(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ BOOLEAN Update
+);
+
+EFI_STATUS UpdateStringPackages(
+ IN EFI_HII_HANDLE Handle
+);
+
+UINTN GetStringBlockSize(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN CHAR8 *Language
+);
+
+VOID GetStringBlock(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN CHAR8 *Language,
+ IN UINT8 *Buffer
+);
+
+BOOLEAN MatchPackage(
+ IN UINT8 PackageType,
+ IN EFI_GUID *PackageGuid,
+ IN EFI_HII_PACKAGE_HEADER *Package
+);
+
+BOOLEAN CheckIfPresent(
+ IN EFI_GUID *Guid,
+ IN EFI_HANDLE DriverHandle
+);
+
+EFI_HII_KEYBOARD_LAYOUT* FindLayoutByGuid(
+ IN EFI_GUID *Guid
+);
+
+EFI_STATUS ParseKeyLayoutPackage(
+ IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package
+);
+
+EFI_STATUS DeleteKeyboardLayout(
+ IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package
+);
+
+EFI_STATUS ParseSimpleFontsPackage(
+ IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package
+);
+
+EFI_STATUS ParseFontsPackage(
+ IN EFI_HII_FONT_PACKAGE_HDR *Package
+);
+
+EFI_STATUS ParseStringsPackage(
+ PACKAGE_LIST_RECORD *PackageList,
+ IN EFI_HII_STRING_PACKAGE_HDR *Package
+);
+
+PACKAGE_LIST_RECORD* NewPackageListRecord(
+ VOID
+);
+
+NOTIFY_RECORD* NewNotifyRecord(
+ VOID
+);
+
+VOID* CreateNewLink(
+ UINT32 Size
+);
+
+VOID DeleteList(
+ DLIST *List
+);
+
+VOID DeleteStringsFromDatabase(DBE_DATABASE *Database);
+VOID DeleteSimpleFonts(IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package);
+
+UINT32 StrSize8(CHAR8 *String);
+
+UINT32 StrSize16(CHAR16 *String);
+
+VOID StrCpy8(CHAR8 *Dest, CHAR8 *Src);
+
+VOID StrCpy16(CHAR16 *Dest, CHAR16 *Src);
+
+INTN StrCmp8(CHAR8 *Dest, CHAR8 *Src);
+
+INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src);
+
+EFI_STATUS AddLanguage(
+ PACKAGE_LIST_RECORD *PackageList,
+ CHAR8 *Language,
+ CHAR16* LanguageName,
+ UINT16 LastStringId
+);
+
+EFI_STATUS GetLanguageId(
+ PACKAGE_LIST_RECORD *PackageList,
+ CHAR8 *Language,
+ UINT16 *LanguageId,
+ LANGUAGE_LINK **Found
+);
+
+EFI_STATUS AddString(
+ PACKAGE_LIST_RECORD *PackageList,
+ UINT16 LanguageId,
+ UINT16 StringId,
+ UINT16 FontId,
+ EFI_STRING String
+);
+
+EFI_STATUS ExtractStrings(
+ PACKAGE_LIST_RECORD *PackageList,
+ UINT16 LanguageId,
+ UINT16 *StringId,
+ UINT16 FontId,
+ UINT16 StringCount,
+ BOOLEAN Compressed,
+ VOID *StringBlock
+);
+
+BOOLEAN IsLineBreak(CHAR16 Char);
+
+BOOLEAN IsLineBreakOpp(CHAR16 Char);
+
+UINTN GetGlyphWidth(CHAR16 Char);
+
+UINTN GetLineLength(UINTN StartIndex, UINTN EndIndex);
+
+UINTN GetClipLineLength(
+ UINTN StartIndex,
+ UINTN MaxLength,
+ BOOLEAN ClipClean,
+ UINTN *EndIndex
+);
+
+UINTN GetWrapIndex(
+ UINTN StartIndex,
+ UINTN MaxLength,
+ UINTN *EndIndex,
+ UINTN *StartIndex2
+);
+
+UINTN GetMaxLineLength(VOID);
+
+EFI_STATUS SplitByLineBreaks(EFI_STRING String);
+
+EFI_STATUS AdjustLineSize(VOID);
+
+VOID DrawNarrowGlyph(
+ UINTN StartX,
+ UINTN StartY,
+ UINTN SizeX,
+ UINTN SizeY,
+ CHAR16 Char,
+ BOOLEAN Transparent,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt
+);
+
+VOID DrawWideGlyph(
+ UINTN StartX,
+ UINTN StartY,
+ UINTN SizeX,
+ UINTN SizeY,
+ CHAR16 Char,
+ BOOLEAN Transparent,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt
+);
+
+VOID Draw(VOID);
+
+BOOLEAN CheckPattern(CHAR16 *String, NAME_PATTERN *Pattern);
+
+EFI_STATUS ExtractConfigString(CHAR16 *String, UINTN *NextIndex, CHAR16 **NewString);
+
+BOOLEAN CheckDevicePath(
+ IN UINT8 *DevicePath,
+ IN UINTN DeviceLength,
+ IN EFI_HII_PACKAGE_HEADER *Package);
+
+EFI_STATUS SearchDevicePath(UINT8 *DevicePach, UINTN DpLength, EFI_HANDLE *Handle);
+
+EFI_STATUS ExtractDevicePath(CHAR16 *ConfigString, UINT8 **DevicePath, UINTN *DpLength);
+
+EFI_STATUS FindDeviceHandle(
+ IN CHAR16 *ConfigString,
+ OUT EFI_HANDLE *Handle);
+
+BOOLEAN IsHexDigit(CHAR16 Char);
+UINT8 HexValue(CHAR8 Char);
+
+VOID StringToBlock(
+ IN CHAR16 *String,
+ IN UINTN StringSize,
+ OUT UINT8 *Block);
+
+EFI_STATUS CollectResults(CHAR16 *Result, UINTN Symbols, RESULT_BLOCK *ResultBlock);
+
+UINT32 GetValue(CHAR16 *String, UINTN Start, UINTN End);
+
+EFI_STATUS GetPatternValue(
+ CHAR16 *String,
+ UINTN *Index,
+ NAME_PATTERN *Pattern,
+ UINT32 *Value);
+
+EFI_STATUS GetStringValue(
+ CHAR16 *String,
+ UINTN *Index,
+ UINT8 *Output,
+ UINT32 Width);
+
+EFI_STATUS ReallocResultString(UINTN NewSize, RESULT_BLOCK *ResultBlock);
+
+EFI_STATUS CollectValueResults(UINT8 *Value, UINT32 Width, RESULT_BLOCK *ResultBlock);
+
+EFI_STATUS InitResultBlock(RESULT_BLOCK *ResultBlock);
+
+VOID WriteSwappedBuffer(
+ OUT UINT8 *Output,
+ IN UINT8 *Input,
+ IN UINTN Size);
+
+EFI_STATUS LoadSystemFont();
+
+EFI_STATUS ExportPack(
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer,
+ IN BOOLEAN FirstCall
+);
+
+VOID StringToChar16(
+ IN CHAR16 *String,
+ IN OUT UINTN *Size,
+ OUT CHAR16 *Block
+);
+
+BOOLEAN CompareDevicePath(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+);
+
+BOOLEAN CompareName(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_STRING Name
+);
+
+BOOLEAN HiiCompareGuid(
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_GUID *Guid
+);
+
+EFI_STATUS CheckAltCfg (
+ IN EFI_STRING ConfigString,
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST EFI_STRING AltCfgId
+);
+
+EFI_STATUS SignalKbLayoutChangedEvent(
+ VOID
+);
+
+EFI_STATUS FillFontInfo(
+ IN EFI_FONT_HANDLE FontHandle,
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut
+);
+
+EFI_STATUS FindFont(
+ IN OUT EFI_FONT_HANDLE *FontHandle,
+ IN CHAR16 *FontName,
+ IN EFI_HII_FONT_STYLE FontStyle,
+ IN UINT16 FontSize,
+ IN FONT_MATCH_MASK Mask,
+ IN CONST EFI_STRING String
+);
+
+EFI_STATUS IntGetGlyph(
+ IN EFI_FONT_HANDLE Font,
+ IN CHAR16 Char,
+ OUT EFI_HII_GLYPH_INFO *Cell,
+ OUT UINT8 **GlyphBlock OPTIONAL,
+ OUT BOOLEAN *Free
+);
+
+VOID UpdateLineSize(
+ IN OUT DRAW_LINE *Line
+);
+
+VOID ClipLine(
+ IN OUT DRAW_LINE *Line,
+ IN UINTN Width,
+ IN BOOLEAN ClipClean
+);
+
+BOOLEAN CheckVisible(
+ IN OUT RECT_COORD *Glyph,
+ IN RECT_COORD *Image
+);
+
+VOID DrawGlyph(
+ IN UINTN StartX,
+ IN UINTN StartY,
+ IN UINTN SizeX,
+ IN UINTN SizeY,
+ IN UINT8 *GlyphBlock,
+ IN BOOLEAN Transparent,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt,
+ IN UINT16 CharWidth
+);
+
+VOID GetDrawImageSize(
+ OUT UINTN *Width,
+ OUT UINTN *Height
+);
+
+EFI_STATUS WrapLine(
+ IN OUT DRAW_LINE *Line,
+ IN UINTN Width
+);
+
+EFI_STATUS AddStringFont(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN UINT16 FontId,
+ IN UINT16 FontSize,
+ IN EFI_HII_FONT_STYLE FontStyle,
+ IN CHAR16 *FontName,
+ OUT UINT16 *NewFontId OPTIONAL
+);
+
+UINT16 GetAvailableFontId(
+ IN PACKAGE_LIST_RECORD *PackageList
+);
+
+EFI_STATUS FindStringFontInfoByTemplate(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN EFI_FONT_INFO *Template,
+ OUT UINT16 *FontId
+);
+
+EFI_STATUS FindStingFontInfoById(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN UINT16 FontId,
+ OUT EFI_FONT_INFO **Info
+);
+
+VOID CreateLanguageName(
+ IN CHAR8 *RfcName,
+ OUT CHAR16* OutName,
+ UINTN MaxSize
+);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//************************************************************************* \ No newline at end of file
diff --git a/Core/CORE_DXE/UefiHii/HiiString.c b/Core/CORE_DXE/UefiHii/HiiString.c
new file mode 100644
index 0000000..91f2708
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/HiiString.c
@@ -0,0 +1,1609 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiString.c 7 8/15/12 3:45p Artems $
+//
+// $Revision: 7 $
+//
+// $Date: 8/15/12 3:45p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiString.c $
+//
+// 7 8/15/12 3:45p Artems
+// [TAG] EIP96755
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Strings in new language added at runtime lost during export
+// [RootCause] Every language represented by its own string package.
+// When
+// strings of new language added at runtime, they're added to database,
+// but not to the list of packages. Export function is working with
+// list of packages, so new language strings will be missed
+// [Solution] Added code to create new string package at runtime when
+// new string
+// of new language is added to database
+// [Files] HiiPrivate.h HiiString.c
+//
+// 6 5/22/12 4:34p Artems
+// [TAG] EIP83593
+// [Category] New Feature
+// [Description] Proportional font support for Aptio
+// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c
+// UefiHii.h
+//
+//
+// 5 10/24/11 5:40p Artems
+// EIP 70530: Bug reported by SCT 2.3.1. Languages shold be compared
+// ignoring case
+//
+// 4 5/13/11 6:15p Artems
+// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and
+// AmiHiiSetString
+// to avoid collusion with EdkII native library functions
+//
+// 3 12/03/09 12:02p Aaronp
+// Fix for SCT GetSecondLanguages failures.
+//
+// 2 11/23/09 7:38p Felixp
+// HiiGetLanguages is updated to accept NULL language buffer when
+// *LanguagesSize is zero.
+//
+// 1 10/09/09 6:12p Felixp
+//
+// 1 2/27/09 3:55p Artems
+// Initial check-in
+//
+// 1 3/18/07 5:23p Felixp
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: HiiString.c
+//
+// Description: Hii string protocol functions implementation
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#pragma warning (disable : 4090)
+
+#include <AmiDxeLib.h>
+#include "HiiPrivate.h"
+
+#define DEFAULT_FONT 0x100
+#define INVALID_FONT_ID 0xFEFE
+
+extern HII_DATABASE_PRIVATE_DATA PrivateData;
+
+DBE_OFFSET_KEY_CONTEXT StringDbKeyContext = {EFI_FIELD_OFFSET(STRING_RECORD ,StringId), 4 };
+DBE_KEY_FIELD StringDbKeyField = OFFSET_KEY(StringDbKeyContext);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AmiHiiGetString
+//
+// Description:
+// This function is HII String protocol function GetString implementation
+//
+// Input:
+// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure
+// IN CHAR8 *Language - Language definition
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// IN EFI_STRING_ID StringId - String Id
+// OUT EFI_STRING String - Pointer to output string
+// IN OUT UINTN *StringSize - Pointer to string size value
+// OUT EFI_FONT_INFO *StringFontInfo - Pointer to returned string font info
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - String or StringSize or Language is NULL
+// EFI_NOT_FOUND - String not found
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiHiiGetString(
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN CONST CHAR8 *Language,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList;
+ STRING_RECORD DbKey;
+ INT8 Vicinity;
+ STRING_RECORD *Found;
+ UINTN *FindRecord;
+ UINT32 Size;
+ EFI_STATUS Status;
+ LANGUAGE_LINK *Ptr;
+ UINT32 i;
+ UINT16 SaveLanguage;
+
+ if (Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (String == NULL && *StringSize != 0)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ DbKey.StringId = StringId;
+ Status = GetLanguageId(Record, Language, &(DbKey.LanguageId), &Ptr);
+ if(EFI_ERROR(Status))
+ return EFI_INVALID_LANGUAGE;
+
+ Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+ if(EFI_ERROR(Status))
+ {
+ //string not found in database, try different languages
+ SaveLanguage = DbKey.LanguageId;
+ for(i = 0; i < Record->LanguageList.Size; i++)
+ {
+ if (i == SaveLanguage)
+ continue;
+ DbKey.LanguageId = (UINT16)i;
+ Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+ if(!EFI_ERROR(Status))
+ return EFI_INVALID_LANGUAGE; //string exists but with different language
+ }
+
+ return EFI_NOT_FOUND;
+ }
+
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+
+ Size = StrSize16(Found->String);
+
+ if(Size > *StringSize)
+ {
+ *StringSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ StrCpy16(String, Found->String);
+ *StringSize = Size;
+
+ if(StringFontInfo != NULL)
+ Status = FindStingFontInfoById(Record, Found->FontId, StringFontInfo);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AmiHiiSetString
+//
+// Description:
+// This function is HII String protocol function SetString implementation
+//
+// Input:
+// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// IN EFI_STRING_ID StringId - String Id
+// IN CHAR8 *Language - Language definition
+// IN EFI_STRING String - String to set
+// IN EFI_FONT_INFO *StringFontInfo - Pointer to string font info
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - String or Language is NULL
+// EFI_NOT_FOUND - String not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiHiiSetString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList;
+ STRING_RECORD DbKey;
+ INT8 Vicinity;
+ STRING_RECORD *Found;
+ UINTN *FindRecord;
+ UINT32 i;
+ UINT16 SaveLanguage;
+ LANGUAGE_LINK *Ptr;
+ EFI_STATUS Status;
+
+ if(String == NULL || Language == NULL || PackageList == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ DbKey.StringId = StringId;
+ Status = GetLanguageId(Record, Language, &(DbKey.LanguageId), &Ptr);
+
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+ if(!EFI_ERROR(Status))
+ { //updated string found in database - retreive font info
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ DbKey.FontId = Found->FontId;
+ DbeDelete(&(Record->StringDb), Found, TRUE);
+ }
+ else //try same StringId with different languages
+ {
+ SaveLanguage = DbKey.LanguageId;
+ for(i = 0; i < Record->LanguageList.Size; i++)
+ {
+ if (i == SaveLanguage)
+ continue;
+ DbKey.LanguageId = i;
+ Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+ if(!EFI_ERROR(Status))
+ break;
+ }
+ if(i == Record->LanguageList.Size)
+ return EFI_NOT_FOUND;
+
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ DbKey.FontId = Found->FontId;
+ DbKey.LanguageId = SaveLanguage;
+ }
+
+ if(StringFontInfo != NULL) {
+ Status = FindStringFontInfoByTemplate(Record, StringFontInfo, &DbKey.FontId);
+ if(EFI_ERROR(Status)) {
+ Status = AddStringFont(Record, INVALID_FONT_ID, StringFontInfo->FontSize,
+ StringFontInfo->FontStyle, StringFontInfo->FontName, &DbKey.FontId);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ }
+
+ Status = AddString(Record, DbKey.LanguageId, DbKey.StringId, DbKey.FontId, String);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiNewString
+//
+// Description:
+// This function is HII String protocol function NewString implementation
+//
+// Input:
+// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// OUT EFI_STRING_ID *StringId - Pointer to returned string Id
+// IN CHAR8 *Language - Language definition
+// IN CHAR16 *LanguageName - Language human readable name
+// IN EFI_STRING String - String to set
+// IN EFI_FONT_INFO *StringFontInfo - Pointer to string font info
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - String or Language or StringId is NULL
+// EFI_NOT_FOUND - Package list handle is invalid
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiNewString (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ OUT EFI_STRING_ID *StringId,
+ IN CONST CHAR8 *Language,
+ IN CONST CHAR16 *LanguageName OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST EFI_FONT_INFO *StringFontInfo)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList;
+ EFI_STATUS Status;
+ UINT16 LanguageId;
+ LANGUAGE_LINK *Link;
+ UINT16 FontId;
+ CHAR16 DefaultName[80];
+
+ if(String == NULL || StringId == NULL || Language == NULL || PackageList == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ Status = GetLanguageId(Record, Language, &LanguageId, &Link);
+ if(EFI_ERROR(Status))
+ {
+ Status = AddLanguage(Record, Language, LanguageName, 0);
+ if(EFI_ERROR(Status))
+ return Status;
+ Status = GetLanguageId(Record, Language, &LanguageId, &Link);
+ //language added, now add language name string to database
+ if(LanguageName == NULL) {
+ CreateLanguageName(Language, DefaultName, 80 * sizeof(CHAR16));
+ LanguageName = DefaultName;
+ }
+ //at this point LastStringId has value LanguageName + 1
+ Status = AmiHiiSetString(This, PackageList, Link->LastStringId - 1, Language, LanguageName, NULL);
+ }
+
+ if(StringFontInfo != NULL) {
+ Status = FindStringFontInfoByTemplate(Record, StringFontInfo, &FontId);
+ if(EFI_ERROR(Status)) {
+ Status = AddStringFont(Record, INVALID_FONT_ID, StringFontInfo->FontSize,
+ StringFontInfo->FontStyle, StringFontInfo->FontName, &FontId);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ } else {
+ FontId = DEFAULT_FONT;
+ }
+
+ Status = AddString(Record, LanguageId, Link->LastStringId, FontId, String);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ *StringId = Link->LastStringId;
+
+ Link->LastStringId++;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetLanguages
+//
+// Description:
+// This function is HII String protocol function GetLanguages implementation
+//
+// Input:
+// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// IN OUT CHAR8 *Languages - Pointer to returned language buffer
+// IN OUT UINTN *LanguagesSize - Pointer to language buffer size
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - LanguagesSize or Languages is NULL
+// EFI_NOT_FOUND - Package list handle is invalid or NULL
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetLanguages (
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN OUT CHAR8 *Languages,
+ IN OUT UINTN *LanguagesSize
+)
+{
+ PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList;
+// EFI_STATUS Status;
+ LANGUAGE_LINK *Link;
+ UINTN Size = 0;
+
+ if(PackageList == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE)
+ return EFI_NOT_FOUND;
+
+ if(LanguagesSize == NULL || Languages == NULL && *LanguagesSize != 0)
+ return EFI_INVALID_PARAMETER;
+
+ if(Record->LanguageList.Size == 0)
+ {
+ *LanguagesSize = 0;
+ *Languages = 0;
+ return EFI_SUCCESS;
+ }
+
+ Link = (LANGUAGE_LINK *)Record->LanguageList.pHead;
+ while(Link != NULL)
+ {
+ Size += StrSize8(Link->Language);
+ Link = (LANGUAGE_LINK *)Link->Link.pNext;
+ }
+
+ if(Size > *LanguagesSize)
+ {
+ *LanguagesSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *LanguagesSize = Size;
+
+ Link = (LANGUAGE_LINK *)Record->LanguageList.pHead;
+ while(Link != NULL)
+ {
+ Size = StrSize8(Link->Language);
+ Size--; //skip NULL-terminator
+ MemCpy(Languages, Link->Language, Size);
+ Languages += Size; //shift pointer
+ *Languages = ';'; //add delimiter
+ Languages++;
+ Link = (LANGUAGE_LINK *)Link->Link.pNext;
+ }
+
+ Languages--; //change delimiter to NULL-terminator
+ *Languages = 0;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HiiGetSecondLanguages
+//
+// Description:
+// This function is HII String protocol function GetSecondaryLanguages implementation
+//
+// Input:
+// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// IN CHAR8 *FirstLanguage - First language definition
+// IN OUT CHAR8 *Languages - Pointer to returned language buffer
+// IN OUT UINTN *LanguagesSize - Pointer to language buffer size
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_INVALID_PARAMETER - LanguagesSize or Languages is NULL
+// EFI_NOT_FOUND - Package list handle is invalid or NULL
+// EFI_BUFFER_TOO_SMALL - Allocated buffer too small
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HiiGetSecondLanguages(
+ IN CONST EFI_HII_STRING_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageList,
+ IN CONST CHAR8 *FirstLanguage,
+ IN OUT CHAR8 *SecondLanguages,
+ IN OUT UINTN *SecondLanguagesSize
+)
+{
+ EFI_STATUS Status;
+ UINTN Size = 0;
+ UINTN i = 0;
+
+ CHAR8 *Langs = NULL;
+
+ if(FirstLanguage == NULL || SecondLanguages == NULL || SecondLanguagesSize == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ // Get the size of all the languages in the Hii Package
+ Status = HiiGetLanguages(This, PackageList, NULL, &Size);
+
+ if(EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL)
+ return Status;
+
+ // Allocate space for the languages
+ Status = pBS->AllocatePool(EfiBootServicesData, Size, &Langs);
+
+ if(!EFI_ERROR(Status))
+ // Get the langues into the temp buffer
+ Status = HiiGetLanguages(This, PackageList, Langs, &Size);
+
+ // find and remove the primary language from the string
+ if(!EFI_ERROR(Status))
+ {
+ Status = EFI_INVALID_LANGUAGE;
+
+ for(; i < Size; i++)
+ {
+ // check if the current offset matches the first language
+ if(MemCmp(Langs+i,FirstLanguage,StrSize8(FirstLanguage)-1) == 0)
+ {
+ Status = EFI_SUCCESS;
+
+ // copy the rest of the string on top of the primary strings location
+ pBS->CopyMem(Langs+i,Langs+i+StrSize8(FirstLanguage),StrSize8(Langs)-i-StrSize8(FirstLanguage));
+ break;
+ }
+ }
+ }
+
+ if(!EFI_ERROR(Status))
+ {
+ Status = EFI_BUFFER_TOO_SMALL;
+
+ // Check if the buffer is large enough to fit the secondary langues
+ if(*SecondLanguagesSize >= StrSize8(Langs))
+ {
+ Status = EFI_SUCCESS;
+ MemCpy(SecondLanguages, Langs, StrSize8(Langs));
+ }
+
+ // fill in the size of the secondary langauges
+ *SecondLanguagesSize = StrSize8(Langs);
+ }
+
+ if(Langs != NULL)
+ pBS->FreePool(Langs);
+
+ return Status;
+}
+
+// *************************** Service functions (not for public use) ************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateLanguageName
+//
+// Description:
+// This function creates human-readable language name from RFC name
+//
+// Input:
+// IN CHAR8 *RfcName - pointer to RFC name
+// OUT CHAR16* OutName - pointer where to store human-readable name
+// UINTN MaxSize - max size of output buffer in bytes
+//
+// Output:
+// UINT16 - number of strings in package
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID CreateLanguageName(
+ IN CHAR8 *RfcName,
+ OUT CHAR16* OutName,
+ UINTN MaxSize)
+{
+ UINTN i;
+
+ for(i = 0; (RfcName[i] != 0 && i < (MaxSize / 2 - 1)); i++)
+ OutName[i] = RfcName[i];
+ OutName[i] = 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddStringPackage
+//
+// Description:
+// This function creates string package for language not existed in package list
+// at the time of submission to database
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs
+// IN CHAR8 *Language - Language RFC name
+//
+// Output:
+// UINT16 - number of strings in package
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 AddStringPackage(
+ PACKAGE_LIST_RECORD *PackageList,
+ CHAR8 *Language)
+{
+ UINT32 Size;
+ PACKAGE_LINK *Template;
+ PACKAGE_LINK *NewLink;
+ DLIST *PackList;
+ UINT16 LanguageStringId;
+ UINT32 i;
+ EFI_HII_STRING_PACKAGE_HDR *Hdr;
+ EFI_HII_STRING_PACKAGE_HDR *NewHdr;
+
+ PackList = &(PackageList->PackageList);
+ Template = (PACKAGE_LINK *)PackList->pHead;
+ while(Template != NULL) {
+ if(Template->Package.Type == EFI_HII_PACKAGE_STRINGS)
+ break;
+ Template = (PACKAGE_LINK *)Template->Link.pNext;
+ }
+
+ if(Template == NULL) {//no string packages in this package list
+ LanguageStringId = 1;
+ } else {
+ Hdr = (EFI_HII_STRING_PACKAGE_HDR *)&(Template->Package);
+ LanguageStringId = Hdr->LanguageName;
+ }
+
+ Size = sizeof(EFI_HII_STRING_PACKAGE_HDR) - 1;
+ Size += StrSize8(Language);
+
+ NewLink = (PACKAGE_LINK *) CreateNewLink(Size);
+ if(NewLink == NULL)
+ return 0;
+
+ NewLink->Package.Type = EFI_HII_PACKAGE_STRINGS;
+ NewLink->Package.Length = Size; //this is technically incorrect, but it will be updated upon export
+ NewHdr = (EFI_HII_STRING_PACKAGE_HDR *)&(NewLink->Package);
+ NewHdr->HdrSize = Size;
+ NewHdr->StringInfoOffset = Size;
+ if(Template == NULL) {
+ for(i = 0; i < 16; i++)
+ NewHdr->LanguageWindow[i] = 0;
+ } else {
+ for(i = 0; i < 16; i++)
+ NewHdr->LanguageWindow[i] = Hdr->LanguageWindow[i];
+ }
+ NewHdr->LanguageName = LanguageStringId;
+ StrCpy8(NewHdr->Language, Language);
+ DListAdd(PackList, (DLINK *)NewLink);
+ return LanguageStringId + 1;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddLanguage
+//
+// Description:
+// This function adds language to private HII database
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs
+// IN EFI_HII_HANDLE PackageList - Handle of package list
+// IN CHAR8 *Language - Language Id
+// IN CHAR16 *LanguageName - Pointer to human readable language name
+// IN UINT16 LastStringId - Last string Id on this language
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddLanguage(
+ PACKAGE_LIST_RECORD *PackageList,
+ CHAR8 *Language,
+ CHAR16* LanguageName,
+ UINT16 LastStringId)
+{
+ UINT32 Size1, Size2 = 0;
+ LANGUAGE_LINK *Link;
+ CHAR16 DefaultName[80];
+ UINT8 *Ptr;
+
+ Size1 = StrSize8(Language);
+
+ if(LanguageName == NULL) {
+ CreateLanguageName(Language, DefaultName, 80 * sizeof(CHAR16));
+ LanguageName = DefaultName;
+ }
+
+ Size2 = StrSize16(LanguageName);
+
+ Link = (LANGUAGE_LINK *)CreateNewLink(Size1 + Size2 + sizeof(UINT32));
+ if(Link == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ if(LastStringId != 0) {
+ Link->LastStringId = LastStringId;
+ } else {
+ //we're adding language, that wasn't in package list from the start
+ Link->LastStringId = AddStringPackage(PackageList, Language);
+ if(Link->LastStringId == 0)
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrCpy8(Link->Language, Language);
+
+ Ptr = (UINT8 *)Link->Language;
+ Ptr += Size1;
+ StrCpy16((CHAR16 *)Ptr, LanguageName);
+
+ DListAdd(&(PackageList->LanguageList), (DLINK *)Link);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetLanguageId
+//
+// Description:
+// This function returns language private Id which corresponds with given language Id
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs
+// IN CHAR8 *Language - Language Id
+// OUT UINT16 *LanguageId - Pointer where to return private Id
+// OUT LANGUAGE_LINK **Found - Pointer where to return found language private data
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_NOT_FOUND - language not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetLanguageId(
+ PACKAGE_LIST_RECORD *PackageList,
+ CHAR8 *Language,
+ UINT16 *LanguageId,
+ LANGUAGE_LINK **Found OPTIONAL)
+{
+ LANGUAGE_LINK *Link = (LANGUAGE_LINK *)PackageList->LanguageList.pHead;
+ UINT8 Id;
+
+ Id = 0;
+ while(Link != NULL)
+ {
+ if(LanguageCodesEqual(Language, Link->Language))
+ {
+ *LanguageId = Id;
+
+ if(Found)
+ *Found = Link;
+
+ return EFI_SUCCESS;
+ }
+ Link = (LANGUAGE_LINK *)Link->Link.pNext;
+ Id++;
+ }
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddString
+//
+// Description:
+// This function adds string to private storage
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where string belongs
+// IN UINT16 LanguageId - Private language Id of the string
+// IN UINT16 StringId - Private string Id of the string
+// IN UINT16 FontId - Private font Id of the string
+// IN EFI_STRING String - String to add
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddString(
+ PACKAGE_LIST_RECORD *PackageList,
+ UINT16 LanguageId,
+ UINT16 StringId,
+ UINT16 FontId,
+ EFI_STRING String)
+{
+ STRING_RECORD *Record;
+ UINT32 Size;
+ EFI_STATUS Status;
+
+ Size = StrSize16(String);
+
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ Size + 6,
+ &Record);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ Record->FontId = FontId;
+ Record->LanguageId = LanguageId;
+ Record->StringId = StringId;
+ StrCpy16(Record->String, String);
+
+ DbeInsert(&(PackageList->StringDb), Record);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ParseStringsPackage
+//
+// Description:
+// This function parses string package
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where string package belongs
+// IN EFI_HII_STRING_PACKAGE_HDR *Package - Pointer to package to parse
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_ERROR - Some error occured during execution
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ParseStringsPackage(
+ PACKAGE_LIST_RECORD *PackageList,
+ IN EFI_HII_STRING_PACKAGE_HDR *Package)
+{
+ EFI_STATUS Status;
+ LANGUAGE_LINK *Link;
+ UINT16 LanguageId;
+ UINT16 StringId;
+ UINT16 FontId;
+ EFI_HII_STRING_BLOCK *ParsePointer;
+ UINT16 StringCount;
+ STRING_RECORD DbKey;
+ INT8 Vicinity;
+ STRING_RECORD *Found;
+ UINTN *FindRecord;
+ BOOLEAN NewLanguage = FALSE;
+ CHAR16 *FontName;
+
+ ParsePointer = (EFI_HII_STRING_BLOCK *)Package;
+ (UINT8 *)ParsePointer += Package->StringInfoOffset;
+
+ Status = GetLanguageId(PackageList, Package->Language, &LanguageId, &Link);
+ if(EFI_ERROR(Status))
+ {
+ LanguageId = (UINT16)PackageList->LanguageList.Size;
+ StringId = 1;
+ NewLanguage = TRUE;
+ }
+ else
+ StringId = Link->LastStringId;
+
+ while(ParsePointer->BlockType != EFI_HII_SIBT_END)
+ {
+ switch(ParsePointer->BlockType)
+ {
+ case EFI_HII_SIBT_SKIP1:
+ StringId += ((EFI_HII_SIBT_SKIP1_BLOCK *)ParsePointer)->SkipCount;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_SKIP1_BLOCK);
+ break;
+ case EFI_HII_SIBT_SKIP2:
+ StringId += ((EFI_HII_SIBT_SKIP2_BLOCK *)ParsePointer)->SkipCount;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK);
+ break;
+ case EFI_HII_SIBT_EXT1:
+ (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT1_BLOCK *)ParsePointer)->Length;
+ break;
+ case EFI_HII_SIBT_EXT2:
+ (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT2_BLOCK *)ParsePointer)->Length;
+ break;
+ case EFI_HII_SIBT_EXT4:
+ (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT4_BLOCK *)ParsePointer)->Length;
+ break;
+ case EFI_HII_SIBT_FONT:
+ FontName = (CHAR16 *)((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer + 1);
+ Status = AddStringFont(PackageList,
+ ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontId,
+ ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontSize,
+ ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontStyle,
+ FontName, NULL);
+ if(EFI_ERROR(Status))
+ return Status;
+ (UINT8 *)ParsePointer += ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->Header.Length;
+ break;
+ case EFI_HII_SIBT_STRING_SCSU:
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_SCSU_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT,
+ 1, TRUE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ FontId = ((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ParsePointer)->FontIdentifier;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId,
+ 1, TRUE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ StringCount = ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ParsePointer)->StringCount;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_SCSU_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT,
+ StringCount, TRUE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ StringCount = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ParsePointer)->StringCount;
+ FontId = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ParsePointer)->FontIdentifier;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId,
+ StringCount, TRUE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ case EFI_HII_SIBT_STRING_UCS2:
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT,
+ 1, FALSE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ FontId = ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *)ParsePointer)->FontIdentifier;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId,
+ 1, FALSE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ StringCount = ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *)ParsePointer)->StringCount;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_UCS2_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT,
+ StringCount, FALSE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ break;
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ StringCount = ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ParsePointer)->StringCount;
+ FontId = ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ParsePointer)->FontIdentifier;
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK);
+ Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId,
+ StringCount, TRUE, &ParsePointer);
+ if(EFI_ERROR(Status))
+ return Status;
+ case EFI_HII_SIBT_DUPLICATE:
+ DbKey.LanguageId = LanguageId;
+ DbKey.StringId = ((EFI_HII_SIBT_DUPLICATE_BLOCK *)ParsePointer)->StringId;
+ Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+ if(!EFI_ERROR(Status))
+ {
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ Status = AddString(PackageList, Found->LanguageId, StringId, Found->FontId, Found->String);
+ if(EFI_ERROR(Status))
+ return Status;
+ StringId++;
+ }
+ (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_DUPLICATE_BLOCK);
+ break;
+ default:
+ break;
+ }
+ }
+
+//Reconstruct full language name
+
+ if(NewLanguage)
+ {
+ DbKey.LanguageId = LanguageId;
+ DbKey.StringId = Package->LanguageName;
+ Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL);
+
+ if(!EFI_ERROR(Status))
+ {
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ Status = AddLanguage(PackageList, Package->Language, Found->String, StringId);
+ }
+ else
+ Status = AddLanguage(PackageList, Package->Language, NULL, StringId);
+
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+ else
+ Link->LastStringId = StringId;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ExtractStrings
+//
+// Description:
+// This function extracts strings from given block of strings
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong
+// IN UINT16 LanguageId - Private language Id
+// IN OUT UINT16 *StringId - Pointer to string Id
+// IN UINT16 FontId - Font Id
+// IN UINT16 StringCount - Number of strings to extract
+// IN BOOLEAN Compressed - Flag, that determines whether string is compressed or not
+// IN OUT VOID **StringBlock - Pointer to block of strings to extract
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_ERROR - Some error occured during execution
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ExtractStrings(
+ PACKAGE_LIST_RECORD *PackageList,
+ UINT16 LanguageId,
+ UINT16 *StringId,
+ UINT16 FontId,
+ UINT16 StringCount,
+ BOOLEAN Compressed,
+ VOID **StringBlock
+)
+{
+ UINT16 i;
+ EFI_STATUS Status;
+ UINT32 StringSize;
+ UINT32 MaxSize = 0x100;
+ CHAR16 *String = NULL;
+ VOID *Pointer = *StringBlock;
+
+ if(Compressed)
+ {
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * MaxSize,
+ &String);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+
+ for(i = 0; i < StringCount; i++)
+ {
+ if(Compressed)
+ {
+ StringSize = StrSize8((CHAR8 *)Pointer);
+ if(StringSize > MaxSize)
+ {
+ MaxSize = StringSize;
+ pBS->FreePool(String);
+ Status = pBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(CHAR16) * MaxSize,
+ &String);
+ if(EFI_ERROR(Status))
+ return Status;
+ }
+// UncompressString(String, (CHAR8 *)Pointer);
+ Status = AddString(PackageList, LanguageId, *StringId, FontId, String);
+ }
+ else
+ {
+ StringSize = StrSize16(Pointer);
+ Status = AddString(PackageList, LanguageId, *StringId, FontId, (EFI_STRING)Pointer);
+ }
+
+ if(EFI_ERROR(Status))
+ return Status;
+ (*StringId)++;
+ (UINT8 *)Pointer += StringSize;
+ }
+ *StringBlock = Pointer;
+ if(String != NULL)
+ pBS->FreePool(String);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStringBlockSize
+//
+// Description:
+// This function determines block size needed to pack strings into string package
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong
+// IN CHAR8 *Language - Language Id
+//
+// Output:
+// UINTN - String block size in bytes
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINTN GetStringBlockSize(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN CHAR8 *Language)
+{
+ STRING_RECORD DbKey;
+ INT8 Vicinity;
+ STRING_RECORD *Found;
+ UINTN *FindRecord;
+ EFI_STATUS Status;
+ UINTN RecordIndex;
+ DBE_DATABASE *Database = &(PackageList->StringDb);
+ UINT16 StringCounter = 0;
+ UINT16 SkipBlock = 0; //number of skip blocks to add to string block
+ UINT16 CurrentStringId;
+ UINTN Size = 0;
+ UINTN i;
+
+ Status = GetLanguageId(PackageList, Language, &(DbKey.LanguageId), NULL);
+ if(EFI_ERROR(Status))
+ return 0;
+
+ DbKey.StringId = 1; //find first string with given language
+ Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, &RecordIndex);
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ if(EFI_ERROR(Status))
+ { //there isn't string with string id = 1
+ if(Found->LanguageId != DbKey.LanguageId) //we got string from previous language
+ {
+ RecordIndex++;
+ Status = DbeGoToIndex(&(PackageList->StringDb), 0, RecordIndex, &Found);
+ }
+ SkipBlock++; //at least one skip block should be added as far as we don't have string with id=1
+ }
+ CurrentStringId = Found->StringId;
+ Size += StrSize16(Found->String);
+ StringCounter++;
+
+ for(i = RecordIndex + 1;
+ (i < PackageList->StringDb.RecordCount) && (Found->LanguageId == DbKey.LanguageId);
+ i++)
+ {
+ Status = DbeGoToIndex(&(PackageList->StringDb), 0, i, &Found);
+ Size += StrSize16(Found->String);
+ StringCounter++;
+ if(Found->StringId > (CurrentStringId + 1))
+ SkipBlock++;
+ CurrentStringId = Found->StringId;
+ }
+
+ Size += SkipBlock * sizeof(EFI_HII_SIBT_SKIP2_BLOCK);
+ Size += StringCounter * sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ Size += sizeof(EFI_HII_SIBT_END_BLOCK);
+
+ return Size;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStringBlock
+//
+// Description:
+// This function packs strings from private storage into string package format
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong
+// IN CHAR8 *Language - Language Id
+// OUT UINT8 *Buffer - Pointer to output buffer
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetStringBlock(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN CHAR8 *Language,
+ IN UINT8 *Buffer)
+{
+ STRING_RECORD DbKey;
+ INT8 Vicinity;
+ STRING_RECORD *Found;
+ UINTN *FindRecord;
+ EFI_STATUS Status;
+ UINTN RecordIndex;
+ DBE_DATABASE *Database = &(PackageList->StringDb);
+ UINT16 StringCounter = 0;
+ UINT16 SkipBlock = 0; //number of skip blocks to add to string block
+ UINT16 CurrentStringId = 1;
+ UINTN Size = 0;
+ UINTN i;
+
+ Status = GetLanguageId(PackageList, Language, &(DbKey.LanguageId), NULL);
+
+ DbKey.StringId = 1; //find first string with given language
+ Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, &RecordIndex);
+ Found = (STRING_RECORD *)(UINTN)(*FindRecord);
+ if(EFI_ERROR(Status))
+ { //there isn't string with string id = 1
+ if(Found->LanguageId != DbKey.LanguageId) //we got string from previous language
+ {
+ RecordIndex++;
+ Status = DbeGoToIndex(&(PackageList->StringDb), 0, RecordIndex, &Found);
+ }
+
+ ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->SkipCount = Found->StringId - CurrentStringId - 1;
+ ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_SKIP2;
+ Buffer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK);
+ }
+ CurrentStringId = Found->StringId;
+ ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
+ Buffer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ Size = StrSize16(Found->String);
+ StrCpy16((CHAR16 *)Buffer, Found->String);
+ Buffer += Size;
+
+ for(i = RecordIndex + 1;
+ (i < PackageList->StringDb.RecordCount) && (Found->LanguageId == DbKey.LanguageId);
+ i++)
+ {
+ Status = DbeGoToIndex(&(PackageList->StringDb), 0, i, &Found);
+
+ if(Found->StringId > (CurrentStringId + 1)) //add skip block
+ {
+ ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->SkipCount = Found->StringId - CurrentStringId - 1;
+ ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_SKIP2;
+ Buffer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK);
+ }
+
+ ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
+ Buffer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK);
+ Size = StrSize16(Found->String);
+ StrCpy16((CHAR16 *)Buffer, Found->String);
+ Buffer += Size;
+ CurrentStringId = Found->StringId;
+ }
+ ((EFI_HII_SIBT_END_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_END;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateStringPackages
+//
+// Description:
+// This function updates string package with strings contained in private storage
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - Handle of package list to update
+//
+// Output:
+// EFI_SUCCESS - Function executed successfully
+// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS UpdateStringPackages(EFI_HII_HANDLE Handle)
+{
+ DLIST *PackageList;
+ PACKAGE_LINK *Link;
+ PACKAGE_LINK *NewLink;
+ EFI_HII_STRING_PACKAGE_HDR *StringPackage;
+ UINT8 *Buffer;
+ UINTN Size;
+
+ PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList);
+ Link = (PACKAGE_LINK *)(PackageList->pHead);
+
+ while(Link != NULL)
+ {
+ if(Link->Package.Type == EFI_HII_PACKAGE_STRINGS)
+ {
+ StringPackage = (EFI_HII_STRING_PACKAGE_HDR *) &(Link->Package);
+ Size = GetStringBlockSize((PACKAGE_LIST_RECORD *)Handle, StringPackage->Language);
+
+ if(Size != 0)
+ {
+ Size += StringPackage->HdrSize;
+ NewLink = (PACKAGE_LINK *) CreateNewLink((UINT32)Size);
+ if(NewLink == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ MemCpy((VOID *) &(NewLink->Package),
+ (VOID *) &(Link->Package),
+ StringPackage->HdrSize);
+ NewLink->Package.Length = (UINT32)Size;
+ Buffer = (UINT8 *) &(NewLink->Package);
+ Buffer += StringPackage->HdrSize;
+
+ GetStringBlock((PACKAGE_LIST_RECORD *)Handle, StringPackage->Language, Buffer);
+
+ DListInsert(PackageList, (DLINK *)NewLink, (DLINK *)Link);
+ DListDelete(PackageList, (DLINK *)Link);
+ pBS->FreePool(Link);
+ Link = NewLink;
+ }
+ }
+ Link = (PACKAGE_LINK *)Link->Link.pNext;
+ }
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrSize8
+//
+// Description:
+// This function returns ASCII string size in bytes
+//
+// Input:
+// IN CHAR8 *String - Pointer to string
+//
+// Output:
+// UINT32 - Size of string in bytes including nul-terminator
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 StrSize8(CHAR8 *String)
+{
+ UINT32 Size = 1;
+ while(*String++)
+ Size++;
+ return Size;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrSize16
+//
+// Description:
+// This function returns UNICODE string size in bytes
+//
+// Input:
+// IN CHAR16 *String - Pointer to string
+//
+// Output:
+// UINT32 - Size of string in bytes including nul-terminator
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 StrSize16(CHAR16 *String)
+{
+ UINT32 Size = 2;
+ while(*String++)
+ Size += 2;
+ return Size;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrCpy8
+//
+// Description:
+// This function copies one ASCII string into another
+//
+// Input:
+// IN CHAR8 *Dest - Pointer to destination string
+// IN CHAR8 *Src - Pointer to source string
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID StrCpy8(CHAR8 *Dest, CHAR8 *Src)
+{
+ MemCpy(Dest, Src, StrSize8(Src));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrCpy16
+//
+// Description:
+// This function copies one UNICODE string into another
+//
+// Input:
+// IN CHAR16 *Dest - Pointer to destination string
+// IN CHAR16 *Src - Pointer to source string
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID StrCpy16(CHAR16 *Dest, CHAR16 *Src)
+{
+ MemCpy(Dest, Src, StrSize16(Src));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrCmp8
+//
+// Description:
+// This function compares two ASCII strings
+//
+// Input:
+// IN CHAR8 *Dest - Pointer to destination string
+// IN CHAR8 *Src - Pointer to source string
+//
+// Output:
+// INTN - Zero if strings are equal, non-zero otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN StrCmp8(CHAR8 *Dest, CHAR8 *Src)
+{
+ return MemCmp(Dest, Src, StrSize8(Src));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrCmp16
+//
+// Description:
+// This function compares two UNICODE strings
+//
+// Input:
+// IN CHAR16 *Dest - Pointer to destination string
+// IN CHAR16 *Src - Pointer to source string
+//
+// Output:
+// INTN - Zero if strings are equal, non-zero otherwise
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src)
+{
+ return MemCmp(Dest, Src, StrSize16(Src));
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetAvailableFontId
+//
+// Description:
+// This function returns available font ID number
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs
+//
+// Output:
+// UINT16 - font ID number
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16 GetAvailableFontId(
+ IN PACKAGE_LIST_RECORD *PackageList
+)
+{
+ UINT16 Id = 0;
+ STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead;
+ while(Link != NULL) {
+ Id = (Link->FontId > Id) ? Link->FontId : Id;
+ Link = (STRING_FONT_LINK *)Link->Link.pNext;
+ }
+ return Id + 1;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindStringFontInfoByTemplate
+//
+// Description:
+// This function searches available fonts and returns font ID if match found
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs
+// IN EFI_FONT_INFO *Template - pointer to font description
+// OUT UINT16 *FontId - pointer where to return font ID
+//
+// Output:
+// EFI_SUCCESS - font found
+// EFI_NOT_FOUND - font not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindStringFontInfoByTemplate(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN EFI_FONT_INFO *Template,
+ OUT UINT16 *FontId
+)
+{
+ STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead;
+ EFI_FONT_INFO *Info;
+
+ while(Link != NULL) {
+ Info = (EFI_FONT_INFO *)(Link + 1);
+ if(!MemCmp(Info, Template, Link->FontInfoSize)) {
+ *FontId = Link->FontId;
+ return EFI_SUCCESS;
+ }
+ Link = (STRING_FONT_LINK *)Link->Link.pNext;
+ }
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindStingFontInfoById
+//
+// Description:
+// This function searches available fonts and returns font description if match found
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs
+// IN UINT16 FontId - font ID to find
+// OUT EFI_FONT_INFO **Info - pointer where to store pointer to font description
+//
+// Output:
+// EFI_SUCCESS - font found
+// EFI_NOT_FOUND - font not found
+// EFI_OUT_OF_RESOURCES - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindStingFontInfoById(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN UINT16 FontId,
+ OUT EFI_FONT_INFO **Info
+)
+{
+ static CHAR16 DefaultFontName[] = L"System font";
+ STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead;
+ UINTN StrSize;
+ EFI_STATUS Status;
+
+ while(Link != NULL) {
+ if(Link->FontId == FontId) {
+ Status = pBS->AllocatePool(EfiBootServicesData, Link->FontInfoSize, Info);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ MemCpy(*Info, (VOID *)(Link + 1), Link->FontInfoSize);
+ return EFI_SUCCESS;
+ }
+ Link = (STRING_FONT_LINK *)Link->Link.pNext;
+ }
+//font not found, return default font
+ StrSize = Wcslen(DefaultFontName) * sizeof(CHAR16);
+ Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_FONT_INFO) + StrSize, Info);
+ if(!EFI_ERROR(Status)) {
+ (*Info)->FontSize = EFI_GLYPH_HEIGHT;
+ (*Info)->FontStyle = EFI_HII_FONT_STYLE_NORMAL;
+ Wcscpy((*Info)->FontName, DefaultFontName);
+ }
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddStringFont
+//
+// Description:
+// This function adds font to font database and assigns font ID if latter was
+// not supplied
+//
+// Input:
+// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs
+// IN UINT16 FontId - font ID
+// IN UINT16 FontSize - font size
+// IN EFI_HII_FONT_STYLE FontStyle - font style
+// IN CHAR16 *FontName - pointer to font name
+// OUT UINT16 *NewFontId OPTIONAL - pointer where to store assigned font ID
+//
+// Output:
+// EFI_SUCCESS - font found
+// EFI_NOT_FOUND - font not found
+// EFI_OUT_OF_RESOURCES - not enough memory to perform operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AddStringFont(
+ IN PACKAGE_LIST_RECORD *PackageList,
+ IN UINT16 FontId,
+ IN UINT16 FontSize,
+ IN EFI_HII_FONT_STYLE FontStyle,
+ IN CHAR16 *FontName,
+ OUT UINT16 *NewFontId OPTIONAL
+)
+{
+ UINT16 Fid;
+ UINT32 FontNameSize;
+ STRING_FONT_LINK *AddLink;
+ EFI_FONT_INFO *FontInfo;
+
+ Fid = (FontId == INVALID_FONT_ID) ? GetAvailableFontId(PackageList) : FontId;
+
+ FontNameSize = (UINT32)((Wcslen(FontName)) * sizeof(CHAR16)); //null-terminator already accounted for in EFI_FONT_INFO structure
+ AddLink = CreateNewLink((UINT32)(sizeof(STRING_FONT_LINK) + sizeof(EFI_FONT_INFO)) + FontNameSize);
+ if(AddLink == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ AddLink->FontId = Fid;
+ AddLink->FontInfoSize = (UINT32)sizeof(EFI_FONT_INFO) + FontNameSize;
+ FontInfo = (EFI_FONT_INFO *)(AddLink + 1);
+ FontInfo->FontSize = FontSize;
+ FontInfo->FontStyle = FontStyle;
+ Wcscpy(FontInfo->FontName, FontName);
+ DListAdd(&(PackageList->StringFontList), (DLINK *)AddLink);
+ if(NewFontId)
+ *NewFontId = Fid;
+ return EFI_SUCCESS;
+}
+
+#pragma warning (default : 4090)
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/CORE_DXE/UefiHii/UefiHii.cif b/Core/CORE_DXE/UefiHii/UefiHii.cif
new file mode 100644
index 0000000..4e82128
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/UefiHii.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "UefiHii"
+ category = ModulePart
+ LocalRoot = "Core\CORE_DXE\UefiHii\"
+ RefName = "UefiHii"
+[files]
+"UefiHii.sdl"
+"HiiConfig.c"
+"HiiDatabase.c"
+"HiiFont.c"
+"HiiFontEx.c"
+"HiiPrivate.h"
+"HiiString.c"
+"Hii.chm"
+"UefiHiiUtils.c"
+"HiAccessConfig.c"
+"hii21ExportConfig.c"
+<endComponent>
diff --git a/Core/CORE_DXE/UefiHii/UefiHii.sdl b/Core/CORE_DXE/UefiHii/UefiHii.sdl
new file mode 100644
index 0000000..9bdae97
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/UefiHii.sdl
@@ -0,0 +1,15 @@
+TOKEN
+ Name = "UefiHii_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable UefiHii support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "UefiHii_DIR"
+ Help = "Path to UefiHii Module in Project"
+End
+
diff --git a/Core/CORE_DXE/UefiHii/UefiHiiUtils.c b/Core/CORE_DXE/UefiHii/UefiHiiUtils.c
new file mode 100644
index 0000000..d58aed3
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/UefiHiiUtils.c
@@ -0,0 +1,750 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/UefiHiiUtils.c 16 5/22/12 4:38p Artems $
+//
+// $Revision: 16 $
+//
+// $Date: 5/22/12 4:38p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/UefiHiiUtils.c $
+//
+// 16 5/22/12 4:38p Artems
+// [TAG] EIP N/A
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] In certain cases system font is absent
+// [RootCause] When font FFS file is not found system doesn't publish
+// system font
+// [Solution] If font FFS file is not found, publish font supplied with
+// Core
+// [Files] UefiHiiUtils.c
+//
+// 15 4/30/12 3:52p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Modified GraphicsConsole driver to output whole string
+// instead of symbol-by-symbol output
+// [Files] Gc.c, AmiDxeLib.h, EfiLib.c, UefiHiiUtils.c
+//
+// 14 1/05/12 5:05p Artems
+// EIP 76735: Font FFS file is not loaded in framework mode, when in
+// nested FV
+//
+// 13 1/05/11 12:12p Artems
+// EIP 51298: BufferSize value gets corrupted after call to ConfigToBlock
+// function - fixed
+//
+// 12 10/07/10 12:18p Felixp
+// Minor bug fix in LoadSystemFont: don't call FreePool if font section
+// has not been read.
+//
+// 11 10/01/10 4:44p Artems
+// Added implementation of function SetBrowserData
+//
+// 10 3/22/10 3:25p Felixp
+// SetCallback bug fix (the bug introduced during previous check in).
+//
+// 9 3/12/10 2:21p Felixp
+// Enhencement: LoadResources is updated to properly publish the packages
+// when NumberOfCallbacks is zero.
+//
+// 7 2/23/10 10:30p Felixp
+// SetBrowserData function is added.
+//
+// 6 2/19/10 4:15p Felixp
+// GetString function is updated: if the string is not defined for the
+// PlatformLang , try with the default language.
+// If still no luck, try English.
+//
+// 5 2/12/10 5:47p Felixp
+// Bug fix in LoadResources and LoadString functions
+// (memory corruption in projects with more than one supported language).
+//
+// 4 11/25/09 11:27a Felixp
+// Action parameter of the Callback function is updated based on UEFI
+// errata
+//
+// 3 11/24/09 4:39p Felixp
+//
+// 2 11/24/09 11:27a Felixp
+// GetString udpated: if PlatformLang variable does not exist use default
+// language instead of English.
+//
+// 1 10/09/09 6:12p Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: UefiHiiUtils.c
+//
+// Description: UEFI 2.1 HII Utilities Protocol Implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <AmiDxeLib.h>
+#include <Protocol/HiiUtilities.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+#include "HiiPrivate.h"
+
+EFI_STATUS HiiAccessExtractConfig(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+);
+EFI_STATUS HiiAccessRouteConfig(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+);
+EFI_STATUS HiiAccessFormCallback(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+);
+
+VOID StripValuePattern(
+ IN OUT EFI_STRING String,
+ IN UINTN Size
+);
+
+UINT32 StrSize16(
+ IN CHAR16 *String
+);
+
+static EFI_HII_DATABASE_PROTOCOL *HiiDatabase=NULL;
+static EFI_HII_STRING_PROTOCOL *HiiString=NULL;
+static EFI_FORM_BROWSER2_PROTOCOL *FormBrowser = NULL;
+static EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting = NULL;
+
+static EFI_GUID HiiResourcesFfsSectionGuid= HII_RESOURCES_FFS_SECTION_GUID;
+static EFI_GUID EfiVariableGuid = EFI_GLOBAL_VARIABLE;
+static CHAR8 *PlatformLang = NULL;
+
+extern const char *DefaultLanguageCode;
+extern SIMPLE_FONT DefaultFont[];
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: SetCallback
+//
+// Description:
+// EFI_STATUS SetCallback(EFI_HII_IFR_PACK *pIfr,
+// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo,
+// CALLBACK_INFO **CallBackFound)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS SetCallback(
+ EFI_LOADED_IMAGE_PROTOCOL *Image,
+ EFI_IFR_FORM_SET *FormSet, UINTN NumberOfCallbacks,
+ CALLBACK_INFO *CallbackInfo, CALLBACK_INFO **CallBackFound,
+ EFI_HANDLE *CallbackHandle
+)
+{
+ UINTN i;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle=NULL;
+ EFI_DEVICE_PATH_PROTOCOL *pPath, *pPath2;
+ CALLBACK_INFO *CallbackInfoPtr;
+
+ static EFI_HII_CONFIG_ACCESS_PROTOCOL DefaultConfigAccess = {
+ HiiAccessExtractConfig, HiiAccessRouteConfig, HiiAccessFormCallback
+ };
+ static CALLBACK_INFO DefaultCallbackInfo = {
+ NULL,&DefaultConfigAccess, 0, 0, NULL
+ };
+ static VENDOR_DEVICE_PATH FormSetDevicePathNode = {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
+ sizeof(VENDOR_DEVICE_PATH)
+ },
+ {0}
+ };
+
+ for( i=0
+ ; i<NumberOfCallbacks
+ && ( CallbackInfo[i].pGuid == NULL
+ || guidcmp(&FormSet->Guid,CallbackInfo[i].pGuid) != 0
+ )
+ ; i++
+ );
+ if (i==NumberOfCallbacks){
+ CallbackInfoPtr = &DefaultCallbackInfo;
+ }else{
+ CallbackInfoPtr = &CallbackInfo[i];
+ if (CallbackInfoPtr->pFormCallback == NULL){
+ CallbackInfoPtr->pFormCallback = &DefaultConfigAccess;
+ }else{
+ if (CallbackInfoPtr->pFormCallback->ExtractConfig==NULL)
+ CallbackInfoPtr->pFormCallback->ExtractConfig =
+ HiiAccessExtractConfig;
+ if (CallbackInfoPtr->pFormCallback->RouteConfig==NULL)
+ CallbackInfoPtr->pFormCallback->RouteConfig =
+ HiiAccessRouteConfig;
+ if (CallbackInfoPtr->pFormCallback->Callback==NULL)
+ CallbackInfoPtr->pFormCallback->Callback =
+ HiiAccessFormCallback;
+ }
+ }
+ Status=pBS->HandleProtocol(Image->DeviceHandle, &guidDevicePath, &pPath);
+ if (EFI_ERROR(Status)) pPath=NULL;
+ pPath = DPAddNode(pPath, Image->FilePath);
+ FormSetDevicePathNode.Guid = FormSet->Guid;
+ pPath2 = DPAddNode(pPath, &FormSetDevicePathNode.Header);
+ pBS->FreePool(pPath);
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &guidDevicePath, pPath2,
+ &gEfiHiiConfigAccessProtocolGuid, CallbackInfoPtr->pFormCallback,
+ NULL
+ );
+ if (EFI_ERROR(Status)) return Status;
+ if (CallbackHandle) *CallbackHandle=Handle;
+ if (CallBackFound){
+ *CallBackFound= (CallbackInfoPtr == &DefaultCallbackInfo)
+ ? NULL
+ : CallbackInfoPtr;
+ }
+ return EFI_SUCCESS;
+}
+
+static EFI_STATUS PublishPackages(
+ IN VOID *PackagePointers, IN UINTN NumberOfPackages,
+ IN EFI_GUID *PackageGuid, IN EFI_HANDLE DriverHandle OPTIONAL,
+ OUT EFI_HII_HANDLE *HiiHandle
+){
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ UINTN i;
+ UINT32 PackageLength;
+ UINT8 *PackagePtr;
+ EFI_HII_PACKAGE_HEADER **Packages = PackagePointers;
+ if (NumberOfPackages==0) return EFI_SUCCESS;
+ if ( !HiiDatabase
+ && EFI_ERROR(Status=pBS->LocateProtocol(
+ &gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase
+ ))
+ ) return Status;
+ //calculate the package list length
+ PackageLength = sizeof(EFI_HII_PACKAGE_LIST_HEADER)
+ + sizeof(EFI_HII_PACKAGE_HEADER); //package list terminator
+ for(i=0; i<NumberOfPackages; i++){
+ PackageLength += Packages[i]->Length;
+ }
+ PackageList = Malloc(PackageLength);
+ if(PackageList==NULL) return EFI_OUT_OF_RESOURCES;
+ PackageList->PackageListGuid = *PackageGuid;
+ PackageList->PackageLength = PackageLength;
+
+ PackagePtr = (UINT8*)(PackageList+1);
+ for( i=0; i<NumberOfPackages; i++){
+ pBS->CopyMem(PackagePtr, Packages[i], Packages[i]->Length);
+ PackagePtr += Packages[i]->Length;
+ }
+ ((EFI_HII_PACKAGE_HEADER *)PackagePtr)->Length = sizeof(EFI_HII_PACKAGE_HEADER);
+ ((EFI_HII_PACKAGE_HEADER *)PackagePtr)->Type = EFI_HII_PACKAGE_END;
+
+ Status = HiiDatabase->NewPackageList(
+ HiiDatabase, PackageList, DriverHandle, HiiHandle
+ );
+ pBS->FreePool(PackageList);
+ return Status;
+}
+
+UINT32 GetNumerOfResourcePackages(
+ HII_RESOURCE_SECTION_HEADER *pSection, UINTN SectionSize
+){
+ EFI_HII_PACKAGE_HEADER *PackagePtr;
+ UINT32 NumberOfPackages = 0;
+ PackagePtr = (EFI_HII_PACKAGE_HEADER*)(pSection+1);
+ while(PackagePtr < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){
+ PackagePtr = (EFI_HII_PACKAGE_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length);
+ NumberOfPackages++;
+ }
+ return NumberOfPackages;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadStrings
+//
+// Description:
+// EFI_STATUS LoadStrings(EFI_HANDLE ImageHandle,
+// EFI_HII_HANDLE *HiiHandle)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS LoadStrings(
+ EFI_HANDLE ImageHandle, EFI_HII_HANDLE *HiiHandle
+)
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ HII_RESOURCE_SECTION_HEADER *pSection;
+ UINTN SectionSize;
+ EFI_HII_PACKAGE_HEADER *pPack;
+ EFI_HII_PACKAGE_HEADER **StringPackagPtr;
+ UINTN NumberOfStringPackages;
+ if (EFI_ERROR(Status=pBS->HandleProtocol(
+ ImageHandle, &gEfiLoadedImageProtocolGuid, &Image
+ ))
+ ) return Status;
+#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1
+{
+#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_
+ UINT8 *pData;
+ pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize);
+ if (!pData) return EFI_NOT_FOUND;
+ pSection = Malloc(SectionSize);
+ pBS->CopyMem(pSection,pData,SectionSize);
+ Status = EFI_SUCCESS;
+}
+#else
+{
+ Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize);
+ if (EFI_ERROR(Status)) return Status;
+}
+#endif
+ //Calculate number of packages.
+ //Original value of pSection->NumberOfPackages treats string packages
+ //for multiple languages as a single package. We need the real number of packages.
+ pSection->NumberOfPackages = GetNumerOfResourcePackages(pSection,SectionSize);
+
+ pPack = (EFI_HII_PACKAGE_HEADER *)(pSection + 1);
+
+ StringPackagPtr = Malloc(pSection->NumberOfPackages*sizeof(EFI_HII_PACKAGE_HEADER*));
+ NumberOfStringPackages=0;
+ while(pPack < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){
+ if (pPack->Type != EFI_HII_PACKAGE_STRINGS){
+ Status=EFI_INVALID_PARAMETER;
+ break;
+ }
+ StringPackagPtr[NumberOfStringPackages++]=pPack;
+ pPack = (EFI_HII_PACKAGE_HEADER*)((UINT8*)pPack+pPack->Length);
+ }
+ Status = PublishPackages(
+ StringPackagPtr, NumberOfStringPackages,
+ &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid,
+ NULL, HiiHandle
+ );
+ pBS->FreePool(StringPackagPtr);
+ pBS->FreePool(pSection);
+ return Status;
+}
+
+//*************************************************************************
+//<AMI_PHDR_START>
+//
+// Name: LoadResources
+//
+// Description:
+// EFI_STATUS LoadResources(EFI_HANDLE ImageHandle,
+// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo,
+// INIT_HII_PACK InitFunction)
+//
+// Input:
+//
+// Output:
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//
+//<AMI_PHDR_END>
+//*************************************************************************
+static EFI_STATUS LoadResources(
+ EFI_HANDLE ImageHandle, UINTN NumberOfCallbacks,
+ CALLBACK_INFO *CallbackInfo, INIT_HII_PACK InitFunction
+)
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ HII_RESOURCE_SECTION_HEADER *pSection;
+ UINTN SectionSize;
+ CALLBACK_INFO *pCallBackFound;
+ if (EFI_ERROR(Status=pBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, &Image))) return Status;
+#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1
+{
+#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_
+ UINT8 *pData;
+ pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize);
+ if (!pData) return EFI_NOT_FOUND;
+ pSection = Malloc(SectionSize);
+ pBS->CopyMem(pSection,pData,SectionSize);
+}
+#else
+{
+ Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize);
+ if (EFI_ERROR(Status)) return Status;
+}
+#endif
+{
+ EFI_HII_PACKAGE_HEADER **IfrPackagPtr, **GlobalPackagPtr, **SharedPackagPtr;
+ UINTN NumberOfIfrPackages, NumberOfGlobalPackages, NumberOfSharedPackages, i;
+ UINT8 *PackagePtrBuffer;
+ EFI_HII_PACKAGE_HEADER *PackagePtr;
+
+ //Calculate number of packages.
+ //Original value of pSection->NumberOfPackages treats string packages
+ //for multiple languages as a single package. We need the real number of packages.
+ pSection->NumberOfPackages = GetNumerOfResourcePackages(pSection,SectionSize);
+
+ PackagePtrBuffer = Malloc(3*pSection->NumberOfPackages*sizeof(EFI_HII_PACKAGE_HEADER*));
+ IfrPackagPtr = (EFI_HII_PACKAGE_HEADER**)PackagePtrBuffer;
+ GlobalPackagPtr = IfrPackagPtr+pSection->NumberOfPackages;
+ SharedPackagPtr = GlobalPackagPtr+pSection->NumberOfPackages;
+ NumberOfIfrPackages = 0;
+ NumberOfGlobalPackages = 0;
+ NumberOfSharedPackages = 0;
+
+ PackagePtr = (EFI_HII_PACKAGE_HEADER*)(pSection+1);
+ while(PackagePtr < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){
+ switch(PackagePtr->Type){
+ case EFI_HII_PACKAGE_FORMS:
+ IfrPackagPtr[NumberOfIfrPackages++]=PackagePtr;
+ break;
+ case EFI_HII_PACKAGE_FONTS: case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ GlobalPackagPtr[NumberOfGlobalPackages++]=PackagePtr;
+ break;
+ default:
+ SharedPackagPtr[NumberOfSharedPackages++]=PackagePtr;
+ break;
+ }
+ PackagePtr = (EFI_HII_PACKAGE_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length);
+ }
+ Status = PublishPackages(
+ GlobalPackagPtr, NumberOfGlobalPackages,
+ &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid,
+ NULL, &HiiHandle
+ );
+ for(i=0; i<NumberOfIfrPackages; i++){
+ EFI_HANDLE CallbackHandle;
+
+ SharedPackagPtr[NumberOfSharedPackages]=IfrPackagPtr[i];
+ SetCallback(
+ Image, (EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1),
+ NumberOfCallbacks,CallbackInfo,&pCallBackFound,&CallbackHandle
+ );
+ Status = PublishPackages(
+ SharedPackagPtr, NumberOfSharedPackages+1,
+ &((EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1))->Guid,
+ CallbackHandle, &HiiHandle
+ );
+ if (pCallBackFound) pCallBackFound->HiiHandle=HiiHandle;
+ if (InitFunction) InitFunction(HiiHandle,pCallBackFound);
+ pCallBackFound=NULL;
+ }
+ pBS->FreePool(PackagePtrBuffer);
+ pBS->FreePool(pSection);
+}
+ return EFI_SUCCESS;
+}
+
+//TODO: header
+static EFI_STATUS GetString(
+ IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId,
+ IN OUT UINTN *StringSize, OUT EFI_STRING String
+){
+ EFI_STATUS Status;
+
+ if ( !HiiString
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, &HiiString))
+ ) return EFI_NOT_FOUND;
+ if (PlatformLang==NULL){
+ UINTN Size;
+ if (EFI_ERROR(GetEfiVariable(
+ L"PlatformLang", &EfiVariableGuid, NULL, &Size, &PlatformLang
+ ))) PlatformLang = (CHAR8*)DefaultLanguageCode;
+ }
+ Status = HiiString->GetString(
+ HiiString, PlatformLang, HiiHandle,StringId, String, StringSize, NULL
+ );
+ // If the string representation for the PlatformLang is not defined,
+ // try with the default language.
+ // If still no luck, try English
+ if (Status==EFI_INVALID_LANGUAGE){
+ Status = HiiString->GetString(
+ HiiString, (CHAR8*)DefaultLanguageCode, HiiHandle,
+ StringId, String, StringSize, NULL
+ );
+ if (Status==EFI_INVALID_LANGUAGE)
+ Status = HiiString->GetString(
+ HiiString, LANGUAGE_CODE_ENGLISH, HiiHandle,
+ StringId, String, StringSize, NULL
+ );
+ }
+ return Status;
+}
+
+//TODO header
+static EFI_STATUS SetString(
+ IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, IN EFI_STRING String
+){
+ CHAR8 *LanguageList = NULL;
+ UINTN Size = 0;
+ EFI_STATUS Status;
+
+ if ( !HiiString
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, &HiiString))
+ ) return EFI_NOT_FOUND;
+
+ Status = HiiString->GetLanguages(HiiString, HiiHandle, LanguageList, &Size);
+ if (Status!=EFI_BUFFER_TOO_SMALL) return Status;
+ LanguageList = Malloc(Size);
+ Status = HiiString->GetLanguages(HiiString, HiiHandle, LanguageList, &Size);
+ if (!EFI_ERROR(Status)){
+ CHAR8 *CurrentLang, *EndOfCurrentLang;
+ EndOfCurrentLang = LanguageList;
+ while(EndOfCurrentLang < LanguageList+Size){
+ CHAR8 OriginalChar;
+ CurrentLang = EndOfCurrentLang;
+ while(*EndOfCurrentLang!=';'&&*EndOfCurrentLang!=0) EndOfCurrentLang++;
+ OriginalChar = *EndOfCurrentLang;
+ *EndOfCurrentLang = 0;
+ Status = HiiString->SetString(
+ HiiString, HiiHandle, StringId, CurrentLang, String, NULL
+ );
+ if (EFI_ERROR(Status)) break;
+ *EndOfCurrentLang = OriginalChar;
+ EndOfCurrentLang++;
+ }
+ }
+ pBS->FreePool(LanguageList);
+ return Status;
+}
+
+static EFI_STATUS GetBrowserData(
+ IN UINTN *BufferSize, OUT VOID *Buffer,
+ IN CONST EFI_GUID *VarStoreGuid, OPTIONAL
+ IN CONST CHAR16 *VarStoreName OPTIONAL
+){
+ UINTN StringDataSize = 0;
+ CHAR16 *StringData = NULL;
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+
+ if ( !FormBrowser
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser))
+ ) return EFI_NOT_FOUND;
+ if ( !HiiConfigRouting
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting))
+ ) return EFI_NOT_FOUND;
+
+ Status = FormBrowser->BrowserCallback(
+ FormBrowser, &StringDataSize, StringData, TRUE,
+ VarStoreGuid, VarStoreName
+ );
+ if (Status!=EFI_BUFFER_TOO_SMALL) return Status;
+ StringData = Malloc(StringDataSize);
+ Status = FormBrowser->BrowserCallback(
+ FormBrowser, &StringDataSize, StringData, TRUE,
+ VarStoreGuid, VarStoreName
+ );
+ if (!EFI_ERROR(Status)){
+ StringDataSize = *BufferSize; //preserve passed buffer size value, as
+ //ConfigToBlock may change it as per UEFI 2.1 spec
+ //it will contain index of last updated byte
+ Status = HiiConfigRouting->ConfigToBlock(
+ HiiConfigRouting, StringData, Buffer, BufferSize, &Progress
+ );
+ *BufferSize = StringDataSize; //restore original value
+ }
+ pBS->FreePool(StringData);
+ return Status;
+}
+
+static EFI_STATUS SetBrowserData(
+ IN UINTN BufferSize, IN VOID *Buffer,
+ IN CONST EFI_GUID *VarStoreGuid, OPTIONAL //TODO: Can it be optional???
+ IN CONST CHAR16 *VarStoreName OPTIONAL
+)
+{
+ UINTN StringDataSize = 0;
+ CHAR16 *StringData = NULL;
+ EFI_STATUS Status;
+ EFI_STRING Config;
+ EFI_STRING Progress;
+
+ if ( !FormBrowser
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser))
+ ) return EFI_NOT_FOUND;
+ if ( !HiiConfigRouting
+ && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting))
+ ) return EFI_NOT_FOUND;
+
+ Status = FormBrowser->BrowserCallback(
+ FormBrowser, &StringDataSize, StringData, TRUE,
+ VarStoreGuid, VarStoreName
+ );
+ if (Status!=EFI_BUFFER_TOO_SMALL) return Status;
+ StringData = Malloc(StringDataSize);
+ Status = FormBrowser->BrowserCallback(
+ FormBrowser, &StringDataSize, StringData, TRUE,
+ VarStoreGuid, VarStoreName
+ );
+ if (EFI_ERROR(Status))
+ return Status;
+
+//we have StringData in format &OFFSET=XXXX&WIDTH=XXXX&VALUE=XXXX&OFFSET=...
+//in order for function BlockToConfig to work we need to modify StringData as follows:
+//&OFFSET=XXXX&WIDTH=XXXX&OFFSET=... (i.e. remove all &VALUE=XXX patterns)
+
+ StripValuePattern(StringData, StringDataSize);
+
+ Status = HiiConfigRouting->BlockToConfig(
+ HiiConfigRouting, StringData, Buffer, BufferSize,
+ &Config, &Progress
+ );
+
+ if(!EFI_ERROR(Status)) {
+ StringDataSize = StrSize16(Config);
+ Status = FormBrowser->BrowserCallback(
+ FormBrowser, &StringDataSize, Config, FALSE,
+ VarStoreGuid, VarStoreName
+ );
+ pBS->FreePool(Config);
+ }
+
+ pBS->FreePool(StringData);
+ return Status;
+}
+
+EFI_STATUS LoadSystemFont(){
+///// Load Font Pack
+#define FONT_FFS_FILE_GUID { 0xdac2b117, 0xb5fb, 0x4964, { 0xa3, 0x12, 0xd, 0xcc, 0x77, 0x6, 0x1b, 0x9b } }
+static EFI_GUID FontFfsFileGuid = FONT_FFS_FILE_GUID;
+extern UINT8 UsStdNarrowGlyphData[];
+ EFI_FIRMWARE_VOLUME_PROTOCOL *pFV;
+ UINTN DataSize;
+ EFI_GUID *pSectionGuid = NULL;
+ UINT32 Authentication;
+ EFI_HANDLE *pHandle;
+ UINTN Number,i;
+ EFI_STATUS FontStatus;
+ EFI_HII_PACKAGE_HEADER *FontPackage;
+ EFI_HII_HANDLE HiiFontHandle;
+
+ FontPackage = (EFI_HII_PACKAGE_HEADER*)&UsStdNarrowGlyphData;
+ FontStatus = pBS->LocateHandleBuffer(ByProtocol,&guidFV, NULL, &Number, &pHandle);
+ for(i=0;i<Number; i++)
+ {
+ FontStatus=pBS->HandleProtocol(pHandle[i], &guidFV, &pFV);
+ if (EFI_ERROR(FontStatus)) continue;
+ pSectionGuid=NULL;
+ DataSize=0;
+ FontStatus=pFV->ReadSection (
+ pFV,&FontFfsFileGuid,
+ EFI_SECTION_FREEFORM_SUBTYPE_GUID,0, &pSectionGuid, &DataSize,
+ &Authentication
+ );
+ if (!EFI_ERROR(FontStatus))
+ {
+ FontPackage=(EFI_HII_PACKAGE_HEADER*)((UINT32*)(pSectionGuid+1)+1);
+ break;
+ }
+ }
+
+ if (FontPackage->Type!=EFI_HII_PACKAGE_SIMPLE_FONTS){
+ //The font package is in the Framework HII format
+ //Convert the header to the UEFI HII format
+ DataSize=FontPackage->Length;
+ FontPackage = (EFI_HII_PACKAGE_HEADER*)((UINT8*)FontPackage+2);
+ FontPackage->Type=EFI_HII_PACKAGE_SIMPLE_FONTS;
+ FontPackage->Length=(UINT32)DataSize;
+ }
+ FontStatus = PublishPackages(&FontPackage, 1, &FontFfsFileGuid, NULL, &HiiFontHandle);
+ if (pSectionGuid!=NULL) pBS->FreePool(pSectionGuid);
+ return FontStatus;
+}
+
+static EFI_STATUS UtilGetGlyphWidth(
+ IN CHAR16 Char,
+ OUT UINT16 *Width
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if(DefaultFont[(UINTN)Char].NarrowGlyph != NULL) {
+ *Width = ((DefaultFont[(UINTN)Char].NarrowGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDTH;
+ } else if(DefaultFont[(UINTN)Char].WideGlyph != NULL) {
+ *Width = ((DefaultFont[(UINTN)Char].WideGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDE_WIDTH;
+ } else if(DefaultFont[0xfffd].NarrowGlyph != NULL) {
+ *Width = EFI_GLYPH_WIDTH;
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ } else if(DefaultFont[0xfffd].WideGlyph != NULL) {
+ *Width = EFI_GLYPH_WIDE_WIDTH;
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ } else {
+ *Width = 0;
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ return Status;
+}
+
+HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol = {
+ LoadResources, LoadStrings, PublishPackages,
+ GetBrowserData, SetBrowserData, GetString, SetString, UtilGetGlyphWidth
+};
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/CORE_DXE/UefiHii/hii21ExportConfig.c b/Core/CORE_DXE/UefiHii/hii21ExportConfig.c
new file mode 100644
index 0000000..91480c0
--- /dev/null
+++ b/Core/CORE_DXE/UefiHii/hii21ExportConfig.c
@@ -0,0 +1,1143 @@
+//*****************************************************************//
+//*****************************************************************//
+//*****************************************************************//
+//** **//
+//** (C)Copyright 2010, American Megatrends, Inc. **//
+//** **//
+//** All Rights Reserved. **//
+//** **//
+//** 5555 Oakbrook Pkwy, Building 200,Norcross, Georgia 30093 **//
+//** **//
+//** Phone (770)-246-8600 **//
+//** **//
+//*****************************************************************//
+//*****************************************************************//
+//*****************************************************************//
+// $Archive: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/hii21ExportConfig.c $
+//
+// $Author: Artems $
+//
+// $Revision: 1 $
+//
+// $Date: 1/25/11 3:20p $
+//
+//*****************************************************************//
+//*****************************************************************//
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/hii21ExportConfig.c $
+//
+// 1 1/25/11 3:20p Artems
+//
+//
+//*****************************************************************//
+//*****************************************************************//
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: hii21ExportConfig.c
+//
+// Description: This file contains code to perform the ExportConfig Operation of Config
+// roughting protocol.
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+
+#include "token.h"
+#include "efi.h"
+//#include "devicepath.h"
+#include <AmiDxeLib.h>
+
+#ifndef EFI_PROTOCOL_DEFINITION
+#define TSE_STRINGIZE(a) #a
+#define EFI_PROTOCOL_DEFINITION(a) TSE_STRINGIZE(Protocol/a.h)
+#endif
+
+#include EFI_PROTOCOL_DEFINITION(HiiDatabase)
+#include EFI_PROTOCOL_DEFINITION(HiiConfigRouting)
+#include EFI_PROTOCOL_DEFINITION(devicepath)
+
+typedef struct _VARSTORE_INFO
+{
+ EFI_GUID VariableGuid; //Varies EFI_GUID for the NVRAM variable store for this data
+ VOID* VariableHandle; //Varies HII Handle to the formset that contains this VarStore
+ UINT16 VariableSize; //Varies The size of Buffer Varstore
+ struct _VARSTORE_INFO *Next;
+ char *VariableName; //Varies Variable store name
+}VARSTORE_INFO;
+
+
+// Helper Functions
+EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;
+EFI_BOOT_SERVICES *gBS;
+EFI_HII_CONFIG_ROUTING_PROTOCOL * gHiiConfigRouting;
+
+VARSTORE_INFO *gVarInfoHead = NULL;
+VARSTORE_INFO *gpVarInfo;
+
+EFI_HII_HANDLE *HiiGetHandles(UINT16 *NumberOfHiiHandles);
+VOID * _HiiGetForm( EFI_HII_HANDLE Handle, UINTN *Length );
+VOID _HiiGetVariable(EFI_HII_HANDLE Handle, UINT8 * buff);
+EFI_STATUS GetVarStoreConfig(VARSTORE_INFO *VarInfo, EFI_STRING *result);
+EFI_STATUS GetConfigHeader(VARSTORE_INFO *VarInfo, EFI_STRING *Configuration, UINTN *Length);
+EFI_STATUS GetBlockName(EFI_STRING *Configuration, UINTN *Length, UINTN Size);
+EFI_STATUS _VerifyResponseString(EFI_STRING Configuration, BOOLEAN NameValue);
+EFI_STATUS _ConstructConfigHdr (
+ IN OUT CHAR16 *ConfigHdr,
+ IN OUT UINTN *StrBufferLen,
+ IN EFI_GUID *Guid,
+ IN CHAR16 *Name, OPTIONAL
+ IN EFI_HANDLE *DriverHandle
+ );
+
+EFI_STATUS
+BufferToHexString (
+ IN OUT CHAR16 *Str,
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize
+ );
+EFI_STATUS
+UnicodeToConfigString (
+ IN OUT CHAR16 *ConfigString,
+ IN OUT UINTN *StrBufferLen,
+ IN CHAR16 *UnicodeString
+ );
+VOID
+SwapBuffer (
+ IN OUT UINT8 *Buffer,
+ IN UINTN BufferSize
+ );
+EFI_STATUS
+BufToHexString (
+ IN OUT CHAR16 *Str,
+ IN OUT UINTN *HexStringBufferLength,
+ IN UINT8 *Buf,
+ IN UINTN Len
+ );
+CHAR16
+NibbleToHexChar (
+ IN UINT8 Nibble
+ );
+VOID
+ToLower (
+ IN OUT CHAR16 *Str
+ );
+VOID StrCpy8(CHAR8 *dest, CHAR8 *src);
+VOID
+EfiStrCpy (
+ IN CHAR16 *Destination,
+ IN CHAR16 *Source
+ );
+
+VOID
+EfiStrCat (
+ IN CHAR16 *Destination,
+ IN CHAR16 *Source
+ );
+
+
+//=== HELPER Functions ====================//
+VOID *
+EfiLibAllocatePool (
+ IN UINTN AllocationSize
+ )
+{
+ return Malloc(AllocationSize);
+}
+
+VOID *
+EfiLibAllocateZeroPool (
+ IN UINTN AllocationSize
+ )
+{
+ return MallocZ(AllocationSize);
+}
+
+UINTN
+EfiStrLen (
+ IN CHAR16 *String
+ );
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MemFreePointer
+//
+// Description: function to free the pointers
+//
+// Input: VOID **ptr
+//
+// Output: void
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID MemFreePointer( VOID **ptr )
+{
+ if ( ( ptr == NULL ) || ( *ptr == NULL ) )
+ return;
+
+ gBS->FreePool( *ptr );
+ *ptr = NULL;
+}
+
+UINTN StrLen8(CHAR8 *string)
+{
+ UINTN i=0;
+ while(string[i])
+ i++;
+
+ return i;
+}
+
+
+CHAR8 *StrDup8( CHAR8 *string )
+{
+ CHAR8 *text;
+
+ text = EfiLibAllocateZeroPool(1 + StrLen8( string ));
+ if ( text != NULL )
+ StrCpy8( text, string );
+
+ return text;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MemCopy
+//
+// Description: function to copy a memory
+//
+// Input: VOID *dest, VOID *src, UINTN size
+//
+// Output: void
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID MemCopy( VOID *dest, VOID *src, UINTN size )
+{
+ gBS->CopyMem( dest, src, size );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: MemReallocateZeroPool
+//
+// Description: function to reuse a allocated buffer
+//
+// Input: VOID *oldBuffer, UINTN oldSize, UINTN newSize
+//
+// Output: void
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID *MemReallocateZeroPool( VOID *oldBuffer, UINTN oldSize, UINTN newSize )
+{
+ VOID *buffer;
+
+ buffer = EfiLibAllocateZeroPool( newSize );
+ if ( buffer == NULL )
+ return buffer;
+
+ if ( newSize < oldSize )
+ oldSize = newSize;
+
+ if ( oldBuffer != NULL )
+ MemCopy( buffer, oldBuffer, oldSize );
+
+ MemFreePointer( (VOID **)&oldBuffer );
+
+ return buffer;
+}
+
+//<AMI_PHDR_START>
+//--------------------------------------------------------------------------
+//
+// Name: StrDup8to16
+//
+// Description: Duplicates a String from CHAR8 to CHAR16
+//
+// Input: CHAR8* string
+//
+// Output: CHAR16 *
+//
+//
+//--------------------------------------------------------------------------
+//<AMI_PHDR_END>
+CHAR16 *StrDup8to16( CHAR8 *string )
+{
+ CHAR16 *text;
+ UINTN i;
+
+ text = EfiLibAllocatePool( (1 + StrLen8( string )) * sizeof(CHAR16));
+ if ( text != NULL )
+ {
+ i=0;
+ while(text[i] = (CHAR16)string[i])
+ i++;
+ }
+
+ return text;
+}
+
+
+INTN
+EfiStrnCmp (
+ IN CHAR16 *String,
+ IN CHAR16 *String2,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+ This function compares the Unicode string String to the Unicode
+ string String2 for len characters. If the first len characters
+ of String is identical to the first len characters of String2,
+ then 0 is returned. If substring of String sorts lexicographically
+ after String2, the function returns a number greater than 0. If
+ substring of String sorts lexicographically before String2, the
+ function returns a number less than 0.
+
+Arguments:
+ String - Compare to String2
+ String2 - Compare to String
+ Length - Number of Unicode characters to compare
+
+Returns:
+ 0 - The substring of String and String2 is identical.
+ > 0 - The substring of String sorts lexicographically after String2
+ < 0 - The substring of String sorts lexicographically before String2
+
+--*/
+{
+ while (*String && Length != 0) {
+ if (*String != *String2) {
+ break;
+ }
+ String += 1;
+ String2 += 1;
+ Length -= 1;
+ }
+ return Length > 0 ? *String - *String2 : 0;
+}
+
+UINTN
+EfiDevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ return DPLength(DevicePath);
+}
+
+
+VOID InitGlobels(VOID)
+{
+ gBS=pBS;
+ gBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, &gHiiDatabase);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Hii21ExportConfigHelper
+//
+// Description: Helper function to perform ExportConfig Operation of Config
+// roughting protocol.
+//
+// Parameter: EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,
+// OUT EFI_STRING *Results
+//
+// Return value: Status
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Hii21ExportConfigHelper (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ OUT EFI_STRING *Results
+)
+{
+ EFI_HII_HANDLE *HiiHandleList;
+ UINT16 NumberOfHiiHandles = 0;
+ UINTN i;
+ UINT8 *FormSet;
+ UINT8 *ifrData;
+ UINTN Length;
+ EFI_STRING result=NULL;
+ UINTN OldSize,NewSize;
+
+ if(Results == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ *Results = NULL;
+ InitGlobels();
+ gHiiConfigRouting = (EFI_HII_CONFIG_ROUTING_PROTOCOL*)This;
+
+ // To get the All the Valid Hii Handles.
+ HiiHandleList = HiiGetHandles(&NumberOfHiiHandles);
+ gpVarInfo = gVarInfoHead = NULL;
+
+ for(i=0;i<NumberOfHiiHandles;i++)
+ {
+ Length = 0;
+ // To get the FormPackage
+ FormSet = _HiiGetForm( HiiHandleList[i], &Length);
+ // donot contain valid package.
+ if(FormSet == NULL)
+ continue;
+ ifrData = (UINT8*)(FormSet + sizeof(EFI_HII_PACKAGE_HEADER));
+ _HiiGetVariable(HiiHandleList[i], ifrData);
+
+ // Free the FormPackage
+ MemFreePointer(&FormSet);
+ }
+
+
+ gpVarInfo = gVarInfoHead;
+ OldSize = NewSize = 0;
+ while( gpVarInfo != NULL )
+ {
+ VARSTORE_INFO *tmpVarInfo;
+ EFI_STATUS Status;
+
+ Status = GetVarStoreConfig(gpVarInfo, &result);
+ if(!EFI_ERROR(Status))
+ {
+ NewSize = OldSize + (EfiStrLen(result)*2)+10;
+ *Results = MemReallocateZeroPool(*Results, OldSize, NewSize);
+ if(OldSize)
+ EfiStrCat(*Results,L"&");
+ EfiStrCat(*Results,result);
+ MemFreePointer(&result);
+ OldSize = NewSize;
+ }
+
+ MemFreePointer(&gpVarInfo->VariableName);
+ tmpVarInfo = gpVarInfo;
+ gpVarInfo = gpVarInfo->Next;
+ MemFreePointer(&tmpVarInfo);
+ }
+
+ // free the Hii Handles
+ MemFreePointer((VOID**)&HiiHandleList);
+ return EFI_SUCCESS;
+}
+
+
+BOOLEAN IsVarStoreFound(EFI_HII_HANDLE Handle, EFI_IFR_VARSTORE *varstore)
+{
+ VARSTORE_INFO * VarInfo;
+// EFI_GUID SetupGuid = SETUP_GUID;
+
+ VarInfo = gVarInfoHead;
+ while( VarInfo != NULL )
+ {
+ if( MemCmp( (UINT8*)&VarInfo->VariableGuid,(UINT8*) &(varstore->Guid) , sizeof(EFI_GUID)) == 0)
+ if(Strcmp(VarInfo->VariableName, (char*)varstore->Name) ==0)
+ {
+// In Aptio, There are many Variables used in multiple Vfr.
+
+/*
+// Setup Variable even if it differ handle the variable info is same.
+ if( (MemCmp( (UINT8*)&VarInfo->VariableGuid,(UINT8*) &SetupGuid , sizeof(EFI_GUID)) == 0) &&
+ (Strcmp(VarInfo->VariableName, "Setup") == 0) )
+ return TRUE;
+// For not SETUP_DATA if the Handle is different it can be different Variable
+ else if(VarInfo->VariableHandle == Handle)
+*/
+ return TRUE;
+
+ }
+ VarInfo = VarInfo->Next;
+ }
+ return FALSE;
+}
+
+VOID _HiiGetVariable(EFI_HII_HANDLE Handle, UINT8 * buff)
+{
+ EFI_IFR_OP_HEADER *Header;
+ UINTN ScopeCount = 0;
+ EFI_IFR_VARSTORE *varstore;
+
+ //go thru the forms get the variables.
+ do
+ {
+ Header = (EFI_IFR_OP_HEADER*)(buff);
+ switch(Header->OpCode )
+ {
+ case EFI_IFR_END_OP:
+ ScopeCount--;
+ break;
+
+ case EFI_IFR_VARSTORE_OP:
+ if(!IsVarStoreFound(Handle, (EFI_IFR_VARSTORE *)buff))
+ {
+ if( gVarInfoHead == NULL)
+ {
+ gVarInfoHead = EfiLibAllocateZeroPool(sizeof(VARSTORE_INFO));
+ gVarInfoHead->Next = NULL;
+ gpVarInfo = gVarInfoHead;
+ }
+ else
+ {
+ gpVarInfo->Next = EfiLibAllocateZeroPool(sizeof(VARSTORE_INFO));
+ gpVarInfo = gpVarInfo->Next;
+ gpVarInfo->Next = NULL;
+ }
+
+ varstore = (EFI_IFR_VARSTORE*)buff;
+
+ MemCopy(&gpVarInfo->VariableGuid, &(varstore->Guid), sizeof(EFI_GUID));
+ gpVarInfo->VariableHandle = (VOID*)Handle;
+ gpVarInfo->VariableSize = varstore->Size;
+ gpVarInfo->VariableName = StrDup8((char*)varstore->Name);
+ }
+ default:
+ if(Header->Scope)
+ {
+ ScopeCount++;
+ }
+ break;
+
+ }
+ buff += Header->Length;
+ }while(ScopeCount != 0);
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: _HiiGetForm
+//
+// Description:
+//
+// Parameter:
+//
+// Return value:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID *_HiiGetForm( EFI_HII_HANDLE Handle, UINTN *Length )
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_HII_PACKAGE_HEADER *pkgHdr;
+ EFI_IFR_OP_HEADER *opHeader = NULL;
+ VOID *hiiFormPackage=NULL;
+ UINT8 *formPkBuffer = NULL;
+ UINT8 *pkgOffset;
+ UINT8 end = 0;
+ UINT32 offset = 0;
+ UINTN len=10;
+ //SETUP_LINK DummySetupLink;
+
+ if(Length == NULL)
+ Length = &len;
+
+ hiiFormPackage = EfiLibAllocateZeroPool(*Length);
+
+ status = gHiiDatabase->ExportPackageLists(gHiiDatabase, Handle, Length, hiiFormPackage);
+ if(status == EFI_BUFFER_TOO_SMALL)
+ {
+ MemFreePointer(&hiiFormPackage);
+ //
+ // Allocate space for retrieval of IFR data
+ //
+ hiiFormPackage = EfiLibAllocateZeroPool(*Length);
+
+ if (hiiFormPackage == NULL)
+ {
+ hiiFormPackage = NULL;
+ goto DONE;
+ }
+ //
+ // Get all the packages associated with this HiiHandle
+ //
+ status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, Length, hiiFormPackage);
+ if(EFI_ERROR(status))
+ {
+ MemFreePointer(&hiiFormPackage);
+ hiiFormPackage = NULL;
+ goto DONE;
+ }
+ }else if(EFI_ERROR(status))
+ {
+ hiiFormPackage = NULL;
+ goto DONE;
+ }
+
+ offset = sizeof(EFI_HII_PACKAGE_LIST_HEADER);
+
+ while(offset < ((EFI_HII_PACKAGE_LIST_HEADER*)hiiFormPackage)->PackageLength)
+ {
+ pkgOffset = ((UINT8*)hiiFormPackage) + offset;
+ pkgHdr = (EFI_HII_PACKAGE_HEADER*)pkgOffset;
+ switch(pkgHdr->Type)
+ {
+ case EFI_HII_PACKAGE_FORMS:
+ formPkBuffer = (UINT8*)EfiLibAllocateZeroPool(pkgHdr->Length);
+ if(formPkBuffer == NULL)
+ {
+ goto DONE;
+ }
+
+ MemCopy(formPkBuffer, pkgHdr, pkgHdr->Length);
+
+ opHeader = (EFI_IFR_OP_HEADER*)((UINT8*)formPkBuffer + sizeof(EFI_HII_PACKAGE_HEADER));
+ if(opHeader->OpCode != EFI_IFR_FORM_SET_OP)
+ {
+ MemFreePointer(&formPkBuffer);
+ formPkBuffer = NULL;
+ *Length = 0;
+ goto DONE;
+ }
+
+ end = 1;
+ break;
+ case EFI_HII_PACKAGE_END:
+ end = 1;
+ break;
+ default:
+ break;
+ }
+ if(end)
+ {
+ break;
+ }
+ offset += pkgHdr->Length;
+ }
+
+ MemFreePointer(&hiiFormPackage);
+
+DONE:
+ return formPkBuffer;
+}
+
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: HiiGetHandles
+//
+// Description: gets all the HII handles
+//
+// Parameter: No of handles
+//
+// Return value: EFI_HII_HANDLE *
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_HII_HANDLE *HiiGetHandles(UINT16 *NumberOfHiiHandles)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_HII_HANDLE *hiiHandleBuffer = NULL;
+ UINTN handleBufferLength = sizeof(EFI_HII_HANDLE);
+
+ hiiHandleBuffer = EfiLibAllocatePool(handleBufferLength);
+
+ status = gHiiDatabase->ListPackageLists (gHiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL,
+ &handleBufferLength, hiiHandleBuffer);
+ if (status == EFI_BUFFER_TOO_SMALL)
+ {
+ //
+ // Free the old pool
+ //
+ MemFreePointer ((VOID**)&hiiHandleBuffer);
+ //
+ // Allocate new pool with correct value
+ //
+ hiiHandleBuffer = EfiLibAllocatePool(handleBufferLength);
+
+ //
+ // Get the Handles of the packages that were registered with Hii
+ //
+ gBS->SetMem(hiiHandleBuffer,handleBufferLength,0);
+ status = gHiiDatabase->ListPackageLists (gHiiDatabase, EFI_HII_PACKAGE_TYPE_ALL,
+ NULL, &handleBufferLength, hiiHandleBuffer);
+
+ if (EFI_ERROR (status))
+ {
+ MemFreePointer((VOID**)&hiiHandleBuffer);
+ hiiHandleBuffer = NULL;
+ goto DONE;
+ }
+ }else if(EFI_ERROR(status))
+ {
+ MemFreePointer((VOID**)&hiiHandleBuffer);
+ hiiHandleBuffer = NULL;
+ goto DONE;
+ }
+
+ *NumberOfHiiHandles = (UINT16)(handleBufferLength / sizeof(EFI_HII_HANDLE));
+
+DONE:
+ return hiiHandleBuffer;
+}
+
+
+
+
+EFI_STATUS GetVarStoreConfig(VARSTORE_INFO *VarInfo, EFI_STRING *result)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_STRING configuration = NULL;
+ EFI_STRING progress = NULL;
+ //EFI_STRING result = NULL;
+ //EFI_STRING stringPtr = NULL;
+ UINTN length = 1;
+ //UINT8 *buffer = NULL;
+
+ configuration = EfiLibAllocateZeroPool(length);
+ if(configuration == NULL)
+ {
+ status = EFI_OUT_OF_RESOURCES;
+ goto DONE;
+ }
+
+ //
+ // Construct the Configuration Header String
+ //
+ status = GetConfigHeader(VarInfo, &configuration, &length);
+ if(EFI_ERROR(status))
+ {
+ //TSE_DEBUG ( (TSE_DBG_LEVEL, "\nGetConfigHeader FAIL\n" ));
+ goto DONE;
+ }
+
+/* if(VariableInfo->ExtendedAttibutes & VARIABLE_ATTRIBUTE_NAMEVALUE)
+ {
+ }else
+*/
+ {
+ status = GetBlockName(&configuration, &length, VarInfo->VariableSize);
+ if(EFI_ERROR(status))
+ {
+ //TSE_DEBUG ( (TSE_DBG_LEVEL, "\n GetBlockname FAIL\n" ));
+ goto DONE;
+ }
+ }
+
+ // Invoke Config Routing Route Config
+ status = gHiiConfigRouting->ExtractConfig(gHiiConfigRouting, configuration, &progress, result);
+
+ if(EFI_ERROR(status))
+ *result = NULL;
+
+ status = _VerifyResponseString(*result, /*(VariableInfo->ExtendedAttibutes & VARIABLE_ATTRIBUTE_NAMEVALUE)? TRUE :*/ FALSE);
+
+DONE:
+ if(configuration)
+ {
+ MemFreePointer(&configuration);
+ }
+
+ return status;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: _VerifyResponseString
+//
+// Description: Verifies Correctness of Response String. This is to prevent
+// crashing if the result pointer is pointing to an invalid location.
+//
+// Parameter: EFI_STRING *Configuration
+//
+// Return value: EFI_STATUS
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS _VerifyResponseString(EFI_STRING Configuration, BOOLEAN NameValue)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_STRING config = Configuration;
+ CHAR16 *keyWord[] = {L"GUID=", L"&NAME=", L"&PATH=", L"&OFFSET=0&WIDTH=", L"&VALUE="};
+ UINT32 i = 0;
+ UINT32 count = NameValue? 3 : 5; // If Name Value Check only upto &Path else check until &Value.
+
+ if(EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0)
+ {
+ status = EFI_NOT_FOUND;
+ goto DONE;
+ }
+
+ for(i = 1; i < count; i++)
+ {
+ for(;EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0 && (config != (Configuration + EfiStrLen(Configuration))); config++)
+ ;
+ if(EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0)
+ {
+ status = EFI_NOT_FOUND;
+ goto DONE;
+ }
+ }
+
+DONE:
+ return status;
+}
+
+
+
+EFI_STATUS GetConfigHeader(VARSTORE_INFO *VarInfo, EFI_STRING *Configuration, UINTN *Length)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_STRING configuration = NULL;
+ EFI_HANDLE driverHandle;
+ UINTN length = 0;
+ CHAR16 *VarName=NULL;
+
+ //
+ // Retrieve the Device Path from Handle
+ //
+ status = gHiiDatabase->GetPackageListHandle(gHiiDatabase, VarInfo->VariableHandle, &driverHandle);
+ if(EFI_ERROR(status))
+ {
+ goto DONE;
+ }
+
+ //
+ // Construct the Configuration Header String
+ //
+ VarName = StrDup8to16(VarInfo->VariableName);
+ status = _ConstructConfigHdr(configuration, &length, &VarInfo->VariableGuid, VarName, driverHandle);
+ if(EFI_ERROR(status))
+ {
+ if(status == EFI_BUFFER_TOO_SMALL)
+ {
+ MemFreePointer(&configuration);
+ configuration = (UINT16*)EfiLibAllocateZeroPool(length);
+ if(configuration == NULL)
+ {
+ status = EFI_OUT_OF_RESOURCES;
+ goto DONE;
+ }
+
+ status = _ConstructConfigHdr(configuration, &length, &VarInfo->VariableGuid, VarName, driverHandle);
+ }
+ }
+
+ if(EFI_ERROR(status))
+ {
+ goto DONE;
+ }
+
+ if(*Configuration)
+ {
+ MemFreePointer(Configuration);
+ }
+ *Configuration = configuration;
+ *Length = length;
+
+DONE:
+ MemFreePointer(&VarName);
+ return status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: _ConstructConfigHdr
+//
+// Description: Construct <ConfigHdr> using routing information GUID/NAME/PATH.
+//
+// Parameter: IN OUT CHAR16 *ConfigHdr,
+// IN OUT UINTN *StrBufferLen,
+// IN EFI_GUID *Guid,
+// IN CHAR16 *Name, OPTIONAL
+// IN EFI_HANDLE *DriverHandle
+//
+// Return value: EFI_STATUS
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS _ConstructConfigHdr (
+ IN OUT CHAR16 *ConfigHdr,
+ IN OUT UINTN *StrBufferLen,
+ IN EFI_GUID *Guid,
+ IN CHAR16 *Name, OPTIONAL
+ IN EFI_HANDLE *DriverHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN NameStrLen;
+ UINTN DevicePathSize;
+ UINTN BufferSize;
+ CHAR16 *StrPtr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (Name == NULL)
+ {
+ //
+ // There will be no "NAME" in <ConfigHdr> for Name/Value storage
+ //
+ NameStrLen = 0;
+ } else
+ {
+ //
+ // For buffer storage
+ //
+ NameStrLen = EfiStrLen (Name);
+ }
+
+ //
+ // Retrieve DevicePath Protocol associated with this HiiPackageList
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &DevicePath
+ );
+ if (EFI_ERROR (Status))
+ {
+ return Status;
+ }
+
+ DevicePathSize = EfiDevicePathSize (DevicePath);
+
+ //
+ // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
+ // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |
+ //
+ BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
+ if (*StrBufferLen < BufferSize)
+ {
+ *StrBufferLen = BufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StrBufferLen = BufferSize;
+
+ StrPtr = ConfigHdr;
+
+ EfiStrCpy (StrPtr, L"GUID=");
+ StrPtr += 5;
+ BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
+ StrPtr += 32;
+
+ //
+ // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044"
+ //
+ EfiStrCpy (StrPtr, L"&NAME=");
+ StrPtr += 6;
+ if (Name != NULL)
+ {
+ BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16);
+ UnicodeToConfigString (StrPtr, &BufferSize, Name);
+ StrPtr += (NameStrLen * 4);
+ }
+
+ EfiStrCpy (StrPtr, L"&PATH=");
+ StrPtr += 6;
+ BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
+
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetBlockName
+//
+// Description:
+//
+// Parameter: EFI_STRING *Configuration, UINTN *Length, UINTN Size
+//
+// Return value: EFI_STATUS
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetBlockName(EFI_STRING *Configuration, UINTN *Length, UINTN Size)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ UINTN length = 0;
+ UINTN finalLen = 0;
+ CHAR16 *tempBuffer = NULL;
+
+ length = (EfiStrLen(L"&OFFSET=0&WIDTH=") + sizeof(Size) + 1) * sizeof(CHAR16);
+ tempBuffer = (CHAR16*)EfiLibAllocateZeroPool(length);
+ if(tempBuffer == NULL)
+ {
+ status = EFI_OUT_OF_RESOURCES;
+ goto DONE;
+ }
+
+ Swprintf_s(tempBuffer, length, L"&OFFSET=0&WIDTH=%x", Size);
+
+ length = EfiStrLen(*Configuration) * sizeof(CHAR16);
+ finalLen = (EfiStrLen(*Configuration) + EfiStrLen(tempBuffer) + 1) * sizeof(CHAR16);
+ *Configuration = MemReallocateZeroPool(*Configuration, length, finalLen);
+ if(*Configuration == NULL)
+ {
+ status = EFI_OUT_OF_RESOURCES;
+ goto DONE;
+ }
+
+ EfiStrCat(*Configuration, tempBuffer);
+
+ MemFreePointer(&tempBuffer);
+ *Length = finalLen;
+
+DONE:
+ return status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BufferToHexString
+//
+// Description: Converts binary buffer to Unicode string in reversed byte order from BufToHexString().
+//
+// Input: Str - String for output
+// Buffer - Binary buffer.
+// BufferSize - Size of the buffer in bytes.
+//
+// Output: EFI_SUCCESS - The function completed successfully.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+BufferToHexString (
+ IN OUT CHAR16 *Str,
+ IN UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *NewBuffer;
+ UINTN StrBufferLen;
+
+ NewBuffer = EfiLibAllocatePool (BufferSize);
+ MemCopy(NewBuffer, Buffer, BufferSize);
+
+ SwapBuffer (NewBuffer, BufferSize);
+
+ StrBufferLen = BufferSize * 2 + 1;
+ Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
+
+ gBS->FreePool (NewBuffer);
+ //
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
+ //
+ ToLower (Str);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UnicodeToConfigString
+//
+// Description: Convert Unicode string to binary representation Config string, e.g.
+// "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e.
+// "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>").
+//
+// Input: ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+
+// StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string.
+// Includes tailing '\0' character.
+// On output:
+// If return EFI_SUCCESS, containing length of Unicode string buffer.
+// If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired.
+// UnicodeString - Original Unicode string.
+//
+// Output: EFI_SUCCESS - Routine success.
+// EFI_BUFFER_TOO_SMALL - The string buffer is too small.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+UnicodeToConfigString (
+ IN OUT CHAR16 *ConfigString,
+ IN OUT UINTN *StrBufferLen,
+ IN CHAR16 *UnicodeString
+ )
+{
+ UINTN Index;
+ UINTN Len;
+ UINTN BufferSize;
+ CHAR16 *String;
+
+ Len = EfiStrLen (UnicodeString);
+ BufferSize = (Len * 4 + 1) * sizeof (CHAR16);
+
+ if (*StrBufferLen < BufferSize) {
+ *StrBufferLen = BufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StrBufferLen = BufferSize;
+ String = ConfigString;
+
+ for (Index = 0; Index < Len; Index++) {
+ BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2);
+
+ ConfigString += 4;
+ UnicodeString += 1;
+ }
+
+ //
+ // Add tailing '\0' character
+ //
+ *ConfigString = L'\0';
+
+ //
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
+ //
+ ToLower (String);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ToLower
+//
+// Description: Converts the unicode character of the string from uppercase to lowercase.
+//
+// Input: Str - String to be converted
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ToLower (
+ IN OUT CHAR16 *Str
+ )
+{
+ CHAR16 *Ptr;
+
+ for (Ptr = Str; *Ptr != L'\0'; Ptr++) {
+ if (*Ptr >= L'A' && *Ptr <= L'Z') {
+ *Ptr = (CHAR16) (*Ptr - L'A' + L'a');
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SwapBuffer
+//
+// Description: Swap bytes in the buffer.
+//
+// Input: Buffer - Binary buffer.
+// BufferSize - Size of the buffer in bytes.
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+SwapBuffer (
+ IN OUT UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ UINTN Index;
+ UINT8 Temp;
+ UINTN SwapCount;
+
+ SwapCount = BufferSize / 2;
+ for (Index = 0; Index < SwapCount; Index++) {
+ Temp = Buffer[Index];
+ Buffer[Index] = Buffer[BufferSize - 1 - Index];
+ Buffer[BufferSize - 1 - Index] = Temp;
+ }
+}
+
diff --git a/Core/CORE_DXE/UnicodeCollation.c b/Core/CORE_DXE/UnicodeCollation.c
new file mode 100644
index 0000000..d283af2
--- /dev/null
+++ b/Core/CORE_DXE/UnicodeCollation.c
@@ -0,0 +1,637 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*****************************************************************************
+// $Header: /Alaska/SOURCE/Core/EDK/DxeMain/UnicodeCollation.c 14 8/28/09 1:21p Felixp $
+//
+// $Revision: 14 $
+//
+// $Date: 8/28/09 1:21p $
+//*****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/EDK/DxeMain/UnicodeCollation.c $
+//
+// 14 8/28/09 1:21p Felixp
+//
+// 13 8/28/09 12:26p Felixp
+// Support for both UnicodeCollation and UnicodeCollation2 protocols
+// (based on value of the EFI_SPECIFICATION_VERSION SDL token).
+//
+// 12 7/08/09 5:53p Vyacheslava
+// Updated according to the coding standards.
+//
+// 11 3/05/09 9:53a Felixp
+// Minor big fix: Invalid return type in the StriColl funcation
+// declaration.
+//
+// 10 12/16/08 1:36a Iminglin
+// The function value of Is_valid_char for compliance.
+//
+// 9 4/24/07 5:18p Robert
+// Updated headers for CHM compatibility and coding standard compliance
+//
+// 8 10/30/06 6:34p Felixp
+// Language list is extended to fix
+// FAT driver failure when non-European
+// language is selected as a primary language.
+//
+// 3 2/15/05 5:01p Felixp
+// SpecialChars moved here from protocol header
+//
+// 2 2/03/05 4:01p Felixp
+// small bug fix in StrToFat
+//
+// 1 1/28/05 12:45p Felixp
+//
+// 3 1/18/05 3:22p Felixp
+// PrintDebugMessage renamed to Trace
+//
+// 2 12/23/04 6:25p Felixp
+// bug fix in StrToFat
+//
+// 7 12/22/04 9:33a Radhikav
+// proper comments added
+//
+// 6 12/20/04 4:00p Radhikav
+// made changes to strtofat and metaimatch.
+//
+// 5 12/08/04 1:22p Radhikav
+// made some changes to StrtoFat function.
+//
+// 4 11/11/04 11:18a Felixp
+//
+// 3 10/18/04 1:30p Radhikav
+// modified metaimatch routine.
+//
+// 2 10/08/04 3:57p Radhikav
+// modified strlwr and strupper routines.
+//
+// 1 10/05/04 2:47p Radhikav
+// Initial check in.
+//
+//*****************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Unicode Collation.c
+//
+// Description: Provides Unicode String functions
+//
+//<AMI_FHDR_END>
+//*****************************************************************************
+#include <Protocol/UnicodeCollation.h>
+#include <AmiDxeLib.h>
+
+//----------------------------------------------------------------------
+// functions prototype
+
+INTN StriColl (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *S1,
+ IN CHAR16 *S2
+
+);
+BOOLEAN MetaiMatch (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *String,
+ IN CHAR16 *Patern
+
+);
+BOOLEAN StrToFat (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *String,
+ IN UINTN FatSize,
+ OUT CHAR8 *Fat
+);
+VOID FatToStr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN UINTN FatSize,
+ IN CHAR8 *Fat,
+ OUT CHAR16 *String
+);
+VOID StrLwr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN OUT CHAR16 *String
+);
+VOID EFIAPI StrUpr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN OUT CHAR16 *String
+);
+BOOLEAN is_valid_char(CHAR16 valid);
+CHAR16 toupper(CHAR16 Data);
+CHAR16 tolower(CHAR16 Value);
+
+//----------------------------------------------------------------------
+// Protocol Definitions
+EFI_UNICODE_COLLATION_PROTOCOL UnicodeCollationProtocol = {
+ StriColl,
+ MetaiMatch,
+ StrLwr,
+ StrUpr,
+ FatToStr,
+ StrToFat,
+ LANGUAGE_CODE_ENGLISH
+};
+
+CHAR8 SpecialChars[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '\\', '.', '_', '^', '$', '~', '!', '#', '%', '&',
+ '-', '{', '}', '(', ')', '@', '`', '\'', '\0'
+};
+
+//----------------------------------------------------------------------
+// Function Defintions
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: UnicodeCollationDriverEntryPoint
+//
+// Description: Initializes the Unicode Collation Driver
+//
+// Input:
+// ImageHandle - EFI Handle for the Unicode Collation Protocol
+// *SystemTable - Pointer to the EFI System Table
+//
+// Output: EFI_STATUS
+//
+// Referrals: InstallProtocolInterface
+//
+// Notes:
+// Here is the control flow of this function:
+// 1. Initialize Ami Lib.
+// 2. Install Driver Binding Protocol
+// 3. Return EFI_SUCCESS.
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+EFI_STATUS UnicodeCollationEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ Status = SystemTable->BootServices->InstallProtocolInterface(
+ &Handle,
+ &gEfiUnicodeCollation2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UnicodeCollationProtocol
+ );
+ return Status;
+}
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: Stricoll
+//
+// Description: Performs a case-insensitive comparison of two
+// Null-terminated unicode strings.
+//
+// Input:
+// *This - pointer to the Unicode Collatioon Protocol
+// *s1 - string one
+// *s2 - string two
+//
+// Output: None
+//
+// Return:
+// 0 - if strings are equal
+// negative value - if s1 is less than s2
+// positive value - if s2 is less than s2
+//
+// Modified: None
+//
+// Referrals: tolower
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+INTN EFIAPI StriColl (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *s1,
+ IN CHAR16 *s2
+)
+{
+ INTN result;
+
+ do {
+ result = tolower(*s1) - tolower(*s2);
+
+ if (result)
+ break;
+ } while ( (*s1++) && (*s2++) );
+
+ return result;
+}
+
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: StrLwr
+//
+// Description: Converts all the unicode charecters in a
+// Null-terminated string to lowercase unicode.
+//
+// Input:
+// *This - pointer to the UnicodeCollation Protocol
+// *String - String to convert to lower case
+//
+// Output: *String - String now in lower case
+//
+// Modified: *String
+//
+// Referrals: tolower
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+VOID EFIAPI StrLwr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN OUT CHAR16 *String
+)
+{
+ CHAR16 *s = String;
+
+ while (*s != L'\0') {
+ *s = tolower(*s);
+ s++;
+ };
+
+}
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: StrUpr
+//
+// Description: Converts all the unicodecharecters in a Null terminated
+// unicode string to a uppercase unicode charecters.
+//
+// Input:
+// *This - pointer to the UnicodeCollation Protocol
+// *String - String to convert to upper case
+//
+// Output: *String - String now in lower case
+//
+// Modified: *String
+//
+// Referrals: toupper
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+VOID EFIAPI StrUpr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN OUT CHAR16 *String
+)
+{
+ CHAR16 *s = String;
+
+ while (*s != L'\0') {
+ *s = toupper(*s);
+ s++ ;
+ };
+}
+
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: MetaiMatch
+//
+// Description: Performs a case insensitive comparision of a
+// Null-terminated unicode pattern string and a null terminated
+// unicode String Converts all the unicodecharecters in a Null terminated
+// unicode string.
+//
+// Input:
+// *This - pointer to the UnicodeCollation Protocol
+// *String - String to convert to upper case
+// *Pattern
+// Output:
+// TRUE - Pattern was found in String.
+// FALSE - Pattern was not found in String.
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+BOOLEAN EFIAPI MetaiMatch (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *String,
+ IN CHAR16 *Pattern
+)
+{
+ CHAR16 ch1, ch, temp;
+ UINTN len1, len2;
+
+ for (; ;) {
+ len1 = Wcslen(String);
+ len2 = Wcslen(Pattern);
+
+ if (!len1) {
+ if (!len2)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ ch1 = *Pattern;
+ Pattern ++;
+
+ switch (ch1) {
+
+ if (*String)
+ return FALSE;
+ else
+ return TRUE ;
+
+ case '*':
+ while (*String) {
+ if (MetaiMatch(This, String, Pattern))
+ return TRUE;
+
+ String ++;
+ }
+
+ return MetaiMatch(This, String, Pattern);
+
+ case '?':
+ if (!*String)
+ return FALSE;
+
+ String ++;
+ break;
+
+ case '[':
+ ch = *String;
+
+ if (!ch)
+ return FALSE;
+
+ temp = 0;
+ ch1 = *Pattern++;
+
+ while ( ch1 ) {
+ if (ch1 == ']')
+ return FALSE;
+
+ if (ch1 == '-') {
+ ch1 = *Pattern;
+
+ if ( ch1 == 0 || ch1 == ']' )
+ return FALSE;
+
+ if ( toupper(ch) >= toupper(temp) &&
+ toupper(ch) <= toupper(ch1) )
+ break;
+ }
+
+ temp = ch1;
+
+ if ( toupper(ch) == toupper(ch1) ) //any charecter
+ break;
+
+ ch1 = *Pattern++;
+ }
+
+ while (ch1 && ch1 != ']') {
+ ch1 = *Pattern;
+ Pattern ++;
+ }
+
+ String ++;
+ break;
+
+ default:
+ ch = *String;
+
+ if ( toupper(ch) != toupper(ch1) )
+ return FALSE;
+
+ String ++;
+ break;
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: FatToString
+//
+// Description: Converts an 8.3 FAT file name in an OEM charecter set
+// to a Null-terminated Unicode string.
+//
+// Input:
+// *This - Pointer to the Unicode Collation Protocol
+// *FatSize - size of the FAT string
+// *Fat - 8.3 FAT ascii string
+// Output:
+// *String - Null terminated Unicode String
+//
+// Return: VOID
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+VOID EFIAPI FatToStr (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN UINTN FatSize,
+ IN CHAR8 *Fat,
+ OUT CHAR16 *String
+)
+{
+ for (; (*Fat && FatSize) != 0; String++, Fat++, FatSize --)
+ *String = *Fat;
+
+ *String = 0;
+}
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: StrtoFat
+//
+// Description: Converts a Null-terminated unicode string to legal
+// characters in a FAT file using an OEM charecter set. Converts all
+// the unicodecharecters in a Null terminated unicode string.
+//
+// Input:
+// *This - Pointer to the Unicode Collation Protocol
+// *FatSize - size of the FAT string
+// *String - Null terminated Unicode String
+// Output:
+// *Fat - 8.3 FAT ascii string
+//
+// Return:
+// TRUE - Pattern was found in String.
+// FALSE - Pattern was not found in String.
+//
+// Referrals: toupper
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+BOOLEAN StrToFat (
+ IN EFI_UNICODE_COLLATION_PROTOCOL *This,
+ IN CHAR16 *String,
+ IN UINTN FatSize,
+ OUT CHAR8 *Fat
+)
+{
+ BOOLEAN InvalidChar;
+ int i = 0, j = 0;
+
+ InvalidChar = FALSE;
+
+ while (String[i] && FatSize) {
+
+ if ( String[i] != 0x002E &&
+ String[i] != 0x0020 ) {
+
+ if ( is_valid_char(String[i]) == 1 ) {
+ Fat[j] = (CHAR8)toupper(String[i]);
+ j++;
+
+ } else {
+ Fat[j] = '_';
+ InvalidChar = TRUE;
+ j++;
+ }
+
+ FatSize --;
+ }
+
+ i++;
+ }
+
+ return(InvalidChar);
+}
+
+//----------------------------------------------------------------------
+//Local functions
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: is_valid_char
+//
+// Description: Checks to see if the character passed in is a valid.
+// ASCII Character
+//
+// Input: valid - character to check
+//
+// Return:
+// TRUE - Character is valid
+// FALSE - Character is invalid
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+BOOLEAN is_valid_char(CHAR16 valid)
+{
+ UINT16 i;
+ CHAR16 tempval;
+
+ if ( (valid >= 0x0061 && valid <= 0x007a) ||
+ (valid >= 0x00E0 && valid <= 0x00F6) ||
+ (valid >= 0x00F8 && valid <= 0x00Fe) )
+ return TRUE;
+
+ else if ( (valid >= 0x0041 && valid <= 0x005a) ||
+ (valid >= 0x00C0 && valid <= 0x00D6) ||
+ (valid >= 0x00D8 && valid <= 0x00DE) )
+ return TRUE;
+
+ else {
+ tempval = (CHAR16)valid;
+
+ for ( i=0; SpecialChars[i]; i++ ) {
+ if (tempval == SpecialChars[i])
+ return TRUE;
+ }
+ }
+
+ return (FALSE);
+}
+
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: tolower
+//
+// Description: Converts Unicode standard European characters to lower case
+//
+// Input: Data - character to convert
+//
+// Return: the Unicode character in lower case Unicode format
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+CHAR16 tolower( CHAR16 Data )
+{
+ if ( ('A' <= Data && Data <= 'Z') ||
+ (Data >= 0xC0 && Data <= 0xD6) ||
+ (Data >= 0xD8 && Data <= 0xDE) )
+ return (CHAR16)(Data + 0x20);
+ else
+ return Data;
+}
+
+
+//----------------------------------------------------------------------
+//<AMI_PHDR_START>
+//
+// Procedure: toupper
+//
+// Description: Converts Unicode standard Europeancharacters to upper case
+//
+// Input: Value - character to convert
+//
+// Return: the character in upper case Unicode format
+//
+//<AMI_PHDR_END>
+//----------------------------------------------------------------------
+
+CHAR16 toupper( CHAR16 Value )
+{
+ if ( ('a' <= Value && Value <= 'z') ||
+ (Value >= 0xE0 && Value <= 0xF6) ||
+ (Value >= 0xF8 && Value <= 0xFE) )
+ return (CHAR16)(Value - 0x20);
+ else
+ return Value;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/CORE_DXE/dependency.c b/Core/CORE_DXE/dependency.c
new file mode 100644
index 0000000..b08c5bf
--- /dev/null
+++ b/Core/CORE_DXE/dependency.c
@@ -0,0 +1,451 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ dependency.c
+
+Abstract:
+
+ DXE Dispatcher Dependency Evaluator
+
+ This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
+ if a driver can be scheduled for execution. The criteria for
+ schedulability is that the dependency expression is satisfied.
+
+--*/
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "EfiDependency.h"
+
+//
+// Global stack used to evaluate dependency expressions
+//
+BOOLEAN *mDepexEvaluationStack = NULL;
+BOOLEAN *mDepexEvaluationStackEnd = NULL;
+BOOLEAN *mDepexEvaluationStackPointer = NULL;
+
+//
+// Worker functions
+//
+
+STATIC
+EFI_STATUS
+GrowDepexStack (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Grow size of the Depex stack
+
+Arguments:
+
+ Stack - Old stack on the way in and new stack on the way out
+
+ StackSize - New size of the stack
+
+Returns:
+
+ EFI_SUCCESS - Stack successfully growed.
+
+ EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
+
+
+
+--*/
+{
+ BOOLEAN *NewStack;
+ UINTN Size;
+
+ Size = DEPEX_STACK_SIZE_INCREMENT;
+ if (mDepexEvaluationStack != NULL) {
+ Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
+ }
+
+ NewStack = CoreAllocateBootServicesPool (Size * sizeof (BOOLEAN));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (mDepexEvaluationStack != NULL) {
+ //
+ // Copy to Old Stack to the New Stack
+ //
+ EfiCommonLibCopyMem (
+ NewStack,
+ mDepexEvaluationStack,
+ (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ CoreFreePool (mDepexEvaluationStack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
+ mDepexEvaluationStack = NewStack;
+ mDepexEvaluationStackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+PushBool (
+ IN BOOLEAN Value
+ )
+/*++
+
+Routine Description:
+
+ Push an element onto the Boolean Stack
+
+Arguments:
+
+ Value - BOOLEAN to push.
+
+Returns:
+
+ EFI_SUCCESS - The value was pushed onto the stack.
+
+ EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowDepexStack ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ *mDepexEvaluationStackPointer = Value;
+ mDepexEvaluationStackPointer++;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+PopBool (
+ OUT BOOLEAN *Value
+ )
+/*++
+
+Routine Description:
+
+ Pop an element from the Boolean stack.
+
+Arguments:
+
+ Value - BOOLEAN to pop.
+
+Returns:
+
+ EFI_SUCCESS - The value was popped onto the stack.
+
+ EFI_ACCESS_DENIED - The pop operation underflowed the stack
+
+--*/
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ mDepexEvaluationStackPointer--;
+ *Value = *mDepexEvaluationStackPointer;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CorePreProcessDepex (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ Preprocess dependency expression and update DriverEntry to reflect the
+ state of Before, After, and SOR dependencies. If DriverEntry->Before
+ or DriverEntry->After is set it will never be cleared. If SOR is set
+ it will be cleared by CoreSchedule(), and then the driver can be
+ dispatched.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ EFI_SUCCESS - It always works.
+
+--*/
+{
+ UINT8 *Iterator;
+
+ Iterator = DriverEntry->Depex;
+ if (*Iterator == EFI_DEP_SOR) {
+ DriverEntry->Unrequested = TRUE;
+ } else {
+ DriverEntry->Dependent = TRUE;
+ }
+
+ if (*Iterator == EFI_DEP_BEFORE) {
+ DriverEntry->Before = TRUE;
+ } else if (*Iterator == EFI_DEP_AFTER) {
+ DriverEntry->After = TRUE;
+ }
+
+ if (DriverEntry->Before || DriverEntry->After) {
+ EfiCommonLibCopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+BOOLEAN
+CoreIsSchedulable (
+ IN EFI_CORE_DRIVER_ENTRY *DriverEntry
+ )
+/*++
+
+Routine Description:
+
+ This is the POSTFIX version of the dependency evaluator. This code does
+ not need to handle Before or After, as it is not valid to call this
+ routine in this case. The SOR is just ignored and is a nop in the grammer.
+
+ POSTFIX means all the math is done on top of the stack.
+
+Arguments:
+
+ DriverEntry - DriverEntry element to update
+
+Returns:
+
+ TRUE - If driver is ready to run.
+ FALSE - If driver is not ready to run or some fatal error was found.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *Iterator;
+ BOOLEAN Operator;
+ BOOLEAN Operator2;
+ EFI_GUID DriverGuid;
+ VOID *Interface;
+
+ if (DriverEntry->After || DriverEntry->Before) {
+ //
+ // If Before or After Depex skip as CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ()
+ // processes them.
+ //
+ return FALSE;
+ }
+
+ if (DriverEntry->Depex == NULL) {
+ //
+ // A NULL Depex means treat the driver like an EFI 1.0 thing.
+ //
+ Status = CoreAllEfiServicesAvailable ();
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ //
+ // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
+ // incorrectly formed DEPEX expressions
+ //
+ mDepexEvaluationStackPointer = mDepexEvaluationStack;
+
+
+ Iterator = DriverEntry->Depex;
+
+ while (TRUE) {
+ //
+ // Check to see if we are attempting to fetch dependency expression instructions
+ // past the end of the dependency expression.
+ //
+ if (((UINTN) Iterator - (UINTN) DriverEntry->Depex) >= DriverEntry->DepexSize) {
+ return FALSE;
+ }
+
+ //
+ // Look at the opcode of the dependency expression instruction.
+ //
+ switch (*Iterator) {
+ case EFI_DEP_BEFORE:
+ case EFI_DEP_AFTER:
+ //
+ // For a well-formed Dependency Expression, the code should never get here.
+ // The BEFORE and AFTER are processed prior to this routine's invocation.
+ // If the code flow arrives at this point, there was a BEFORE or AFTER
+ // that were not the first opcodes.
+ //
+ ASSERT (FALSE);
+ case EFI_DEP_SOR:
+ //
+ // These opcodes can only appear once as the first opcode. If it is found
+ // at any other location, then the dependency expression evaluates to FALSE
+ //
+ if (Iterator != DriverEntry->Depex) {
+ return FALSE;
+ }
+ //
+ // Otherwise, it is the first opcode and should be treated as a NOP.
+ //
+ break;
+
+ case EFI_DEP_PUSH:
+ //
+ // Push operator is followed by a GUID. Test to see if the GUID protocol
+ // is installed and push the boolean result on the stack.
+ //
+ EfiCommonLibCopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));
+
+ Status = CoreLocateProtocol (&DriverGuid, NULL, &Interface);
+
+ if (EFI_ERROR (Status)) {
+ Status = PushBool (FALSE);
+ } else {
+ *Iterator = EFI_DEP_REPLACE_TRUE;
+ Status = PushBool (TRUE);
+ }
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+
+ case EFI_DEP_AND:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN) (Operator && Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_OR:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PopBool (&Operator2);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN) (Operator || Operator2));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_NOT:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Status = PushBool ((BOOLEAN) (!Operator));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_FALSE:
+ Status = PushBool (FALSE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ break;
+
+ case EFI_DEP_END:
+ Status = PopBool (&Operator);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return Operator;
+
+ case EFI_DEP_REPLACE_TRUE:
+ Status = PushBool (TRUE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ Iterator += sizeof (EFI_GUID);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ //
+ // Skip over the Dependency Op Code we just processed in the switch.
+ // The math is done out of order, but it should not matter. That is
+ // we may add in the sizeof (EFI_GUID) before we account for the OP Code.
+ // This is not an issue, since we just need the correct end result. You
+ // need to be careful using Iterator in the loop as it's intermediate value
+ // may be strange.
+ //
+ Iterator++;
+ }
+ return FALSE;
+}
+
diff --git a/Core/CORE_DXE/event.c b/Core/CORE_DXE/event.c
new file mode 100644
index 0000000..1f61db3
--- /dev/null
+++ b/Core/CORE_DXE/event.c
@@ -0,0 +1,867 @@
+/*++
+
+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:
+
+ event.c
+
+Abstract:
+
+ EFI Event support.
+
+--*/
+
+#include "exec.h"
+#include "hand.h"
+
+//
+// Enumerate the valid types
+//
+UINT32 mEventTable[] = {
+ //
+ // 0x80000200 Timer event with a notification function that is
+ // queue when the event is signaled with SignalEvent()
+ //
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ //
+ // 0x80000000 Timer event without a notification function. It can be
+ // signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().
+ //
+ EFI_EVENT_TIMER,
+ //
+ // 0x00000100 Generic event with a notification function that
+ // can be waited on with CheckEvent() or WaitForEvent()
+ //
+ EFI_EVENT_NOTIFY_WAIT,
+ //
+ // 0x00000200 Generic event with a notification function that
+ // is queue when the event is signaled with SignalEvent()
+ //
+ EFI_EVENT_NOTIFY_SIGNAL,
+ //
+ // 0x00000201 ExitBootServicesEvent.
+ //
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ //
+ // 0x60000202 SetVirtualAddressMapEvent.
+ //
+ EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+ //
+ // 0x00000203 ReadyToBootEvent.
+ //
+ EFI_EVENT_SIGNAL_READY_TO_BOOT,
+ //
+ // 0x00000204 LegacyBootEvent.
+ //
+ EFI_EVENT_SIGNAL_LEGACY_BOOT,
+ //
+ // 0x00000603 Signal all ReadyToBootEvents.
+ //
+ EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT,
+ //
+ // 0x00000604 Signal all LegacyBootEvents.
+ //
+ EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT,
+#endif
+ //
+ // 0x00000000 Generic event without a notification function.
+ // It can be signaled with SignalEvent() and checked with CheckEvent()
+ // or WaitForEvent().
+ //
+ 0x00000000,
+ //
+ // 0x80000100 Timer event with a notification function that can be
+ // waited on with CheckEvent() or WaitForEvent()
+ //
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT,
+};
+
+
+VOID
+CoreAcquireEventLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by acquiring the lock on gEventQueueLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gEventQueueLock);
+}
+
+
+VOID
+CoreReleaseEventLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing the lock on gEventQueueLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gEventQueueLock);
+}
+
+
+EFI_STATUS
+CoreInitializeEventServices (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes "event" support and populates parts of the System and Runtime Table.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Always return success
+
+--*/
+{
+ UINTN Index;
+
+ for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index ++) {
+ InitializeListHead (&gEventQueue[Index]);
+ }
+
+ CoreInitializeTimer ();
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CoreDispatchEventNotifies (
+ IN EFI_TPL Priority
+ )
+/*++
+
+Routine Description:
+
+ Dispatches all pending events.
+
+Arguments:
+
+ Priority - The task priority level of event notifications to dispatch
+
+Returns:
+
+ None
+
+--*/
+{
+ IEVENT *Event;
+ EFI_LIST_ENTRY *Head;
+
+ CoreAcquireEventLock ();
+ ASSERT (gEventQueueLock.OwnerTpl == Priority);
+ Head = &gEventQueue[Priority];
+
+ //
+ // Dispatch all the pending notifications
+ //
+ while (!IsListEmpty (Head)) {
+
+ Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
+ RemoveEntryList (&Event->NotifyLink);
+
+ Event->NotifyLink.ForwardLink = NULL;
+
+ //
+ // Only clear the SIGNAL status if it is a SIGNAL type event.
+ // WAIT type events are only cleared in CheckEvent()
+ //
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ Event->SignalCount = 0;
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // Notify this event
+ //
+ Event->NotifyFunction (Event, Event->NotifyContext);
+
+ //
+ // Check for next pending event
+ //
+ CoreAcquireEventLock ();
+ }
+
+ gEventPending &= ~(1 << Priority);
+ CoreReleaseEventLock ();
+}
+
+
+VOID
+STATIC
+CoreNotifyEvent (
+ IN IEVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ Queues the event's notification function to fire
+
+Arguments:
+
+ Event - The Event to notify
+
+Returns:
+
+ None
+
+--*/
+{
+
+ //
+ // Event database must be locked
+ //
+ ASSERT_LOCKED (&gEventQueueLock);
+
+ //
+ // If the event is queued somewhere, remove it
+ //
+
+ if (Event->NotifyLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->NotifyLink);
+ Event->NotifyLink.ForwardLink = NULL;
+ }
+
+ //
+ // Queue the event to the pending notification list
+ //
+
+ InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
+ gEventPending |= (UINTN)1 << Event->NotifyTpl;
+}
+
+
+
+VOID
+CoreNotifySignalList (
+ IN EFI_GUID *EventGroup
+ )
+/*++
+
+Routine Description:
+
+ Signals all events on the requested list
+
+Arguments:
+
+ SignalType - The list to signal
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY *Head;
+ IEVENT *Event;
+
+ CoreAcquireEventLock ();
+
+ Head = &gEventSignalQueue;
+ for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
+ Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
+ if ((Event->ExFlag) && EfiCompareGuid (&Event->EventGroup, EventGroup)) {
+ CoreNotifyEvent (Event);
+ }
+ }
+
+ CoreReleaseEventLock ();
+}
+
+//*** AMI PORTING BEGIN ***//
+// UEFI 2.0 handling of Ready to Boot and Legacy Boot events is not
+// backward compatible.
+// It can break customer's code
+// Let's make the Core backward compatible
+#if 1
+//#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+//*** AMI PORTING END *****//
+
+static
+VOID
+EFIAPI
+EventNotifySignalAllNullEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // This null event is a size efficent way to enusre that
+ // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly.
+ // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into
+ // CreateEventEx() and this function is used to make the
+ // old error checking in CreateEvent() for Tiano extensions
+ // function.
+ //
+ return;
+}
+
+#endif
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEvent (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ Creates a general-purpose event structure
+
+Arguments:
+
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+{
+ EFI_GUID *GuidPtr;
+ EFI_EVENT_NOTIFY Function;
+
+ GuidPtr = NULL;
+ Function = NotifyFunction;
+
+//*** AMI PORTING BEGIN ***//
+// To make even handling backward compatible.
+// See also comments above.
+#if 1
+//#if (EFI_SPECIFICATION_VERSION < 0x00020000)
+//*** AMI PORTING END *****//
+ //
+ // Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the
+ // EventGroup now have this property. So we need to filter it out.
+ //
+ if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) {
+ Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL;
+ Function = EventNotifySignalAllNullEvent;
+ }
+
+ //
+ // Map the Tiano extensions Events to CreateEventEx form
+ //
+ if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) {
+ GuidPtr = &gEfiEventReadyToBootGuid;
+//*** AMI PORTING BEGIN ***//
+// To make even handling backward compatible.
+// See also comments above.
+ Type = EFI_EVENT_NOTIFY_SIGNAL;
+//*** AMI PORTING END *****//
+ } else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) {
+ GuidPtr = &gEfiEventLegacyBootGuid;
+//*** AMI PORTING BEGIN ***//
+// To make even handling backward compatible.
+// See also comments above.
+ Type = EFI_EVENT_NOTIFY_SIGNAL;
+//*** AMI PORTING END *****//
+ }
+#endif
+
+ //
+ // Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping
+ //
+ if (Type == EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES) {
+ Type = 0;
+ GuidPtr = &gEfiEventExitBootServicesGuid;
+ } else if (Type == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
+ Type = 0;
+ GuidPtr = &gEfiEventVirtualAddressChangeGuid;
+ }
+
+ return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event);
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCreateEventEx (
+ IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ IN CONST EFI_GUID *EventGroup, OPTIONAL
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+ Creates a general-purpose event structure
+
+Arguments:
+ Type - The type of event to create and its mode and attributes
+ NotifyTpl - The task priority level of event notifications
+ NotifyFunction - Pointer to the events notification function
+ NotifyContext - Pointer to the notification functions context; corresponds to
+ parameter "Context" in the notification function
+ EventGroup - GUID for EventGroup if NULL act the same as gBS->CreateEvent().
+ Event - Pointer to the newly created event if the call succeeds; undefined otherwise
+
+Returns:
+ EFI_SUCCESS - The event structure was created
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value
+ EFI_OUT_OF_RESOURCES - The event could not be allocated
+
+--*/
+{
+ EFI_STATUS Status;
+ IEVENT *IEvent;
+ INTN Index;
+
+
+ if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For event group, type EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES and EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+ // are not valid
+ //
+ if (EventGroup != NULL) {
+ if ((Type == EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Check to make sure no reserved flags are set
+ //
+ Status = EFI_INVALID_PARAMETER;
+ for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
+ if (Type == mEventTable[Index]) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ if(EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Convert Event type for pre-defined Event groups
+ //
+ if (EventGroup != NULL) {
+ if (EfiCompareGuid ((VOID *) EventGroup, &gEfiEventExitBootServicesGuid)) {
+ Type = EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES;
+ } else if (EfiCompareGuid ((VOID *) EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
+ Type = EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
+ }
+ }
+
+ //
+ // If it's a notify type of event, check its parameters
+ //
+ if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) {
+ //
+ // Check for an invalid NotifyFunction or NotifyTpl
+ //
+ if ((NotifyFunction == NULL) ||
+ (NotifyTpl < EFI_TPL_APPLICATION) ||
+ (NotifyTpl >= EFI_TPL_HIGH_LEVEL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ } else {
+ //
+ // No notification needed, zero ignored values
+ //
+ NotifyTpl = 0;
+ NotifyFunction = NULL;
+ NotifyContext = NULL;
+ }
+
+ //
+ // Allcoate and initialize a new event structure.
+ //
+ Status = CoreAllocatePool (
+ (Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData,
+ sizeof (IEVENT),
+ (VOID **)&IEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EfiCommonLibSetMem (IEvent, sizeof (IEVENT), 0);
+
+ IEvent->Signature = EVENT_SIGNATURE;
+ IEvent->Type = Type;
+ IEvent->NotifyTpl = NotifyTpl;
+ IEvent->NotifyFunction = NotifyFunction;
+ IEvent->NotifyContext = (VOID *)NotifyContext;
+ if (EventGroup != NULL) {
+ EfiCommonLibCopyMem (&IEvent->EventGroup, (VOID*)EventGroup, sizeof (EFI_GUID));
+ IEvent->ExFlag = TRUE;
+ }
+
+ *Event = IEvent;
+
+ if (Type & EFI_EVENT_RUNTIME) {
+ //
+ // Keep a list of all RT events so we can tell the RT AP.
+ //
+ IEvent->RuntimeData.Type = Type;
+ IEvent->RuntimeData.NotifyTpl = NotifyTpl;
+ IEvent->RuntimeData.NotifyFunction = NotifyFunction;
+ IEvent->RuntimeData.NotifyContext = NotifyContext;
+ IEvent->RuntimeData.Event = (EFI_EVENT *) IEvent;
+ InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
+ }
+
+ CoreAcquireEventLock ();
+
+ if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) {
+ //
+ // The Event's NotifyFunction must be queued whenever the event is signaled
+ //
+ InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSignalEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Signals the event. Queues the event to be notified if needed
+
+Arguments:
+
+ UserEvent - The event to signal
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event was signaled.
+
+--*/
+{
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireEventLock ();
+
+ //
+ // If the event is not already signalled, do so
+ //
+
+ if (Event->SignalCount == 0x00000000) {
+ Event->SignalCount ++;
+
+ //
+ // If signalling type is a notify function, queue it
+ //
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ if (Event->ExFlag) {
+ //
+ // The CreateEventEx() style requires all members of the Event Group
+ // to be signaled.
+ //
+ CoreReleaseEventLock ();
+ CoreNotifySignalList (&Event->EventGroup);
+ CoreAcquireEventLock ();
+ } else {
+ CoreNotifyEvent (Event);
+ }
+ }
+ }
+
+ CoreReleaseEventLock ();
+ return EFI_SUCCESS;
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCheckEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Check the status of an event
+
+Arguments:
+
+ UserEvent - The event to check
+
+Returns:
+
+ EFI_SUCCESS - The event is in the signaled state
+ EFI_NOT_READY - The event is not in the signaled state
+ EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL
+
+--*/
+
+{
+ IEVENT *Event;
+ EFI_STATUS Status;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_READY;
+
+ if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) {
+
+ //
+ // Queue the wait notify function
+ //
+
+ CoreAcquireEventLock ();
+ if (!Event->SignalCount) {
+ CoreNotifyEvent (Event);
+ }
+ CoreReleaseEventLock ();
+ }
+
+ //
+ // If the even looks signalled, get the lock and clear it
+ //
+
+ if (Event->SignalCount) {
+ CoreAcquireEventLock ();
+
+ if (Event->SignalCount) {
+ Event->SignalCount = 0;
+ Status = EFI_SUCCESS;
+ }
+
+ CoreReleaseEventLock ();
+ }
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreWaitForEvent (
+ IN UINTN NumberOfEvents,
+ IN EFI_EVENT *UserEvents,
+ OUT UINTN *UserIndex
+ )
+/*++
+
+Routine Description:
+
+ Stops execution until an event is signaled.
+
+Arguments:
+
+ NumberOfEvents - The number of events in the UserEvents array
+ UserEvents - An array of EFI_EVENT
+ UserIndex - Pointer to the index of the event which satisfied the wait condition
+
+Returns:
+
+ EFI_SUCCESS - The event indicated by Index was signaled.
+ EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or
+ Event was not a valid type
+ EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION
+
+--*/
+
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ //
+ // Can only WaitForEvent at TPL_APPLICATION
+ //
+ if (gEfiCurrentTpl != EFI_TPL_APPLICATION) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for(;;) {
+
+ for(Index = 0; Index < NumberOfEvents; Index++) {
+
+ Status = CoreCheckEvent (UserEvents[Index]);
+
+ //
+ // provide index of event that caused problem
+ //
+ if (Status != EFI_NOT_READY) {
+ *UserIndex = Index;
+ return Status;
+ }
+ }
+
+ //
+ // This was the location of the Idle loop callback in EFI 1.x reference
+ // code. We don't have that concept in this base at this point.
+ //
+ }
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreCloseEvent (
+ IN EFI_EVENT UserEvent
+ )
+/*++
+
+Routine Description:
+
+ Closes an event and frees the event structure.
+
+Arguments:
+
+ UserEvent - Event to close
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameters are not valid.
+
+ EFI_SUCCESS - The event has been closed
+
+--*/
+
+{
+ EFI_STATUS Status;
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If it's a timer event, make sure it's not pending
+ //
+ if (Event->Type & EFI_EVENT_TIMER) {
+ CoreSetTimer (Event, TimerCancel, 0);
+ }
+
+ CoreAcquireEventLock ();
+
+ //
+ // If the event is queued somewhere, remove it
+ //
+
+ if (Event->RuntimeData.Link.ForwardLink != NULL) {
+ RemoveEntryList (&Event->RuntimeData.Link);
+ }
+
+ if (Event->NotifyLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->NotifyLink);
+ }
+
+ if (Event->SignalLink.ForwardLink != NULL) {
+ RemoveEntryList (&Event->SignalLink);
+ }
+
+ CoreReleaseEventLock ();
+
+ //
+ // If the event is registered on a protocol notify,
+ // then remove it from the protocol database
+ //
+ CoreUnregisterProtocolNotify (Event);
+
+ Status = CoreFreePool (Event);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Core/CORE_DXE/exec.h b/Core/CORE_DXE/exec.h
new file mode 100644
index 0000000..2abdc90
--- /dev/null
+++ b/Core/CORE_DXE/exec.h
@@ -0,0 +1,209 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ exec.h
+
+Abstract:
+
+ EFI Event support
+
+--*/
+
+#ifndef _EXEC_H_
+#define _EXEC_H_
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+#define VALID_TPL(a) ((a) <= EFI_TPL_HIGH_LEVEL)
+
+//
+// EFI_EVENT
+//
+
+#define EVENT_SIGNATURE EFI_SIGNATURE_32('e','v','n','t')
+typedef struct {
+ UINTN Signature;
+ UINT32 Type;
+ UINT32 SignalCount;
+
+ //
+ // Entry if the event is registered to be signalled
+ //
+
+ EFI_LIST_ENTRY SignalLink;
+
+ //
+ // Notification information for this event
+ //
+
+ EFI_TPL NotifyTpl;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_GUID EventGroup;
+ EFI_LIST_ENTRY NotifyLink;
+ BOOLEAN ExFlag;
+
+ //
+ // A list of all runtime events
+ //
+ EFI_RUNTIME_EVENT_ENTRY RuntimeData;
+
+ //
+ // Information by event type
+ //
+
+ union {
+ //
+ // For timer events
+ //
+ struct {
+ EFI_LIST_ENTRY Link;
+ UINT64 TriggerTime;
+ UINT64 Period;
+ } Timer;
+ } u;
+
+} IEVENT;
+
+//
+// Internal prototypes
+//
+
+VOID
+CoreDispatchEventNotifies (
+ IN EFI_TPL Priority
+ )
+/*++
+
+Routine Description:
+
+ Dispatches all pending events.
+
+Arguments:
+
+ Priority - The task priority level of event notifications to dispatch
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+UINTN
+CoreHighestSetBit (
+ IN UINTN Number
+ )
+/*++
+
+Routine Description:
+
+ Return the highest set bit
+
+Arguments:
+
+ Number - The value to check
+
+Returns:
+
+ Bit position of the highest set bit
+
+--*/
+;
+
+
+BOOLEAN
+GetInterruptState (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Disables CPU 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.
+
+--*/
+;
+
+//
+// Exported functions
+//
+
+VOID
+CoreEventVirtualAddressFixup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ A function out of date, should be removed.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+VOID
+CoreInitializeTimer (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes timer support
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+//
+// extern data declarations
+//
+
+extern EFI_LOCK gEventQueueLock;
+extern UINTN gEventPending;
+extern EFI_LIST_ENTRY gEventQueue[];
+extern EFI_LIST_ENTRY gEventSignalQueue;
+extern UINT8 gHSB[];
+
+#endif
diff --git a/Core/CORE_DXE/execdata.c b/Core/CORE_DXE/execdata.c
new file mode 100644
index 0000000..284b89b
--- /dev/null
+++ b/Core/CORE_DXE/execdata.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ execdata.c
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include "exec.h"
+
+
+//
+// gTpl - Task priority level
+//
+EFI_TPL gEfiCurrentTpl = EFI_TPL_DRIVER;
+
+
+//
+// gEventQueueLock - Protects the event queus
+//
+EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+
+//
+// gEventQueue - A list of event's to notify for each priority level
+// gEventPending - A bitmask of the EventQueues that are pending
+//
+EFI_LIST_ENTRY gEventQueue[EFI_TPL_HIGH_LEVEL + 1];
+UINTN gEventPending = 0;
+
+//
+// gEventSignalQueue - A list of events to signal when the EFI operation occurs
+//
+EFI_LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);
+
diff --git a/Core/CORE_DXE/gcd.c b/Core/CORE_DXE/gcd.c
new file mode 100644
index 0000000..4080672
--- /dev/null
+++ b/Core/CORE_DXE/gcd.c
@@ -0,0 +1,2472 @@
+/*++
+
+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:
+
+ gcd.c
+
+Abstract:
+
+ The file contains the GCD related services in the EFI Boot Services Table.
+ The GCD services are used to manage the memory and I/O regions that
+ are accessible to the CPU that is executing the DXE core.
+
+--*/
+
+#include "gcd.h"
+
+#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED | \
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
+
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+ EFI_RESOURCE_ATTRIBUTE_TESTED )
+
+#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
+
+#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
+
+#define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
+
+//
+// Module Variables
+//
+EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+EFI_LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);
+EFI_LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);
+
+EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {
+ EFI_GCD_MAP_SIGNATURE,
+ { NULL, NULL },
+ 0,
+ 0,
+ 0,
+ 0,
+ EfiGcdMemoryTypeNonExistent,
+ 0,
+ NULL,
+ NULL
+};
+
+EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {
+ EFI_GCD_MAP_SIGNATURE,
+ { NULL, NULL },
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ EfiGcdIoTypeNonExistent,
+ NULL,
+ NULL
+};
+
+GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED, EFI_MEMORY_RP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED, EFI_MEMORY_WP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED, EFI_MEMORY_XP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },
+ { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },
+ { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },
+ { 0, 0, FALSE }
+};
+
+VOID
+CoreAcquireGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreAcquireLock (&mGcdMemorySpaceLock);
+}
+
+
+VOID
+CoreReleaseGcdMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdMemorySpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreReleaseLock (&mGcdMemorySpaceLock);
+}
+
+
+
+VOID
+CoreAcquireGcdIoLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Acquire memory lock on mGcdIoSpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreAcquireLock (&mGcdIoSpaceLock);
+}
+
+
+VOID
+CoreReleaseGcdIoLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release memory lock on mGcdIoSpaceLock
+
+Arguments:
+ None
+
+Returns:
+ None
+
+--*/
+{
+ CoreReleaseLock (&mGcdIoSpaceLock);
+}
+
+
+
+//
+// GCD Initialization Worker Functions
+//
+UINT64
+AlignValue (
+ IN UINT64 Value,
+ IN UINTN Alignment,
+ IN BOOLEAN RoundUp
+ )
+/*++
+
+Routine Description:
+
+ Aligns a value to the specified boundary.
+
+Arguments:
+
+ Value - 64 bit value to align
+ Alignment - Log base 2 of the boundary to align Value to
+ RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary.
+ FALSE is Value is to be rounded down to the nearest aligned boundary.
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ UINT64 AlignmentMask;
+
+ AlignmentMask = LShiftU64 (1, Alignment) - 1;
+ if (RoundUp) {
+ Value += AlignmentMask;
+ }
+ return Value & (~AlignmentMask);
+}
+
+UINT64
+PageAlignAddress (
+ IN UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Aligns address to the page boundary.
+
+Arguments:
+
+ Value - 64 bit address to align
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);
+}
+
+UINT64
+PageAlignLength (
+ IN UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Aligns length to the page boundary.
+
+Arguments:
+
+ Value - 64 bit length to align
+
+Returns:
+
+ A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
+
+--*/
+{
+ return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);
+}
+
+//
+// GCD Memory Space Worker Functions
+//
+EFI_STATUS
+CoreAllocateGcdMapEntry (
+ IN OUT EFI_GCD_MAP_ENTRY **TopEntry,
+ IN OUT EFI_GCD_MAP_ENTRY **BottomEntry
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool for two entries.
+
+Arguments:
+
+ TopEntry - An entry of GCD map
+ BottomEntry - An entry of GCD map
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
+ EFI_SUCCESS - Both entries successfully allocated.
+
+--*/
+{
+ *TopEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
+ if (*TopEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *BottomEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
+ if (*BottomEntry == NULL) {
+ CoreFreePool (*TopEntry);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreInsertGcdMapEntry (
+ IN EFI_LIST_ENTRY *Link,
+ IN EFI_GCD_MAP_ENTRY *Entry,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_GCD_MAP_ENTRY *TopEntry,
+ IN EFI_GCD_MAP_ENTRY *BottomEntry
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Inserts a new descriptor into a sorted list
+
+Arguments:
+
+ Link - The linked list to insert the range BaseAddress and Length into
+
+ Entry - A pointer to the entry that is inserted
+
+ BaseAddress - The base address of the new range
+
+ Length - The length of the new range in bytes
+
+ TopEntry - Top pad entry to insert if needed.
+
+ BottomEntry - Bottom pad entry to insert if needed.
+
+Returns:
+
+ EFI_SUCCESS - The new range was inserted into the linked list
+
+--*/
+{
+ ASSERT (Length != 0);
+
+ if (BaseAddress > Entry->BaseAddress) {
+ ASSERT (BottomEntry->Signature == 0);
+ EfiCommonLibCopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
+ Entry->BaseAddress = BaseAddress;
+ BottomEntry->EndAddress = BaseAddress - 1;
+ InsertTailList (Link, &BottomEntry->Link);
+ }
+
+ if ((BaseAddress + Length - 1) < Entry->EndAddress) {
+ ASSERT (TopEntry->Signature == 0);
+ EfiCommonLibCopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
+ TopEntry->BaseAddress = BaseAddress + Length;
+ Entry->EndAddress = BaseAddress + Length - 1;
+ InsertHeadList (Link, &TopEntry->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreMergeGcdMapEntry (
+ IN EFI_LIST_ENTRY *Link,
+ IN BOOLEAN Forward,
+ IN EFI_LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Merge the Gcd region specified by Link and its adjacent entry
+
+Arguments:
+
+ Link - Specify the entry to be merged (with its adjacent entry).
+
+ Forward - Direction (forward or backward).
+
+ Map - Boundary.
+
+Returns:
+
+ EFI_SUCCESS - Successfully returned.
+
+ EFI_UNSUPPORTED - These adjacent regions could not merge.
+
+--*/
+{
+ EFI_LIST_ENTRY *AdjacentLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *AdjacentEntry;
+
+ //
+ // Get adjacent entry
+ //
+ if (Forward) {
+ AdjacentLink = Link->ForwardLink;
+ } else {
+ AdjacentLink = Link->BackLink;
+ }
+
+ //
+ // If AdjacentLink is the head of the list, then no merge can be performed
+ //
+ if (AdjacentLink == Map) {
+ return EFI_SUCCESS;
+ }
+
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (Entry->Capabilities != AdjacentEntry->Capabilities) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->Attributes != AdjacentEntry->Attributes) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Forward) {
+ Entry->EndAddress = AdjacentEntry->EndAddress;
+ } else {
+ Entry->BaseAddress = AdjacentEntry->BaseAddress;
+ }
+ RemoveEntryList (AdjacentLink);
+ CoreFreePool (AdjacentEntry);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreCleanupGcdMapEntry (
+ IN EFI_GCD_MAP_ENTRY *TopEntry,
+ IN EFI_GCD_MAP_ENTRY *BottomEntry,
+ IN EFI_LIST_ENTRY *StartLink,
+ IN EFI_LIST_ENTRY *EndLink,
+ IN EFI_LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Merge adjacent entries on total chain.
+
+Arguments:
+
+ TopEntry - Top entry of GCD map.
+
+ BottomEntry - Bottom entry of GCD map.
+
+ StartLink - Start link of the list for this loop.
+
+ EndLink - End link of the list for this loop.
+
+ Map - Boundary.
+
+Returns:
+
+ EFI_SUCCESS - GCD map successfully cleaned up.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+
+ if (TopEntry->Signature == 0) {
+ CoreFreePool (TopEntry);
+ }
+ if (BottomEntry->Signature == 0) {
+ CoreFreePool (BottomEntry);
+ }
+
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ CoreMergeGcdMapEntry (Link, FALSE, Map);
+ Link = Link->ForwardLink;
+ }
+ CoreMergeGcdMapEntry (EndLink, TRUE, Map);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreSearchGcdMapEntry (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT EFI_LIST_ENTRY **StartLink,
+ OUT EFI_LIST_ENTRY **EndLink,
+ IN EFI_LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Search a segment of memory space in GCD map. The result is a range of GCD entry list.
+
+Arguments:
+
+ BaseAddress - The start address of the segment.
+
+ Length - The length of the segment.
+
+ StartLink - The first GCD entry involves this segment of memory space.
+
+ EndLink - The first GCD entry involves this segment of memory space.
+
+ Map - Points to the start entry to search.
+
+Returns:
+
+ EFI_SUCCESS - Successfully found the entry.
+
+ EFI_NOT_FOUND - Not found.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ ASSERT (Length != 0);
+
+ *StartLink = NULL;
+ *EndLink = NULL;
+
+ Link = Map->ForwardLink;
+ while (Link != Map) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) {
+ *StartLink = Link;
+ }
+ if (*StartLink != NULL) {
+ if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&
+ (BaseAddress + Length - 1) <= Entry->EndAddress ) {
+ *EndLink = Link;
+ return EFI_SUCCESS;
+ }
+ }
+ Link = Link->ForwardLink;
+ }
+ return EFI_NOT_FOUND;
+}
+
+UINTN
+CoreCountGcdMapEntry (
+ IN EFI_LIST_ENTRY *Map
+ )
+/*++
+
+Routine Description:
+
+ Count the amount of GCD map entries.
+
+Arguments:
+
+ Map - Points to the start entry to do the count loop.
+
+Returns:
+
+ The count.
+
+--*/
+{
+ UINTN Count;
+ EFI_LIST_ENTRY *Link;
+
+ Count = 0;
+ Link = Map->ForwardLink;
+ while (Link != Map) {
+ Count++;
+ Link = Link->ForwardLink;
+ }
+ return Count;
+}
+
+UINT64
+ConverToCpuArchAttributes (
+ UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Return the memory attribute specified by Attributes
+
+Arguments:
+
+ Attributes - A num with some attribute bits on.
+
+Returns:
+
+ The enum value of memory attribute.
+
+--*/
+{
+ if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {
+ return EFI_MEMORY_UC;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) {
+ return EFI_MEMORY_WC;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) {
+ return EFI_MEMORY_WT;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) {
+ return EFI_MEMORY_WB;
+ }
+
+ if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) {
+ return EFI_MEMORY_WP;
+ }
+
+ return INVALID_CPU_ARCH_ATTRIBUTES;
+
+}
+
+
+EFI_STATUS
+CoreConvertSpace (
+ IN UINTN Operation,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
+
+Arguments:
+
+ Operation - The type of the operation
+
+ GcdMemoryType - Additional information for the operation
+
+ GcdIoType - Additional information for the operation
+
+ BaseAddress - Start address of the segment
+
+ Length - length of the segment
+
+ Capabilities - The alterable attributes of a newly added entry
+
+ Attributes - The attributes needs to be set
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Length is 0 or address (length) not aligned when setting attribute.
+
+ EFI_SUCCESS - Action successfully done.
+
+ EFI_UNSUPPORTED - Could not find the proper descriptor on this segment or
+ set an upsupported attribute.
+
+ EFI_ACCESS_DENIED - Operate on an space non-exist or is used for an image.
+
+ EFI_NOT_FOUND - Free a non-using space or remove a non-exist space, and so on.
+
+ EFI_OUT_OF_RESOURCES - No buffer could be allocated.
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *Map;
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_LIST_ENTRY *EndLink;
+
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ UINT64 CpuArchAttributes;
+
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Map = NULL;
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreAcquireGcdMemoryLock ();
+ Map = &mGcdMemorySpaceMap;
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreAcquireGcdIoLock ();
+ Map = &mGcdIoSpaceMap;
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+
+ goto Done;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated non-existent memory.
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ switch (Operation) {
+ //
+ // Add operations
+ //
+ case GCD_ADD_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||
+ Entry->ImageHandle != NULL ) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case GCD_ADD_IO_OPERATION:
+ if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||
+ Entry->ImageHandle != NULL ) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ //
+ // Free operations
+ //
+ case GCD_FREE_MEMORY_OPERATION:
+ case GCD_FREE_IO_OPERATION:
+ if (Entry->ImageHandle == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ break;
+ //
+ // Remove operations
+ //
+ case GCD_REMOVE_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->ImageHandle != NULL) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case GCD_REMOVE_IO_OPERATION:
+ if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->ImageHandle != NULL) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ //
+ // Set attribute operations
+ //
+ case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
+ if (Attributes & EFI_MEMORY_RUNTIME) {
+ if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+
+ goto Done;
+ }
+ }
+ if ((Entry->Capabilities & Attributes) != Attributes) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ break;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Allocate work space to perform this operation
+ //
+ Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
+ //
+ // Call CPU Arch Protocol to attempt to set attributes on the range
+ //
+ CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
+ if ( CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES ) {
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, &CpuArch);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ Status = CpuArch->SetMemoryAttributes (
+ CpuArch,
+ BaseAddress,
+ Length,
+ CpuArchAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ }
+
+ //
+ // Convert/Insert the list of descriptors from StartLink to EndLink
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);
+ switch (Operation) {
+ //
+ // Add operations
+ //
+ case GCD_ADD_MEMORY_OPERATION:
+ Entry->GcdMemoryType = GcdMemoryType;
+ if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+ Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;
+ } else {
+ Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;
+ }
+ break;
+ case GCD_ADD_IO_OPERATION:
+ Entry->GcdIoType = GcdIoType;
+ break;
+ //
+ // Free operations
+ //
+ case GCD_FREE_MEMORY_OPERATION:
+ case GCD_FREE_IO_OPERATION:
+ Entry->ImageHandle = NULL;
+ Entry->DeviceHandle = NULL;
+ break;
+ //
+ // Remove operations
+ //
+ case GCD_REMOVE_MEMORY_OPERATION:
+ Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;
+ Entry->Capabilities = 0;
+ break;
+ case GCD_REMOVE_IO_OPERATION:
+ Entry->GcdIoType = EfiGcdIoTypeNonExistent;
+ break;
+ //
+ // Set attribute operations
+ //
+ case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
+ Entry->Attributes = Attributes;
+ break;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Cleanup
+ //
+ Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
+
+Done:
+ if (Operation & GCD_MEMORY_SPACE_OPERATION) {
+ CoreReleaseGcdMemoryLock ();
+ }
+ if (Operation & GCD_IO_SPACE_OPERATION) {
+ CoreReleaseGcdIoLock ();
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CoreAllocateSpaceCheckEntry (
+ IN UINTN Operation,
+ IN EFI_GCD_MAP_ENTRY *Entry,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType
+ )
+/*++
+
+Routine Description:
+
+ Check whether an entry could be used to allocate space.
+
+Arguments:
+
+ Operation - Allocate memory or IO
+
+ Entry - The entry to be tested
+
+ GcdMemoryType - The desired memory type
+
+ GcdIoType - The desired IO type
+
+Returns:
+
+ EFI_NOT_FOUND - The memory type does not match or there's an image handle on the entry.
+
+ EFI_UNSUPPORTED - The operation unsupported.
+
+ EFI_SUCCESS - It's ok for this entry to be used to allocate space.
+
+--*/
+{
+ if (Entry->ImageHandle != NULL) {
+ return EFI_NOT_FOUND;
+ }
+ switch (Operation) {
+ case GCD_ALLOCATE_MEMORY_OPERATION:
+ if (Entry->GcdMemoryType != GcdMemoryType) {
+ return EFI_NOT_FOUND;
+ }
+ break;
+ case GCD_ALLOCATE_IO_OPERATION:
+ if (Entry->GcdIoType != GcdIoType) {
+ return EFI_NOT_FOUND;
+ }
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreAllocateSpace (
+ IN UINTN Operation,
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocate space on specified address and length.
+
+Arguments:
+
+ Operation - The type of operation (memory or IO)
+ GcdAllocateType - The type of allocate operation
+ GcdMemoryType - The desired memory type
+ GcdIoType - The desired IO type
+ Alignment - Align with 2^Alignment
+ Length - Length to allocate
+ BaseAddress - Base address to allocate
+ ImageHandle - The image handle consume the allocated space.
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+ EFI_NOT_FOUND - No descriptor for the desired space exists.
+ EFI_SUCCESS - Space successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS AlignmentMask;
+ EFI_PHYSICAL_ADDRESS MaxAddress;
+ EFI_LIST_ENTRY *Map;
+ EFI_LIST_ENTRY *Link;
+ EFI_LIST_ENTRY *SubLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MAP_ENTRY *TopEntry;
+ EFI_GCD_MAP_ENTRY *BottomEntry;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_LIST_ENTRY *EndLink;
+ BOOLEAN Found;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (BaseAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Alignment >= 64) {
+ return EFI_NOT_FOUND;
+ }
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Map = NULL;
+ if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
+ CoreAcquireGcdMemoryLock ();
+ Map = &mGcdMemorySpaceMap;
+ }
+ if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
+ CoreAcquireGcdIoLock ();
+ Map = &mGcdIoSpaceMap;
+ }
+
+ Found = FALSE;
+ StartLink = NULL;
+ EndLink = NULL;
+ //
+ // Compute alignment bit mask
+ //
+ AlignmentMask = LShiftU64 (1, Alignment) - 1;
+
+ if (GcdAllocateType == EfiGcdAllocateAddress) {
+ //
+ // Verify that the BaseAddress passed in is aligned correctly
+ //
+ if ((*BaseAddress & AlignmentMask) != 0) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ Link = Link->ForwardLink;
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+ Found = TRUE;
+ } else {
+
+ Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ //
+ // Compute the maximum address to use in the search algorithm
+ //
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||
+ GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown) {
+ MaxAddress = *BaseAddress;
+ } else {
+ MaxAddress = Entry->EndAddress;
+ }
+
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {
+ Link = Map->BackLink;
+ } else {
+ Link = Map->ForwardLink;
+ }
+ while (Link != Map) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {
+ Link = Link->BackLink;
+ } else {
+ Link = Link->ForwardLink;
+ }
+
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {
+ if (Entry->BaseAddress > MaxAddress) {
+ continue;
+ }
+ if (Length > (Entry->EndAddress + 1)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ if (Entry->EndAddress > MaxAddress) {
+ *BaseAddress = MaxAddress;
+ } else {
+ *BaseAddress = Entry->EndAddress;
+ }
+ *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);
+ } else {
+ *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);
+ if ((*BaseAddress + Length - 1) > MaxAddress) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ //
+ // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
+ //
+ Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ Link = StartLink;
+ //
+ // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
+ //
+ Found = TRUE;
+ SubLink = StartLink;
+ while (SubLink != EndLink->ForwardLink) {
+ Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
+ if (EFI_ERROR (Status)) {
+ Link = SubLink;
+ Found = FALSE;
+ break;
+ }
+ SubLink = SubLink->ForwardLink;
+ }
+ if (Found) {
+ break;
+ }
+ }
+ }
+ if (!Found) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Allocate work space to perform this operation
+ //
+ Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Convert/Insert the list of descriptors from StartLink to EndLink
+ //
+ Link = StartLink;
+ while (Link != EndLink->ForwardLink) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);
+ Entry->ImageHandle = ImageHandle;
+ Entry->DeviceHandle = DeviceHandle;
+ Link = Link->ForwardLink;
+ }
+
+ //
+ // Cleanup
+ //
+ Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
+
+Done:
+ if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
+ CoreReleaseGcdMemoryLock ();
+ }
+ if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
+ CoreReleaseGcdIoLock ();
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+CoreInternalAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Add a segment of memory to GCD map.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+ Capabilities - alterable attributes of the segment.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameters.
+
+ EFI_SUCCESS - Successfully add a segment of memory space.
+
+--*/
+{
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, 0, BaseAddress, Length, Capabilities, 0);
+}
+
+//
+// GCD Core Services
+//
+EFI_STATUS
+CoreAllocateMemorySpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocates nonexistent memory, reserved memory, system memory, or memorymapped
+I/O resources from the global coherency domain of the processor.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdMemoryType - The desired memory type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - Memory space successfully allocated.
+
+--*/
+{
+ return CoreAllocateSpace (
+ GCD_ALLOCATE_MEMORY_OPERATION,
+ GcdAllocateType,
+ GcdMemoryType,
+ 0,
+ Alignment,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle
+ );
+}
+
+EFI_STATUS
+CoreAddMemorySpace (
+ IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Capabilities
+ )
+/*++
+
+Routine Description:
+
+ Adds reserved memory, system memory, or memory-mapped I/O resources to the
+global coherency domain of the processor.
+
+Arguments:
+
+ GcdMemoryType - Memory type of the memory space.
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+ Capabilities - alterable attributes of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Merged this memory space into GCD map.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PageBaseAddress;
+ UINT64 PageLength;
+
+ Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);
+
+ if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
+
+ PageBaseAddress = PageAlignLength (BaseAddress);
+ PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);
+
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ GcdMemoryType,
+ EFI_PAGE_SHIFT,
+ PageLength,
+ &PageBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ PageBaseAddress,
+ RShiftU64 (PageLength, EFI_PAGE_SHIFT),
+ Capabilities
+ );
+ } else {
+ for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ GcdMemoryType,
+ EFI_PAGE_SHIFT,
+ EFI_PAGE_SIZE,
+ &PageBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ PageBaseAddress,
+ 1,
+ Capabilities
+ );
+ }
+ }
+ }
+ }
+ return Status;
+}
+
+EFI_STATUS
+CoreFreeMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Frees nonexistent memory, reserved memory, system memory, or memory-mapped
+I/O resources from the global coherency domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+{
+ return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreRemoveMemorySpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Removes reserved memory, system memory, or memory-mapped I/O resources from
+the global coherency domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the memory space.
+
+ Length - Length of the memory space.
+
+Returns:
+
+ EFI_SUCCESS - Successfully remove a segment of memory space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+VOID
+BuildMemoryDescriptor (
+ IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,
+ IN EFI_GCD_MAP_ENTRY *Entry
+ )
+/*++
+
+Routine Description:
+
+ Build a memory descriptor according to an entry.
+
+Arguments:
+
+ Descriptor - The descriptor to be built
+
+ Entry - According to this entry
+
+Returns:
+
+ None
+
+--*/
+{
+ Descriptor->BaseAddress = Entry->BaseAddress;
+ Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
+ Descriptor->Capabilities = Entry->Capabilities;
+ Descriptor->Attributes = Entry->Attributes;
+ Descriptor->GcdMemoryType = Entry->GcdMemoryType;
+ Descriptor->ImageHandle = Entry->ImageHandle;
+ Descriptor->DeviceHandle = Entry->DeviceHandle;
+}
+
+EFI_STATUS
+CoreGetMemorySpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the descriptor for a memory region containing a specified address.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully get memory space descriptor.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_LIST_ENTRY *EndLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Search for the list of descriptors that contain BaseAddress
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Copy the contents of the found descriptor into Descriptor
+ //
+ Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildMemoryDescriptor (Descriptor, Entry);
+ }
+
+ CoreReleaseGcdMemoryLock ();
+
+ return Status;
+}
+
+EFI_STATUS
+CoreSetMemorySpaceAttributes (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Modifies the attributes for a memory region in the global coherency domain of the
+processor.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Length - Specified length
+
+ Attributes - Specified attributes
+
+Returns:
+
+ EFI_SUCCESS - Successfully set attribute of a segment of memory space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, Attributes);
+}
+
+EFI_STATUS
+CoreGetMemorySpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Returns a map of the memory resources in the global coherency domain of the
+processor.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ MemorySpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get memory space map.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (NumberOfDescriptors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MemorySpaceMap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdMemoryLock ();
+
+ //
+ // Count the number of descriptors
+ //
+ *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
+
+ //
+ // Allocate the MemorySpaceMap
+ //
+ *MemorySpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
+ if (*MemorySpaceMap == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Fill in the MemorySpaceMap
+ //
+ Descriptor = *MemorySpaceMap;
+ Link = mGcdMemorySpaceMap.ForwardLink;
+ while (Link != &mGcdMemorySpaceMap) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildMemoryDescriptor (Descriptor, Entry);
+ Descriptor++;
+ Link = Link->ForwardLink;
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseGcdMemoryLock ();
+ return Status;
+}
+
+EFI_STATUS
+CoreAddIoSpace (
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Adds reserved I/O or I/O resources to the global coherency domain of the processor.
+
+Arguments:
+
+ GcdIoType - IO type of the segment.
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Merged this segment into GCD map.
+ EFI_INVALID_PARAMETER - Parameter not valid
+
+--*/
+{
+ //
+ // Make sure parameters are valid
+ //
+ if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return CoreConvertSpace (GCD_ADD_IO_OPERATION, 0, GcdIoType, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreAllocateIoSpace (
+ IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
+ IN EFI_GCD_IO_TYPE GcdIoType,
+ IN UINTN Alignment,
+ IN UINT64 Length,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE DeviceHandle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+domain of the processor.
+
+Arguments:
+
+ GcdAllocateType - The type of allocate operation
+
+ GcdIoType - The desired IO type
+
+ Alignment - Align with 2^Alignment
+
+ Length - Length to allocate
+
+ BaseAddress - Base address to allocate
+
+ ImageHandle - The image handle consume the allocated space.
+
+ DeviceHandle - The device handle consume the allocated space.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+ EFI_NOT_FOUND - No descriptor contains the desired space.
+
+ EFI_SUCCESS - IO space successfully allocated.
+
+--*/
+{
+ return CoreAllocateSpace (
+ GCD_ALLOCATE_IO_OPERATION,
+ GcdAllocateType,
+ 0,
+ GcdIoType,
+ Alignment,
+ Length,
+ BaseAddress,
+ ImageHandle,
+ DeviceHandle
+ );
+}
+
+EFI_STATUS
+CoreFreeIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
+domain of the processor.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Space successfully freed.
+
+--*/
+{
+ return CoreConvertSpace (GCD_FREE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+EFI_STATUS
+CoreRemoveIoSpace (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ Removes reserved I/O or I/O resources from the global coherency domain of the
+processor.
+
+Arguments:
+
+ BaseAddress - Base address of the segment.
+
+ Length - Length of the segment.
+
+Returns:
+
+ EFI_SUCCESS - Successfully removed a segment of IO space.
+
+--*/
+{
+ return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0);
+}
+
+VOID
+BuildIoDescriptor (
+ IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,
+ IN EFI_GCD_MAP_ENTRY *Entry
+ )
+/*++
+
+Routine Description:
+
+ Build a IO descriptor according to an entry.
+
+Arguments:
+
+ Descriptor - The descriptor to be built
+
+ Entry - According to this entry
+
+Returns:
+
+ None
+
+--*/
+{
+ Descriptor->BaseAddress = Entry->BaseAddress;
+ Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
+ Descriptor->GcdIoType = Entry->GcdIoType;
+ Descriptor->ImageHandle = Entry->ImageHandle;
+ Descriptor->DeviceHandle = Entry->DeviceHandle;
+}
+
+EFI_STATUS
+CoreGetIoSpaceDescriptor (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the descriptor for an I/O region containing a specified address.
+
+Arguments:
+
+ BaseAddress - Specified start address
+
+ Descriptor - Specified length
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Descriptor is NULL.
+
+ EFI_SUCCESS - Successfully get the IO space descriptor.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *StartLink;
+ EFI_LIST_ENTRY *EndLink;
+ EFI_GCD_MAP_ENTRY *Entry;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdIoLock ();
+
+ //
+ // Search for the list of descriptors that contain BaseAddress
+ //
+ Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Copy the contents of the found descriptor into Descriptor
+ //
+ Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildIoDescriptor (Descriptor, Entry);
+ }
+
+ CoreReleaseGcdIoLock ();
+
+ return Status;
+}
+
+EFI_STATUS
+CoreGetIoSpaceMap (
+ OUT UINTN *NumberOfDescriptors,
+ OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
+ )
+/*++
+
+Routine Description:
+
+ Returns a map of the I/O resources in the global coherency domain of the processor.
+
+Arguments:
+
+ NumberOfDescriptors - Number of descriptors.
+
+ IoSpaceMap - Descriptor array
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Successfully get IO space map.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;
+
+ //
+ // Make sure parameters are valid
+ //
+ if (NumberOfDescriptors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (IoSpaceMap == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireGcdIoLock ();
+
+ //
+ // Count the number of descriptors
+ //
+ *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);
+
+ //
+ // Allocate the IoSpaceMap
+ //
+ *IoSpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));
+ if (*IoSpaceMap == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Fill in the IoSpaceMap
+ //
+ Descriptor = *IoSpaceMap;
+ Link = mGcdIoSpaceMap.ForwardLink;
+ while (Link != &mGcdIoSpaceMap) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+ BuildIoDescriptor (Descriptor, Entry);
+ Descriptor++;
+ Link = Link->ForwardLink;
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseGcdIoLock ();
+ return Status;
+}
+
+UINT64
+CoreConvertResourceDescriptorHobAttributesToCapabilities (
+ EFI_GCD_MEMORY_TYPE GcdMemoryType,
+ UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
+ capabilities mask
+
+Arguments:
+
+ GcdMemoryType - Type of resource in the GCD memory map.
+ Attributes - The attribute mask in the Resource Descriptor HOB.
+
+Returns:
+
+ The capabilities mask for an EFI Memory Descriptor.
+
+--*/
+{
+ UINT64 Capabilities;
+ GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {
+ if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {
+ if (Attributes & Conversion->Attribute) {
+ Capabilities |= Conversion->Capability;
+ }
+ }
+ }
+
+ return Capabilities;
+}
+
+EFI_STATUS
+CoreInitializeMemoryServices (
+ IN VOID **HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
+ OUT UINT64 *MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map.
+
+Arguments:
+
+ HobStart - The start address of the HOB.
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+ MemoryLength - Length of memory region found to init DXE core.
+
+Returns:
+
+ EFI_SUCCESS - Memory services successfully initialized.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
+ UINTN DataSize;
+ BOOLEAN Found;
+ EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 Capabilities;
+ EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
+ UINT64 MaxMemoryLength;
+ UINT64 MaxMemoryAttributes;
+ EFI_PHYSICAL_ADDRESS MaxAddress;
+ EFI_PHYSICAL_ADDRESS HighAddress;
+ EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;
+
+ //
+ // Point at the first HOB. This must be the PHIT HOB.
+ //
+ Hob.Raw = *HobStart;
+ ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
+
+ //
+ // Initialize the spin locks and maps in the memory services.
+ // Also fill in the memory services into the EFI Boot Services Table
+ //
+ CoreInitializePool ();
+
+ //
+ // Initialize Local Variables
+ //
+ PhitResourceHob = NULL;
+ MaxResourceHob = NULL;
+ ResourceHob = NULL;
+ BaseAddress = 0;
+ Length = 0;
+ Attributes = 0;
+ MaxMemoryBaseAddress = 0;
+ MaxMemoryLength = 0;
+ MaxMemoryAttributes = 0;
+
+ //
+ // Cache the PHIT HOB for later use
+ //
+ PhitHob = Hob.HandoffInformationTable;
+
+ //
+ // See if a Memory Type Information HOB is available
+ //
+ Status = GetNextGuidHob (&Hob.Raw, &gEfiMemoryTypeInformationGuid, &EfiMemoryTypeInformation, &DataSize);
+ if (!EFI_ERROR (Status) &&
+ EfiMemoryTypeInformation != NULL &&
+ DataSize > 0 &&
+ DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
+ gBS->CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
+ }
+
+ //
+ // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
+ //
+ Length = 0;
+ Found = FALSE;
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+
+ if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) {
+
+ if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart &&
+ PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) {
+
+ //
+ // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
+ //
+ PhitResourceHob = ResourceHob;
+ Found = TRUE;
+
+ Attributes = PhitResourceHob->ResourceAttribute;
+ BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
+ Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
+ BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
+ Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
+ BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
+ Length = PageAlignLength ((UINT64)*HobStart - BaseAddress);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
+ //
+ ASSERT (Found);
+
+ //
+ // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
+ // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
+ // The max address must be within the physically addressible range for the processor.
+ //
+ MaxMemoryLength = 0;
+ MaxAddress = EFI_MAX_ADDRESS;
+ do {
+ HighAddress = 0;
+ Found = FALSE;
+ //
+ // Search for a tested memory region that is below MaxAddress
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ //
+ // See if this is a resource descriptor HOB that does not contain the PHIT.
+ //
+ if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+ //
+ // See if this resource descrior HOB describes tested system memory below MaxAddress
+ //
+ if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES &&
+ ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress ) {
+
+ //
+ // See if this is the highest tested system memory region below MaxAddress
+ //
+ if (ResourceHob->PhysicalStart > HighAddress) {
+
+ MaxResourceHob = ResourceHob;
+ HighAddress = MaxResourceHob->PhysicalStart;
+ Found = TRUE;
+ }
+ }
+ }
+ }
+ if (Found) {
+ //
+ // Compute the size of the tested memory region below MaxAddrees
+ //
+ MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart);
+ MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress);
+ MaxMemoryAttributes = MaxResourceHob->ResourceAttribute;
+ }
+ MaxAddress = ResourceHob->PhysicalStart;
+ } while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE);
+
+ //
+ //
+ //
+ if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||
+ (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE) ) {
+ BaseAddress = MaxMemoryBaseAddress;
+ Length = MaxMemoryLength;
+ Attributes = MaxMemoryAttributes;
+ }
+
+ //
+ // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
+ //
+ ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
+
+ //
+ // Declare the very first memory region, so the EFI Memory Services are available.
+ //
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ BaseAddress,
+ RShiftU64 (Length, EFI_PAGE_SHIFT),
+ Capabilities
+ );
+
+ *MemoryBaseAddress = BaseAddress;
+ *MemoryLength = Length;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CoreInitializeGcdServices (
+ IN OUT VOID **HobStart,
+ IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
+ IN UINT64 MemoryLength
+ )
+/*++
+
+Routine Description:
+
+ External function. Initializes the GCD and memory services based on the memory
+ descriptor HOBs. This function is responsible for priming the GCD map and the
+ memory map, so memory allocations and resource allocations can be made. The first
+ part of this function can not depend on any memory services until at least one
+ memory descriptor is provided to the memory services. Then the memory services
+ can be used to intialize the GCD map. The HobStart will be relocated to a pool
+ buffer.
+
+Arguments:
+
+ HobStart - The start address of the HOB
+
+ MemoryBaseAddress - Start address of memory region found to init DXE core.
+
+ MemoryLength - Length of memory region found to init DXE core.
+
+
+Returns:
+
+ EFI_SUCCESS - GCD services successfully initialized.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ VOID *NewHobList;
+ EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
+ UINT8 SizeOfMemorySpace;
+ UINT8 SizeOfIoSpace;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ EFI_STATUS Status;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_GCD_MEMORY_TYPE GcdMemoryType;
+ EFI_GCD_IO_TYPE GcdIoType;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINTN Index;
+ UINT64 Capabilities;
+
+ //
+ // Cache the PHIT HOB for later use
+ //
+ PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
+
+ //
+ // Get the number of address lines in the I/O and Memory space for the CPU
+ //
+ Status = GetCpuHobInfo (*HobStart, &SizeOfMemorySpace, &SizeOfIoSpace);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize the GCD Memory Space Map
+ //
+ Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
+ ASSERT (Entry != NULL);
+
+ Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
+
+ InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
+
+ //
+ // Initialize the GCD I/O Space Map
+ //
+ Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
+ ASSERT (Entry != NULL);
+
+ Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
+
+ InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
+
+ //
+ // Walk the HOB list and add all resource descriptors to the GCD
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+
+ GcdMemoryType = EfiGcdMemoryTypeNonExistent;
+ GcdIoType = EfiGcdIoTypeNonExistent;
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+
+ ResourceHob = Hob.ResourceDescriptor;
+
+ switch (ResourceHob->ResourceType) {
+ case EFI_RESOURCE_SYSTEM_MEMORY:
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
+ GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+ }
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
+//*** AMI PORTING BEGIN ***//
+// TODO: MRC reports most of the memory as untested. As a result it is marked as Reserved.
+// GcdMemoryType = EfiGcdMemoryTypeReserved;
+ GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+//*** AMI PORTING END *****//
+ }
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
+ GcdMemoryType = EfiGcdMemoryTypeReserved;
+ }
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO:
+ case EFI_RESOURCE_FIRMWARE_DEVICE:
+ GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
+ case EFI_RESOURCE_MEMORY_RESERVED:
+ GcdMemoryType = EfiGcdMemoryTypeReserved;
+ break;
+ case EFI_RESOURCE_IO:
+ GcdIoType = EfiGcdIoTypeIo;
+ break;
+ case EFI_RESOURCE_IO_RESERVED:
+ GcdIoType = EfiGcdIoTypeReserved;
+ break;
+ }
+
+ if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
+
+ //
+ // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
+ //
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
+ GcdMemoryType,
+ ResourceHob->ResourceAttribute
+ );
+
+ Status = CoreInternalAddMemorySpace (
+ GcdMemoryType,
+ ResourceHob->PhysicalStart,
+ ResourceHob->ResourceLength,
+ Capabilities
+ );
+ }
+
+ if (GcdIoType != EfiGcdIoTypeNonExistent) {
+ Status = CoreAddIoSpace (
+ GcdIoType,
+ ResourceHob->PhysicalStart,
+ ResourceHob->ResourceLength
+ );
+ }
+ }
+ }
+
+ //
+ // Allocate first memory region from the GCD by the DXE core
+ //
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeSystemMemory,
+ 0,
+ MemoryLength,
+ &MemoryBaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+
+ //
+ // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
+ // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
+ //
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ MemoryHob = Hob.MemoryAllocation;
+ BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
+ Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
+ if (!EFI_ERROR (Status)) {
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ Descriptor.GcdMemoryType,
+ 0,
+ MemoryHob->AllocDescriptor.MemoryLength,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ if (!EFI_ERROR (Status) && Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
+ CoreAddMemoryDescriptor (
+ MemoryHob->AllocDescriptor.MemoryType,
+ MemoryHob->AllocDescriptor.MemoryBaseAddress,
+ RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
+ Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
+ );
+ }
+ }
+ }
+
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ BaseAddress = FirmwareVolumeHob->BaseAddress;
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ 0,
+ FirmwareVolumeHob->Length,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ }
+ }
+
+ //
+ // Relocate HOB List to an allocated pool buffer.
+ //
+ NewHobList = CoreAllocateCopyPool (
+ (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
+ *HobStart
+ );
+ ASSERT (NewHobList != NULL);
+
+ *HobStart = NewHobList;
+
+ //
+ // Add and allocate the remaining unallocated system memory to the memory services.
+ //
+ Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
+ if (MemorySpaceMap[Index].ImageHandle == NULL) {
+ BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
+ Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
+ if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {
+ continue;
+ }
+ CoreAddMemoryDescriptor (
+ EfiConventionalMemory,
+ BaseAddress,
+ RShiftU64 (Length, EFI_PAGE_SHIFT),
+ MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
+ );
+ Status = CoreAllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeSystemMemory,
+ 0,
+ Length,
+ &BaseAddress,
+ gDxeCoreImageHandle,
+ NULL
+ );
+ }
+ }
+ }
+ CoreFreePool (MemorySpaceMap);
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/gcd.h b/Core/CORE_DXE/gcd.h
new file mode 100644
index 0000000..13d448d
--- /dev/null
+++ b/Core/CORE_DXE/gcd.h
@@ -0,0 +1,54 @@
+/*++
+
+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:
+
+ gcd.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _GCD_H
+#define _GCD_H
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+//
+// GCD Operations
+//
+#define GCD_MEMORY_SPACE_OPERATION 0x20
+#define GCD_IO_SPACE_OPERATION 0x40
+
+#define GCD_ADD_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 0)
+#define GCD_ALLOCATE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 1)
+#define GCD_FREE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 2)
+#define GCD_REMOVE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 3)
+#define GCD_SET_ATTRIBUTES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 4)
+
+#define GCD_ADD_IO_OPERATION (GCD_IO_SPACE_OPERATION | 0)
+#define GCD_ALLOCATE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 1)
+#define GCD_FREE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 2)
+#define GCD_REMOVE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 3)
+
+//
+// The data structure used to convert from GCD attributes to EFI Memory Map attributes
+//
+typedef struct {
+ UINT64 Attribute;
+ UINT64 Capability;
+ BOOLEAN Memory;
+} GCD_ATTRIBUTE_CONVERSION_ENTRY;
+
+#endif
diff --git a/Core/CORE_DXE/hand.h b/Core/CORE_DXE/hand.h
new file mode 100644
index 0000000..d048073
--- /dev/null
+++ b/Core/CORE_DXE/hand.h
@@ -0,0 +1,339 @@
+/*++
+
+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:
+
+ hand.h
+
+Abstract:
+
+ EFI internal protocol definitions
+
+
+
+Revision History
+
+--*/
+
+#ifndef _HAND_H_
+#define _HAND_H_
+
+#include "Tiano.h"
+#include "DxeCore.h"
+
+//
+// IHANDLE - contains a list of protocol handles
+//
+
+#define EFI_HANDLE_SIGNATURE EFI_SIGNATURE_32('h','n','d','l')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY AllHandles; // All handles list of IHANDLE
+ EFI_LIST_ENTRY Protocols; // List of PROTOCOL_INTERFACE's for this handle
+ UINTN LocateRequest; //
+ UINT64 Key; // The Handle Database Key value when this handle was last created or modified
+} IHANDLE;
+
+#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
+
+
+//
+// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
+// database. Each handler that supports this protocol is listed, along
+// with a list of registered notifies.
+//
+
+#define PROTOCOL_ENTRY_SIGNATURE EFI_SIGNATURE_32('p','r','t','e')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY AllEntries; // All entries
+ EFI_GUID ProtocolID; // ID of the protocol
+ EFI_LIST_ENTRY Protocols; // All protocol interfaces
+ EFI_LIST_ENTRY Notify; // Registerd notification handlers
+} PROTOCOL_ENTRY;
+
+//
+// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
+// with a protocol interface structure
+//
+
+#define PROTOCOL_INTERFACE_SIGNATURE EFI_SIGNATURE_32('p','i','f','c')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle; // Back pointer
+ EFI_LIST_ENTRY Link; // Link on IHANDLE.Protocols
+ EFI_LIST_ENTRY ByProtocol; // Link on PROTOCOL_ENTRY.Protocols
+ PROTOCOL_ENTRY *Protocol; // The protocol ID
+ VOID *Interface; // The interface value
+
+ EFI_LIST_ENTRY OpenList; // OPEN_PROTOCOL_DATA list.
+ UINTN OpenListCount;
+
+ EFI_HANDLE ControllerHandle;
+
+} PROTOCOL_INTERFACE;
+
+#define OPEN_PROTOCOL_DATA_SIGNATURE EFI_SIGNATURE_32('p','o','d','l')
+
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link;
+
+ EFI_HANDLE AgentHandle;
+ EFI_HANDLE ControllerHandle;
+ UINT32 Attributes;
+ UINT32 OpenCount;
+} OPEN_PROTOCOL_DATA;
+
+
+//
+// PROTOCOL_NOTIFY - used for each register notification for a protocol
+//
+
+#define PROTOCOL_NOTIFY_SIGNATURE EFI_SIGNATURE_32('p','r','t','n')
+typedef struct {
+ UINTN Signature;
+ PROTOCOL_ENTRY *Protocol;
+ EFI_LIST_ENTRY Link; // All notifications for this protocol
+ EFI_EVENT Event; // Event to notify
+ EFI_LIST_ENTRY *Position; // Last position notified
+} PROTOCOL_NOTIFY;
+
+//
+// Internal prototypes
+//
+
+
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol entry for the requested protocol.
+
+ N.B. The gProtocolDatabaseLock must be owned
+
+Arguments:
+
+ Protocol - The ID of the protocol
+
+ Create - Create a new entry if not found
+
+Returns:
+
+ Protocol entry
+
+--*/
+;
+
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ )
+/*++
+
+Routine Description:
+
+ Signal event for every protocol in protocol entry.
+
+Arguments:
+
+ ProtEntry - Protocol entry
+
+Returns:
+
+--*/
+;
+
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol instance for the requested handle and protocol.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ Handle - The handle to search the protocol on
+
+ Protocol - GUID of the protocol
+
+ Interface - The interface for the protocol being searched
+
+Returns:
+
+ Protocol instance (NULL: Not found)
+
+--*/
+;
+
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Removes Protocol from the protocol list (but not the handle list).
+
+Arguments:
+
+ Handle - The handle to remove protocol on.
+
+ Protocol - GUID of the protocol to be moved
+
+ Interface - The interface of the protocol
+
+Returns:
+
+ Protocol Entry
+
+--*/
+;
+
+EFI_STATUS
+CoreUnregisterProtocolNotify (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes all the events in the protocol database that match Event.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS when done searching the entire database.
+
+--*/
+;
+
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ )
+/*++
+
+Routine Description:
+
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ UserHandle - The handle on which the protocol is installed
+ Prot - The protocol to disconnect drivers from
+
+Returns:
+
+ EFI_SUCCESS - Drivers using the protocol interface are all disconnected
+ EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
+
+--*/
+;
+
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acquire lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Release lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ )
+/*++
+
+Routine Description:
+
+ Check whether a handle is a valid EFI_HANDLE
+
+Arguments:
+
+ UserHandle - The handle to check
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
+
+ EFI_SUCCESS - The handle is valid EFI_HANDLE.
+
+--*/
+;
+
+//
+// Externs
+//
+
+extern EFI_LOCK gProtocolDatabaseLock;
+extern EFI_LIST_ENTRY gHandleList;
+extern UINT64 gHandleDatabaseKey;
+
+#endif
diff --git a/Core/CORE_DXE/handle.c b/Core/CORE_DXE/handle.c
new file mode 100644
index 0000000..0def8d1
--- /dev/null
+++ b/Core/CORE_DXE/handle.c
@@ -0,0 +1,1703 @@
+/*++
+
+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:
+
+ handle.c
+
+Abstract:
+
+ EFI handle & protocol handling
+
+
+
+Revision History
+
+--*/
+
+#include "hand.h"
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+
+
+//
+// mProtocolDatabase - A list of all protocols in the system. (simple list for now)
+// gHandleList - A list of all the handles in the system
+// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
+// gHandleDatabaseKey - The Key to show that the handle has been created/modified
+//
+static EFI_LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+EFI_LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
+EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+UINT64 gHandleDatabaseKey = 0;
+
+
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Acquire lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreAcquireLock (&gProtocolDatabaseLock);
+}
+
+
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Release lock on gProtocolDatabaseLock.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ CoreReleaseLock (&gProtocolDatabaseLock);
+}
+
+
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ )
+/*++
+
+Routine Description:
+
+ Check whether a handle is a valid EFI_HANDLE
+
+Arguments:
+
+ UserHandle - The handle to check
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
+
+ EFI_SUCCESS - The handle is valid EFI_HANDLE.
+
+--*/
+{
+ IHANDLE *Handle;
+
+ Handle = (IHANDLE *)UserHandle;
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol entry for the requested protocol.
+
+ N.B. The gProtocolDatabaseLock must be owned
+
+Arguments:
+
+ Protocol - The ID of the protocol
+
+ Create - Create a new entry if not found
+
+Returns:
+
+ Protocol entry
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *Item;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ ASSERT_LOCKED(&gProtocolDatabaseLock);
+
+ //
+ // Search the database for the matching GUID
+ //
+
+ ProtEntry = NULL;
+ for (Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink) {
+
+ Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+ if (EfiCompareGuid (&Item->ProtocolID, Protocol)) {
+
+ //
+ // This is the protocol entry
+ //
+
+ ProtEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((ProtEntry == NULL) && Create) {
+ ProtEntry = CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY));
+
+ if (ProtEntry != NULL) {
+ //
+ // Initialize new protocol entry structure
+ //
+ ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
+ ProtEntry->ProtocolID = *Protocol;
+ InitializeListHead (&ProtEntry->Protocols);
+ InitializeListHead (&ProtEntry->Notify);
+
+ //
+ // Add it to protocol database
+ //
+ InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
+ }
+ }
+
+ return ProtEntry;
+}
+
+
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Finds the protocol instance for the requested handle and protocol.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ Handle - The handle to search the protocol on
+
+ Protocol - GUID of the protocol
+
+ Interface - The interface for the protocol being searched
+
+Returns:
+
+ Protocol instance (NULL: Not found)
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ EFI_LIST_ENTRY *Link;
+
+ ASSERT_LOCKED(&gProtocolDatabaseLock);
+ Prot = NULL;
+
+ //
+ // Lookup the protocol entry for this protocol ID
+ //
+
+ ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (ProtEntry != NULL) {
+
+ //
+ // Look at each protocol interface for any matches
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
+
+ //
+ // If this protocol interface matches, remove it
+ //
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
+ break;
+ }
+
+ Prot = NULL;
+ }
+ }
+
+ return Prot;
+}
+
+STATIC
+EFI_STATUS
+CoreUnregisterProtocolNotifyEvent (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes an event from a register protocol notify list on a protocol.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS if the event was found and removed.
+ EFI_NOT_FOUND if the event was not found in the protocl database.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *ProtEntry;
+ EFI_LIST_ENTRY *NotifyLink;
+ PROTOCOL_NOTIFY *ProtNotify;
+
+ CoreAcquireProtocolLock ();
+
+ for ( Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink) {
+
+ ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+
+ for ( NotifyLink = ProtEntry->Notify.ForwardLink;
+ NotifyLink != &ProtEntry->Notify;
+ NotifyLink = NotifyLink->ForwardLink) {
+
+ ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Event == Event) {
+ RemoveEntryList(&ProtNotify->Link);
+ CoreFreePool(ProtNotify);
+ CoreReleaseProtocolLock ();
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+CoreUnregisterProtocolNotify (
+ IN EFI_EVENT Event
+ )
+/*++
+
+Routine Description:
+
+ Removes all the events in the protocol database that match Event.
+
+Arguments:
+
+ Event - The event to search for in the protocol database.
+
+Returns:
+
+ EFI_SUCCESS when done searching the entire database.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ do {
+ Status = CoreUnregisterProtocolNotifyEvent (Event);
+ } while (!EFI_ERROR (Status));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
+ Calls the private one which contains a BOOLEAN parameter for notifications
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+Returns:
+
+ Status code
+
+--*/
+{
+ return CoreInstallProtocolInterfaceNotify (
+ UserHandle,
+ Protocol,
+ InterfaceType,
+ Interface,
+ TRUE
+ );
+}
+
+EFI_STATUS
+CoreInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ )
+/*++
+
+Routine Description:
+
+ Installs a protocol interface into the boot services environment.
+
+Arguments:
+
+ UserHandle - The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+
+ Protocol - The protocol to add to the handle
+
+ InterfaceType - Indicates whether Interface is supplied in native form.
+
+ Interface - The interface for the protocol being added
+
+ Notify - indicates whether notify the notification list
+ for this protocol
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Protocol interface successfully installed
+
+--*/
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ IHANDLE *Handle;
+ EFI_STATUS Status;
+ VOID *ExistingInterface;
+
+ //
+ // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
+ // Also added check for invalid UserHandle and Protocol pointers.
+ //
+ if (UserHandle == NULL || Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterfaceType != EFI_NATIVE_INTERFACE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print debug message
+ //
+//*** AMI PORTING BEGIN ***//
+//Disable Protocol debug message
+// DEBUG((EFI_D_ERROR | EFI_D_INFO, "InstallProtocolInterface: %g %x\n", Protocol, Interface));
+//*** AMI PORTING END *****//
+
+ Status = EFI_OUT_OF_RESOURCES;
+ Prot = NULL;
+ Handle = NULL;
+
+ ASSERT (NULL != gBS);
+
+ if (*UserHandle != NULL_HANDLE) {
+ Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
+ if (!EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Lookup the Protocol Entry for the requested protocol
+ //
+ ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
+ if (ProtEntry == NULL) {
+ goto Done;
+ }
+
+ //
+ // Allocate a new protocol interface structure
+ //
+ Prot = CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE));
+ if (Prot == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // If caller didn't supply a handle, allocate a new one
+ //
+ Handle = (IHANDLE *)*UserHandle;
+ if (Handle == NULL) {
+ Handle = CoreAllocateZeroBootServicesPool (sizeof(IHANDLE));
+ if (Handle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize new handler structure
+ //
+ Handle->Signature = EFI_HANDLE_SIGNATURE;
+ InitializeListHead (&Handle->Protocols);
+
+ //
+ // Initialize the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Add this handle to the list global list of all handles
+ // in the system
+ //
+ InsertTailList (&gHandleList, &Handle->AllHandles);
+ }
+
+ Status = CoreValidateHandle (Handle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Each interface that is added must be unique
+ //
+ ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
+
+ //
+ // Initialize the protocol interface structure
+ //
+ Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
+ Prot->Handle = Handle;
+ Prot->Protocol = ProtEntry;
+ Prot->Interface = Interface;
+
+ //
+ // Initalize OpenProtocol Data base
+ //
+ InitializeListHead (&Prot->OpenList);
+ Prot->OpenListCount = 0;
+
+ //
+ // Add this protocol interface to the head of the supported
+ // protocol list for this handle
+ //
+ InsertHeadList (&Handle->Protocols, &Prot->Link);
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Notify the notification list for this protocol
+ //
+ if (Notify) {
+ CoreNotifyProtocolEntry (ProtEntry);
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ if (!EFI_ERROR (Status)) {
+ //
+ // Return the new handle back to the caller
+ //
+ *UserHandle = Handle;
+ } else {
+ //
+ // There was an error, clean up
+ //
+ if (Prot != NULL) {
+ CoreFreePool (Prot);
+ }
+ }
+
+ return Status;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreInstallMultipleProtocolInterfaces (
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Installs a list of protocol interface into the boot services environment.
+ This function calls InstallProtocolInterface() in a loop. If any error
+ occures all the protocols added by this function are removed. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to install the protocol handlers on,
+ or NULL if a new handle is to be allocated
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to InstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Handle is NULL.
+
+ EFI_SUCCESS - Protocol interfaces successfully installed.
+
+--*/
+{
+ VA_LIST args;
+ EFI_STATUS Status;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ EFI_TPL OldTpl;
+ UINTN Index;
+ EFI_HANDLE OldHandle;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Syncronize with notifcations.
+ //
+ OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
+ OldHandle = *Handle;
+
+ //
+ // Check for duplicate device path and install the protocol interfaces
+ //
+ VA_START (args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (args, VOID *);
+
+ //
+ // Make sure you are installing on top a device path that has already been added.
+ //
+ if (EfiCompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
+ DeviceHandle = NULL;
+ DevicePath = Interface;
+ Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
+ Status = EFI_ALREADY_STARTED;
+ continue;
+ }
+ }
+
+ //
+ // Install it
+ //
+ Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+
+ //
+ // If there was an error, remove all the interfaces that were installed without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (args, Handle);
+ for (; Index > 1; Index--) {
+ Protocol = VA_ARG (args, EFI_GUID *);
+ Interface = VA_ARG (args, VOID *);
+ CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
+ }
+ *Handle = OldHandle;
+ }
+
+ //
+ // Done
+ //
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ )
+/*++
+
+Routine Description:
+
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+Arguments:
+
+ UserHandle - The handle on which the protocol is installed
+ Prot - The protocol to disconnect drivers from
+
+Returns:
+
+ EFI_SUCCESS - Drivers using the protocol interface are all disconnected
+ EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
+
+--*/
+{
+ EFI_STATUS Status;
+ BOOLEAN ItemFound;
+ EFI_LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Attempt to disconnect all drivers from this protocol interface
+ //
+ do {
+ ItemFound = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink;
+ (Link != &Prot->OpenList) && !ItemFound;
+ Link = Link->ForwardLink ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ ItemFound = TRUE;
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (EFI_ERROR (Status)) {
+ ItemFound = FALSE;
+ break;
+ }
+ }
+ }
+ } while (ItemFound);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
+ //
+ do {
+ ItemFound = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink;
+ (Link != &Prot->OpenList) && !ItemFound;
+ Link = Link->ForwardLink ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes &
+ (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
+ ItemFound = TRUE;
+ RemoveEntryList (&OpenData->Link);
+ Prot->OpenListCount--;
+ CoreFreePool (OpenData);
+ }
+ }
+ } while (ItemFound);
+ }
+
+ //
+ // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
+ //
+ if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
+ CoreReleaseProtocolLock ();
+ CoreConnectController (UserHandle, NULL, NULL, TRUE);
+ CoreAcquireProtocolLock ();
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ return Status;
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls all instances of a protocol:interfacer from a handle.
+ If the last protocol interface is remove from the handle, the
+ handle is freed.
+
+Arguments:
+
+ UserHandle - The handle to remove the protocol handler from
+
+ Protocol - The protocol, of protocol:interface, to remove
+
+ Interface - The interface, of protocol:interface, to remove
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Protocol interface successfully uninstalled.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+
+ //
+ // Check that Protocol is valid
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check that UserHandle is a valid handle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
+ if (Prot == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
+ //
+ Status = CoreDisconnectControllersUsingProtocolInterface (
+ UserHandle,
+ Prot
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // One or more drivers refused to release, so return the error
+ //
+ goto Done;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Status = EFI_NOT_FOUND;
+ Handle = (IHANDLE *)UserHandle;
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
+
+ if (Prot != NULL) {
+ //
+ // Update the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Remove the protocol interface from the handle
+ //
+ RemoveEntryList (&Prot->Link);
+
+ //
+ // Free the memory
+ //
+ Prot->Signature = 0;
+ CoreFreePool (Prot);
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // If there are no more handlers for the handle, free the handle
+ //
+ if (IsListEmpty (&Handle->Protocols)) {
+ Handle->Signature = 0;
+ RemoveEntryList (&Handle->AllHandles);
+ CoreFreePool (Handle);
+ }
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreUninstallMultipleProtocolInterfaces (
+ IN EFI_HANDLE Handle,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Uninstalls a list of protocol interface in the boot services environment.
+ This function calls UnisatllProtocolInterface() in a loop. This is
+ basically a lib function to save space.
+
+Arguments:
+
+ Handle - The handle to uninstall the protocol
+
+ ... - EFI_GUID followed by protocol instance. A NULL terminates the
+ list. The pairs are the arguments to UninstallProtocolInterface().
+ All the protocols are added to Handle.
+
+Returns:
+
+ Status code
+
+--*/
+{
+ EFI_STATUS Status;
+ VA_LIST args;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ UINTN Index;
+
+ VA_START (args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (args, VOID *);
+
+ //
+ // Uninstall it
+ //
+ Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
+ }
+
+ //
+ // If there was an error, add all the interfaces that were
+ // uninstalled without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (args, Handle);
+ for (; Index > 1; Index--) {
+ Protocol = VA_ARG(args, EFI_GUID *);
+ Interface = VA_ARG(args, VOID *);
+ CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+ }
+
+ return Status;
+}
+
+PROTOCOL_INTERFACE *
+CoreGetProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol
+ )
+/*++
+
+Routine Description:
+
+ Locate a certain GUID protocol interface in a Handle's protocols.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The GUID of the protocol
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_INTERFACE *Prot;
+ IHANDLE *Handle;
+ EFI_LIST_ENTRY *Link;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+
+ //
+ // Look at each protocol interface for a match
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ ProtEntry = Prot->Protocol;
+ if (EfiCompareGuid (&ProtEntry->ProtocolID, Protocol)) {
+ return Prot;
+ }
+ }
+ return NULL;
+}
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Queries a handle to determine if it supports a specified protocol.
+
+Arguments:
+
+ UserHandle - The handle being queried.
+
+ Protocol - The published unique identifier of the protocol.
+
+ Interface - Supplies the address where a pointer to the corresponding Protocol
+ Interface is returned.
+
+Returns:
+
+ The requested protocol interface for the handle
+
+--*/
+{
+ return CoreOpenProtocol (
+ UserHandle,
+ Protocol,
+ Interface,
+ gDxeCoreImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+}
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreOpenProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface OPTIONAL,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Locates the installed protocol handler for the handle, and
+ invokes it to obtain the protocol interface. Usage information
+ is registered in the protocol data base.
+
+Arguments:
+
+ UserHandle - The handle to obtain the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ Interface - The location to return the protocol interface
+
+ ImageHandle - The handle of the Image that is opening the protocol interface
+ specified by Protocol and Interface.
+
+ ControllerHandle - The controller handle that is requiring this interface.
+
+ Attributes - The open mode of the protocol interface specified by Handle
+ and Protocol.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Protocol is NULL.
+
+ EFI_SUCCESS - Get the protocol interface.
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ BOOLEAN ByDriver;
+ BOOLEAN Exclusive;
+ BOOLEAN Disconnect;
+ BOOLEAN ExactMatch;
+
+ //
+ // Check for invalid Protocol
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for invalid Interface
+ //
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ *Interface = NULL;
+ }
+ }
+
+ //
+ // Check for invalid UserHandle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check for invalid Attributes
+ //
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (UserHandle == ControllerHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER :
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Prot = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (Prot == NULL) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ //
+ // This is the protocol interface entry for this protocol
+ //
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+ *Interface = Prot->Interface;
+ }
+ Status = EFI_SUCCESS;
+
+ ByDriver = FALSE;
+ Exclusive = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
+ (OpenData->Attributes == Attributes) &&
+ (OpenData->ControllerHandle == ControllerHandle));
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ ByDriver = TRUE;
+ if (ExactMatch) {
+ Status = EFI_ALREADY_STARTED;
+ goto Done;
+ }
+ }
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+ Exclusive = TRUE;
+ } else if (ExactMatch) {
+ OpenData->OpenCount++;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
+ // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
+ // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
+ // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
+ //
+
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_DRIVER :
+ if (Exclusive || ByDriver) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+ if (Exclusive) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ if (ByDriver) {
+ do {
+ Disconnect = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ Disconnect = TRUE;
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+ }
+ }
+ } while (Disconnect);
+ }
+ break;
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+ break;
+ }
+
+ if (ImageHandle == NULL) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ //
+ // Create new entry
+ //
+ OpenData = CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA));
+ if (OpenData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
+ OpenData->AgentHandle = ImageHandle;
+ OpenData->ControllerHandle = ControllerHandle;
+ OpenData->Attributes = Attributes;
+ OpenData->OpenCount = 1;
+ InsertTailList (&Prot->OpenList, &OpenData->Link);
+ Prot->OpenListCount++;
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+ //
+ // Done. Release the database lock are return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreCloseProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE AgentHandle,
+ IN EFI_HANDLE ControllerHandle
+ )
+/*++
+
+Routine Description:
+
+ Closes a protocol on a handle that was opened using OpenProtocol().
+
+Arguments:
+
+ UserHandle - The handle for the protocol interface that was previously opened
+ with OpenProtocol(), and is now being closed.
+ Protocol - The published unique identifier of the protocol. It is the caller's
+ responsibility to pass in a valid GUID.
+ AgentHandle - The handle of the agent that is closing the protocol interface.
+ ControllerHandle - If the agent that opened a protocol is a driver that follows the
+ EFI Driver Model, then this parameter is the controller handle
+ that required the protocol interface. If the agent does not follow
+ the EFI Driver Model, then this parameter is optional and may be NULL.
+
+Returns:
+
+ EFI_SUCCESS - The protocol instance was closed.
+ EFI_INVALID_PARAMETER - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE.
+ EFI_NOT_FOUND - Can not find the specified protocol or AgentHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ EFI_LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ //
+ // Check for invalid parameters
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = CoreValidateHandle (AgentHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ControllerHandle != NULL_HANDLE) {
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Walk the Open data base looking for AgentHandle
+ //
+ Link = ProtocolInterface->OpenList.ForwardLink;
+ while (Link != &ProtocolInterface->OpenList) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ Link = Link->ForwardLink;
+ if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
+ RemoveEntryList (&OpenData->Link);
+ ProtocolInterface->OpenListCount--;
+ CoreFreePool (OpenData);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+Done:
+ //
+ // Done. Release the database lock and return.
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreOpenProtocolInformation (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ )
+/*++
+
+Routine Description:
+
+ Return information about Opened protocols in the system
+
+Arguments:
+
+ UserHandle - The handle to close the protocol interface on
+
+ Protocol - The ID of the protocol
+
+ EntryBuffer - A pointer to a buffer of open protocol information in the form of
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+
+ EntryCount - Number of EntryBuffer entries
+
+Returns:
+
+
+--*/
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ EFI_LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
+ UINTN Count;
+ UINTN Size;
+
+ *EntryBuffer = NULL;
+ *EntryCount = 0;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Count the number of Open Entries
+ //
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList) ;
+ Link = Link->ForwardLink ) {
+ Count++;
+ }
+
+ ASSERT (Count == ProtocolInterface->OpenListCount);
+
+ if (Count == 0) {
+ Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ } else {
+ Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ }
+
+ Buffer = CoreAllocateBootServicesPool (Size);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = EFI_SUCCESS;
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList);
+ Link = Link->ForwardLink, Count++ ) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+
+ Buffer[Count].AgentHandle = OpenData->AgentHandle;
+ Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
+ Buffer[Count].Attributes = OpenData->Attributes;
+ Buffer[Count].OpenCount = OpenData->OpenCount;
+ }
+
+ *EntryBuffer = Buffer;
+ *EntryCount = Count;
+
+Done:
+ //
+ // Done. Release the database lock are return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreProtocolsPerHandle (
+ IN EFI_HANDLE UserHandle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+Arguments:
+
+ UserHandle - The handle from which to retrieve the list of protocol interface
+ GUIDs.
+
+ ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are
+ installed on Handle.
+
+ ProtocolBufferCount - A pointer to the number of GUID pointers present in
+ ProtocolBuffer.
+
+Returns:
+ EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in
+ ProtocolBuffer. The number of protocol interface GUIDs was
+ returned in ProtocolBufferCount.
+ EFI_INVALID_PARAMETER - Handle is NULL.
+ EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ProtocolBuffer is NULL.
+ EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results.
+
+--*/
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_LIST_ENTRY *Link;
+ UINTN ProtocolCount;
+ EFI_GUID **Buffer;
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+
+ if (ProtocolBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ProtocolBufferCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ProtocolBufferCount = 0;
+
+ ProtocolCount = 0;
+
+ CoreAcquireProtocolLock ();
+
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ ProtocolCount++;
+ }
+
+ //
+ // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
+ //
+ if (ProtocolCount == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Buffer = CoreAllocateBootServicesPool (sizeof (EFI_GUID *) * ProtocolCount);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *ProtocolBuffer = Buffer;
+ *ProtocolBufferCount = ProtocolCount;
+
+ for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
+ Link != &Handle->Protocols;
+ Link = Link->ForwardLink, ProtocolCount++) {
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
+ }
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+UINT64
+CoreGetHandleDatabaseKey (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ return handle database key.
+
+Arguments:
+
+ None
+
+Returns:
+
+ Handle database key.
+
+--*/
+{
+ return gHandleDatabaseKey;
+}
+
+
+VOID
+CoreConnectHandlesByKey (
+ UINT64 Key
+ )
+/*++
+
+Routine Description:
+
+ Go connect any handles that were created or modified while a image executed.
+
+Arguments:
+
+ Key - The Key to show that the handle has been created/modified
+
+Returns:
+
+ None
+--*/
+{
+ UINTN Count;
+ EFI_LIST_ENTRY *Link;
+ EFI_HANDLE *HandleBuffer;
+ IHANDLE *Handle;
+ UINTN Index;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ Count++;
+ }
+ }
+
+ HandleBuffer = CoreAllocateBootServicesPool (Count * sizeof (EFI_HANDLE));
+ if (HandleBuffer == NULL) {
+ CoreReleaseProtocolLock ();
+ return;
+ }
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ HandleBuffer[Count++] = Handle;
+ }
+ }
+
+ //
+ // Unlock the protocol database
+ //
+ CoreReleaseProtocolLock ();
+
+ //
+ // Connect all handles whose Key value is greater than Key
+ //
+ for (Index = 0; Index < Count; Index++) {
+ CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ CoreFreePool(HandleBuffer);
+}
diff --git a/Core/CORE_DXE/hob.c b/Core/CORE_DXE/hob.c
new file mode 100644
index 0000000..7c96c69
--- /dev/null
+++ b/Core/CORE_DXE/hob.c
@@ -0,0 +1,530 @@
+/*++
+
+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:
+
+ hob.c
+
+Abstract:
+
+ Support for hob operation
+
+--*/
+
+#include "Tiano.h"
+#include "EfiCommonLib.h"
+//#include "EfiDriverLib.h"
+#include "PeiHob.h"
+//#include EFI_GUID_DEFINITION (IoBaseHob)
+//#include EFI_GUID_DEFINITION (MemoryAllocationHob)
+
+VOID *
+GetHob (
+ IN UINT16 Type,
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ This function returns the first instance of a HOB type in a HOB list.
+
+Arguments:
+
+ Type The HOB type to return.
+ HobStart The first HOB in the HOB list.
+
+Returns:
+
+ HobStart There were no HOBs found with the requested type.
+ else Returns the first HOB with the matching type.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Hob.Raw = HobStart;
+ //
+ // Return input if not found
+ //
+ if (HobStart == NULL) {
+ return HobStart;
+ }
+
+ //
+ // Parse the HOB list, stop if end of list or matching type found.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+
+ if (Hob.Header->HobType == Type) {
+ break;
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ //
+ // Return input if not found
+ //
+ if (END_OF_HOB_LIST (Hob)) {
+ return HobStart;
+ }
+
+ return (VOID *) (Hob.Raw);
+}
+
+UINTN
+GetHobListSize (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Get size of hob list.
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+Returns:
+
+ Size of hob list.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN Size;
+
+ Hob.Raw = HobStart;
+ Size = 0;
+
+ while (Hob.Header->HobType != EFI_HOB_TYPE_END_OF_HOB_LIST) {
+ Size += Hob.Header->HobLength;
+ Hob.Raw += Hob.Header->HobLength;
+ }
+
+ Size += Hob.Header->HobLength;
+
+ return Size;
+}
+
+UINT32
+GetHobVersion (
+ IN VOID *HobStart
+ )
+/*++
+
+Routine Description:
+
+ Get hob version.
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+Returns:
+
+ Hob version.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Hob.Raw = HobStart;
+ return Hob.HandoffInformationTable->Version;
+}
+
+EFI_STATUS
+GetHobBootMode (
+ IN VOID *HobStart,
+ OUT EFI_BOOT_MODE *BootMode
+ )
+/*++
+
+Routine Description:
+
+ Get current boot mode.
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ BootMode - Current boot mode recorded in PHIT hob
+
+Returns:
+
+ EFI_NOT_FOUND - Invalid hob header
+
+ EFI_SUCCESS - Boot mode found
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Hob.Raw = HobStart;
+ if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {
+ return EFI_NOT_FOUND;
+ }
+
+ *BootMode = Hob.HandoffInformationTable->BootMode;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetCpuHobInfo (
+ IN VOID *HobStart,
+ OUT UINT8 *SizeOfMemorySpace,
+ OUT UINT8 *SizeOfIoSpace
+ )
+/*++
+
+Routine Description:
+
+ Get information recorded in CPU hob (Memory space size, Io space size)
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ SizeOfMemorySpace - Size of memory size
+
+ SizeOfIoSpace - Size of IO size
+
+Returns:
+
+ EFI_NOT_FOUND - CPU hob not found
+
+ EFI_SUCCESS - CPU hob found and information got.
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS CpuHob;
+
+ CpuHob.Raw = HobStart;
+ CpuHob.Raw = GetHob (EFI_HOB_TYPE_CPU, CpuHob.Raw);
+ if (CpuHob.Header->HobType != EFI_HOB_TYPE_CPU) {
+ return EFI_NOT_FOUND;
+ }
+
+ *SizeOfMemorySpace = CpuHob.Cpu->SizeOfMemorySpace;
+ *SizeOfIoSpace = CpuHob.Cpu->SizeOfIoSpace;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetDxeCoreHobInfo (
+ IN VOID *HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length,
+ OUT VOID **EntryPoint,
+ OUT EFI_GUID **FileName
+ )
+/*++
+
+Routine Description:
+
+ Get memory allocation hob created for DXE core and extract its information
+
+Arguments:
+
+ HobStart - Start pointer of the hob list
+
+ BaseAddress - Start address of memory allocated for DXE core
+
+ Length - Length of memory allocated for DXE core
+
+ EntryPoint - DXE core file name
+
+Returns:
+
+ EFI_NOT_FOUND - DxeCoreHob not found
+
+ EFI_SUCCESS - DxeCoreHob found and information got
+
+ FileName - FileName
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS DxeCoreHob;
+#define EFI_HOB_MEMORY_ALLOC_MODULE_GUID \
+ {0xf8e21975, 0x899, 0x4f58, 0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6,0xd7, 0x7a}
+ static EFI_GUID gEfiHobMemeryAllocModuleGuid=EFI_HOB_MEMORY_ALLOC_MODULE_GUID;
+ DxeCoreHob.Raw = HobStart;
+ DxeCoreHob.Raw = GetHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw);
+ while(!END_OF_HOB_LIST(DxeCoreHob) &&
+ !EfiCompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemeryAllocModuleGuid)) {
+
+ DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
+ DxeCoreHob.Raw = GetHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw);
+
+ }
+
+ if (END_OF_HOB_LIST (DxeCoreHob)) {
+ return EFI_NOT_FOUND;
+ }
+
+ *BaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
+ *Length = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
+ *EntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;
+ *FileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNextFirmwareVolumeHob (
+ IN OUT VOID **HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length
+ )
+/*++
+
+Routine Description:
+
+ Get next firmware volume hob from HobStart
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ BaseAddress - Start address of next firmware volume
+
+ Length - Length of next firmware volume
+
+Returns:
+
+ EFI_NOT_FOUND - Next firmware volume not found
+
+ EFI_SUCCESS - Next firmware volume found with address information
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS FirmwareVolumeHob;
+
+ FirmwareVolumeHob.Raw = *HobStart;
+ if (END_OF_HOB_LIST (FirmwareVolumeHob)) {
+ return EFI_NOT_FOUND;
+ }
+
+ FirmwareVolumeHob.Raw = GetHob (EFI_HOB_TYPE_FV, *HobStart);
+ if (FirmwareVolumeHob.Header->HobType != EFI_HOB_TYPE_FV) {
+ return EFI_NOT_FOUND;
+ }
+
+ *BaseAddress = FirmwareVolumeHob.FirmwareVolume->BaseAddress;
+ *Length = FirmwareVolumeHob.FirmwareVolume->Length;
+
+ *HobStart = GET_NEXT_HOB (FirmwareVolumeHob);
+
+ return EFI_SUCCESS;
+}
+
+//PI 1.1 ++
+#if defined (PI_SPECIFICATION_VERSION) && (PI_SPECIFICATION_VERSION >= 0x00010000)
+EFI_STATUS
+GetNextFirmwareVolume2Hob (
+ IN OUT VOID **HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length,
+ OUT EFI_GUID *FileName
+ )
+/*++
+
+Routine Description:
+
+ Get next firmware volume2 hob from HobStart
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ BaseAddress - Start address of next firmware volume
+
+ Length - Length of next firmware volume
+
+Returns:
+
+ EFI_NOT_FOUND - Next firmware volume not found
+
+ EFI_SUCCESS - Next firmware volume found with address information
+
+--*/
+{
+ EFI_PEI_HOB_POINTERS FirmwareVolumeHob;
+
+ FirmwareVolumeHob.Raw = *HobStart;
+ if (END_OF_HOB_LIST (FirmwareVolumeHob)) {
+ return EFI_NOT_FOUND;
+ }
+
+ FirmwareVolumeHob.Raw = GetHob (EFI_HOB_TYPE_FV2, *HobStart);
+ if (FirmwareVolumeHob.Header->HobType != EFI_HOB_TYPE_FV2) {
+ return EFI_NOT_FOUND;
+ }
+
+ *BaseAddress = FirmwareVolumeHob.FirmwareVolume2->BaseAddress;
+ *Length = FirmwareVolumeHob.FirmwareVolume2->Length;
+ EfiCommonLibCopyMem(FileName,&FirmwareVolumeHob.FirmwareVolume2->FileName,sizeof(EFI_GUID));
+
+ *HobStart = GET_NEXT_HOB (FirmwareVolumeHob);
+
+ return EFI_SUCCESS;
+}
+#endif
+//PI 1.1 --
+
+EFI_STATUS
+GetNextGuidHob (
+ IN OUT VOID **HobStart,
+ IN EFI_GUID * Guid,
+ OUT VOID **Buffer,
+ OUT UINTN *BufferSize OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Get the next guid hob.
+
+Arguments:
+ HobStart A pointer to the start hob.
+ Guid A pointer to a guid.
+ Buffer A pointer to the buffer.
+ BufferSize Buffer size.
+
+Returns:
+ Status code.
+
+ EFI_NOT_FOUND - Next Guid hob not found
+
+ EFI_SUCCESS - Next Guid hob found and data for this Guid got
+
+ EFI_INVALID_PARAMETER - invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Status = EFI_NOT_FOUND; EFI_ERROR (Status);) {
+
+ GuidHob.Raw = *HobStart;
+ if (END_OF_HOB_LIST (GuidHob)) {
+ return EFI_NOT_FOUND;
+ }
+
+ GuidHob.Raw = GetHob (EFI_HOB_TYPE_GUID_EXTENSION, *HobStart);
+ if (GuidHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
+ if (EfiCompareGuid (Guid, &GuidHob.Guid->Name)) {
+ Status = EFI_SUCCESS;
+ *Buffer = (VOID *) ((UINT8 *) (&GuidHob.Guid->Name) + sizeof (EFI_GUID));
+ if (BufferSize != NULL) {
+ *BufferSize = GuidHob.Header->HobLength - sizeof (EFI_HOB_GUID_TYPE);
+ }
+ }
+ }
+
+ *HobStart = GET_NEXT_HOB (GuidHob);
+ }
+
+ return Status;
+}
+
+
+#define PAL_ENTRY_HOB {0xe53cb8cc, 0xd62c, 0x4f74, 0xbd, 0xda, 0x31, 0xe5, 0x8d, 0xe5, 0x3e, 0x2}
+EFI_GUID gPalEntryHob = PAL_ENTRY_HOB;
+
+EFI_STATUS
+GetPalEntryHobInfo (
+ IN VOID *HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *PalEntry
+ )
+/*++
+
+Routine Description:
+
+ Get PAL entry from PalEntryHob
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ PalEntry - Pointer to PAL entry
+
+Returns:
+
+ Status code.
+
+--*/
+{
+ VOID *Buffer;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+ VOID *HobStart2;
+
+ HobStart2 = HobStart;
+ Status = GetNextGuidHob (
+ &HobStart2,
+ &gPalEntryHob,
+ &Buffer,
+ &BufferSize
+ );
+
+ *PalEntry = *((EFI_PHYSICAL_ADDRESS *) Buffer);
+ return Status;
+}
+
+
+EFI_STATUS
+GetIoPortSpaceAddressHobInfo (
+ IN VOID *HobStart,
+ OUT EFI_PHYSICAL_ADDRESS *IoPortSpaceAddress
+ )
+/*++
+
+Routine Description:
+
+ Get IO port space address from IoBaseHob.
+
+Arguments:
+
+ HobStart - Start pointer of hob list
+
+ IoPortSpaceAddress - IO port space address
+
+Returns:
+
+ Status code
+
+--*/
+{
+/*
+ VOID *Buffer;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+ VOID *HobStart2;
+
+ HobStart2 = HobStart;
+ Status = GetNextGuidHob (
+ &HobStart2,
+ &gEfiIoBaseHobGuid,
+ &Buffer,
+ &BufferSize
+ );
+
+ *IoPortSpaceAddress = *((EFI_PHYSICAL_ADDRESS *) Buffer);
+ return Status;*/
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/imem.h b/Core/CORE_DXE/imem.h
new file mode 100644
index 0000000..d9029c5
--- /dev/null
+++ b/Core/CORE_DXE/imem.h
@@ -0,0 +1,214 @@
+/*++
+
+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:
+
+ imem.h
+
+Abstract:
+
+ Head file to imem.h
+
+
+Revision History
+
+--*/
+
+#ifndef _IMEM_H_
+#define _IMEM_H_
+
+#include "Tiano.h"
+#include "DxeCore.h"
+#include "Processor.h"
+
+//
+// MEMORY_MAP_ENTRY
+//
+
+#define MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('m','m','a','p')
+typedef struct {
+ UINTN Signature;
+ EFI_LIST_ENTRY Link;
+ BOOLEAN FromPages;
+
+ EFI_MEMORY_TYPE Type;
+ UINT64 Start;
+ UINT64 End;
+
+ UINT64 VirtualStart;
+ UINT64 Attribute;
+} MEMORY_MAP;
+
+//
+// Internal prototypes
+//
+
+VOID *
+CoreAllocatePoolPages (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NumberOfPages,
+ IN UINTN Alignment
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Used by the pool functions to allocate pages
+ to back pool allocation requests.
+
+Arguments:
+
+ PoolType - The type of memory for the new pool pages
+
+ NumberOfPages - No of pages to allocate
+
+ Alignment - Bits to align.
+
+Returns:
+
+ The allocated memory, or NULL
+
+--*/
+;
+
+
+VOID
+CoreFreePoolPages (
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NumberOfPages
+ )
+/*++
+
+Routine Description:
+
+ Internal function. Frees pool pages allocated via AllocatePoolPages ()
+
+Arguments:
+
+ Memory - The base address to free
+
+ NumberOfPages - The number of pages to free
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+VOID *
+CoreAllocatePoolI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Internal function to allocate pool of a particular type.
+
+ N.B. Caller must have the memory lock held
+
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+Returns:
+
+ The allocate pool, or NULL
+
+--*/
+;
+
+
+EFI_STATUS
+CoreFreePoolI (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Internal function to free a pool entry.
+
+ N.B. Caller must have the memory lock held
+
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer not valid
+
+ EFI_SUCCESS - Buffer successfully freed.
+
+--*/
+;
+
+
+VOID
+CoreAcquireMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enter critical section by gaining lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+CoreReleaseMemoryLock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Exit critical section by releasing lock on gMemoryLock
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+//
+// Internal Global data
+//
+
+extern EFI_LOCK gMemoryLock;
+extern EFI_LIST_ENTRY gMemoryMap;
+extern MEMORY_MAP *gMemoryLastConvert;
+extern EFI_LIST_ENTRY mGcdMemorySpaceMap;
+#endif
diff --git a/Core/CORE_DXE/locate.c b/Core/CORE_DXE/locate.c
new file mode 100644
index 0000000..413e671
--- /dev/null
+++ b/Core/CORE_DXE/locate.c
@@ -0,0 +1,777 @@
+/*++
+
+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:
+
+ locate.c
+
+Abstract:
+
+ Locate handle functions
+
+Revision History
+
+--*/
+
+#include "hand.h"
+
+//
+// ProtocolRequest - Last LocateHandle request ID
+//
+UINTN mEfiLocateHandleRequest = 0;
+
+//
+// Internal prototypes
+//
+
+typedef struct {
+ EFI_GUID *Protocol;
+ VOID *SearchKey;
+ EFI_LIST_ENTRY *Position;
+ PROTOCOL_ENTRY *ProtEntry;
+} LOCATE_POSITION;
+
+typedef
+IHANDLE *
+(* CORE_GET_NEXT) (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+//
+//
+//
+
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Locates the requested handle(s) and returns them in Buffer.
+
+Arguments:
+
+ SearchType - The type of search to perform to locate the handles
+
+ Protocol - The protocol to search for
+
+ SearchKey - Dependant on SearchType
+
+ BufferSize - On input the size of Buffer. On output the
+ size of data returned.
+
+ Buffer - The buffer to return the results in
+
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
+
+--*/
+{
+ EFI_STATUS Status;
+ LOCATE_POSITION Position;
+ PROTOCOL_NOTIFY *ProtNotify;
+ CORE_GET_NEXT GetNext;
+ UINTN ResultSize;
+ IHANDLE *Handle;
+ IHANDLE **ResultBuffer;
+ VOID *Interface;
+
+//*** AMI PORTING BEGIN *****//
+ BOOLEAN ZeroSizeBuffer = FALSE;
+//*** AMI PORTING END *****//
+
+ if (BufferSize == NULL) {
+//*** AMI PORTING BEGIN ***//
+//Bug fix(EIP 82756): original code was just setting Status to EFI_INVALID_PARAMETER
+// and acessing *BufferSize right below.
+// This caused problems with the WHCK AllocateHandle test
+// Status = EFI_INVALID_PARAMETER;
+ ZeroSizeBuffer = TRUE;
+ } else {
+ if ((*BufferSize > 0) && (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+//*** AMI PORTING END *****//
+
+ GetNext = NULL;
+ //
+ // Set initial position
+ //
+
+ Position.Protocol = Protocol;
+ Position.SearchKey = SearchKey;
+ Position.Position = &gHandleList;
+
+ ResultSize = 0;
+ ResultBuffer = (IHANDLE **) Buffer;
+ Status = EFI_SUCCESS;
+
+ //
+ // Lock the protocol database
+ //
+
+ CoreAcquireProtocolLock ();
+
+ //
+ // Get the search function based on type
+ //
+ switch (SearchType) {
+ case AllHandles:
+ GetNext = CoreGetNextLocateAllHandles;
+ break;
+
+ case ByRegisterNotify:
+ //
+ // Must have SearchKey for locate ByRegisterNotify
+ //
+ if (SearchKey == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ GetNext = CoreGetNextLocateByRegisterNotify;
+ break;
+
+ case ByProtocol:
+ GetNext = CoreGetNextLocateByProtocol;
+ if (Protocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+//*** AMI PORTING BEGIN *****//
+/* If we're here, some handles are found.
+ We should return INVALID_PARAMETER if buffer size pointer is zero
+*/
+ if(ZeroSizeBuffer) {
+ return EFI_INVALID_PARAMETER;
+ }
+//*** AMI PORTING END *****//
+
+ //
+ // Enumerate out the matching handles
+ //
+ mEfiLocateHandleRequest += 1;
+ for (; ;) {
+ //
+ // Get the next handle. If no more handles, stop
+ //
+ Handle = GetNext (&Position, &Interface);
+ if (NULL == Handle) {
+ break;
+ }
+
+ //
+ // Increase the resulting buffer size, and if this handle
+ // fits return it
+ //
+ ResultSize += sizeof(Handle);
+ if (ResultSize <= *BufferSize) {
+ *ResultBuffer = Handle;
+ ResultBuffer += 1;
+ }
+ }
+
+ //
+ // If the result is a zero length buffer, then there were no
+ // matching handles
+ //
+ if (ResultSize == 0) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // Return the resulting buffer size. If it's larger than what
+ // was passed, then set the error code
+ //
+ if (ResultSize > *BufferSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = ResultSize;
+
+ if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = SearchKey;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for all handles.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+
+ //
+ // Next handle
+ //
+ Position->Position = Position->Position->ForwardLink;
+
+ //
+ // If not at the end of the list, get the handle
+ //
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ if (Position->Position != &gHandleList) {
+ Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ }
+
+ return Handle;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for register protocol
+ notifies.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+ PROTOCOL_NOTIFY *ProtNotify;
+ PROTOCOL_INTERFACE *Prot;
+ EFI_LIST_ENTRY *Link;
+
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ ProtNotify = Position->SearchKey;
+
+ //
+ // If this is the first request, get the next handle
+ //
+ if (ProtNotify != NULL) {
+ ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
+ Position->SearchKey = NULL;
+
+ //
+ // If not at the end of the list, get the next handle
+ //
+ Link = ProtNotify->Position->ForwardLink;
+ if (Link != &ProtNotify->Protocol->Protocols) {
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = (IHANDLE *) Prot->Handle;
+ *Interface = Prot->Interface;
+ }
+ }
+
+ return Handle;
+}
+
+
+STATIC
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Routine to get the next Handle, when you are searching for a given protocol.
+
+Arguments:
+
+ Position - Information about which Handle to seach for.
+
+ Interface - Return the interface structure for the matching protocol.
+
+Returns:
+ IHANDLE - An IHANDLE is returned if the next Position is not the end of the
+ list. A NULL_HANDLE is returned if it's the end of the list.
+
+--*/
+{
+ IHANDLE *Handle;
+ EFI_LIST_ENTRY *Link;
+ PROTOCOL_INTERFACE *Prot;
+
+ Handle = NULL_HANDLE;
+ *Interface = NULL;
+ for (; ;) {
+ //
+ // Next entry
+ //
+ Link = Position->Position->ForwardLink;
+ Position->Position = Link;
+
+ //
+ // If not at the end, return the handle
+ //
+ if (Link == &Position->ProtEntry->Protocols) {
+ Handle = NULL_HANDLE;
+ break;
+ }
+
+ //
+ // Get the handle
+ //
+ Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = (IHANDLE *) Prot->Handle;
+ *Interface = Prot->Interface;
+
+ //
+ // If this handle has not been returned this request, then
+ // return it now
+ //
+ if (Handle->LocateRequest != mEfiLocateHandleRequest) {
+ Handle->LocateRequest = mEfiLocateHandleRequest;
+ break;
+ }
+ }
+
+ return Handle;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreLocateDevicePath (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT EFI_HANDLE *Device
+ )
+/*++
+
+Routine Description:
+
+ Locates the handle to a device on the device path that best matches the specified protocol.
+
+Arguments:
+
+ Protocol - The protocol to search for.
+ DevicePath - On input, a pointer to a pointer to the device path. On output, the device
+ path pointer is modified to point to the remaining part of the devicepath.
+ Device - A pointer to the returned device handle.
+
+Returns:
+
+ EFI_SUCCESS - The resulting handle was returned.
+ EFI_NOT_FOUND - No handles matched the search.
+ EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
+
+--*/
+{
+ INTN SourceSize;
+ INTN Size;
+ INTN BestMatch;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *SourcePath;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
+
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DevicePath == NULL) || (*DevicePath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+//*** AMI PORTING BEGIN ***//
+//Modified to pass SCT test
+ //
+ // Get a list of all handles that support the requested protocol
+ //
+ Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
+ if (EFI_ERROR (Status) || HandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+//*** AMI PORTING END *****//
+
+ if (Device == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Device = NULL_HANDLE;
+ SourcePath = *DevicePath;
+ TmpDevicePath = SourcePath;
+ while (!EfiIsDevicePathEnd (TmpDevicePath)) {
+ if (EfiIsDevicePathEndInstance (TmpDevicePath)) {
+ //
+ // If DevicePath is a multi-instance device path,
+ // the function will operate on the first instance
+ //
+ break;
+ }
+ TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+ }
+
+ SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;
+
+//*** AMI PORTING BEGIN ***//
+//Modified to pass SCT test
+//Commented code moved to be executed before checking if passed Handle is NULL
+/*
+ //
+ // Get a list of all handles that support the requested protocol
+ //
+ Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
+ if (EFI_ERROR (Status) || HandleCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+*/
+//*** AMI PORTING END *****//
+
+ BestMatch = -1;
+ for(Index = 0; Index < HandleCount; Index += 1) {
+ Handle = Handles[Index];
+ Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, &TmpDevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // If this handle doesn't support device path, then skip it
+ //
+ continue;
+ }
+
+ //
+ // Check if DevicePath is first part of SourcePath
+ //
+ Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
+ if ((Size <= SourceSize) && EfiCompareMem (SourcePath, TmpDevicePath, Size) == 0) {
+ //
+ // If the size is equal to the best match, then we
+ // have a duplice device path for 2 different device
+ // handles
+ //
+ ASSERT (Size != BestMatch);
+
+ //
+ // We've got a match, see if it's the best match so far
+ //
+ if (Size > BestMatch) {
+ BestMatch = Size;
+ *Device = Handle;
+ }
+ }
+ }
+
+ CoreFreePool (Handles);
+
+ //
+ // If there wasn't any match, then no parts of the device path was found.
+ // Which is strange since there is likely a "root level" device path in the system.
+ //
+ if (BestMatch == -1) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Return the remaining part of the device path
+ //
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
+ return EFI_SUCCESS;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Return the first Protocol Interface that matches the Protocol GUID. If
+ Registration is pasased in return a Protocol Instance that was just add
+ to the system. If Retistration is NULL return the first Protocol Interface
+ you find.
+
+Arguments:
+
+ Protocol - The protocol to search for
+
+ Registration - Optional Registration Key returned from RegisterProtocolNotify()
+
+ Interface - Return the Protocol interface (instance).
+
+Returns:
+
+ EFI_SUCCESS - If a valid Interface is returned
+
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+ EFI_NOT_FOUND - Protocol interface not found
+
+--*/
+{
+ EFI_STATUS Status;
+ LOCATE_POSITION Position;
+ PROTOCOL_NOTIFY *ProtNotify;
+ IHANDLE *Handle;
+
+ if (Interface == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Protocol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Interface = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Set initial position
+ //
+ Position.Protocol = Protocol;
+ Position.SearchKey = Registration;
+ Position.Position = &gHandleList;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ mEfiLocateHandleRequest += 1;
+
+ if (NULL == Registration) {
+ //
+ // Look up the protocol entry and set the head pointer
+ //
+ Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (Position.ProtEntry == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ Position.Position = &Position.ProtEntry->Protocols;
+
+ Handle = CoreGetNextLocateByProtocol (&Position, Interface);
+ } else {
+ Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
+ }
+
+ if (NULL == Handle) {
+ Status = EFI_NOT_FOUND;
+ } else if (NULL != Registration) {
+ //
+ // If this is a search by register notify and a handle was
+ // returned, update the register notification position
+ //
+ ProtNotify = Registration;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+
+EFI_BOOTSERVICE11
+EFI_STATUS
+EFIAPI
+CoreLocateHandleBuffer (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *NumberHandles,
+ OUT EFI_HANDLE **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Function returns an array of handles that support the requested protocol
+ in a buffer allocated from pool. This is a version of CoreLocateHandle()
+ that allocates a buffer for the caller.
+
+Arguments:
+
+ SearchType - Specifies which handle(s) are to be returned.
+ Protocol - Provides the protocol to search by.
+ This parameter is only valid for SearchType ByProtocol.
+ SearchKey - Supplies the search key depending on the SearchType.
+ NumberHandles - The number of handles returned in Buffer.
+ Buffer - A pointer to the buffer to return the requested array of
+ handles that support Protocol.
+
+Returns:
+
+ EFI_SUCCESS - The result array of handles was returned.
+ EFI_NOT_FOUND - No handles match the search.
+ EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
+ EFI_INVALID_PARAMETER - Invalid parameter
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+
+ if (NumberHandles == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BufferSize = 0;
+ *NumberHandles = 0;
+ *Buffer = NULL;
+ Status = CoreLocateHandle (
+ SearchType,
+ Protocol,
+ SearchKey,
+ &BufferSize,
+ *Buffer
+ );
+ //
+ // LocateHandleBuffer() returns incorrect status code if SearchType is
+ // invalid.
+ //
+ // Add code to correctly handle expected errors from CoreLocateHandle().
+ //
+ if (EFI_ERROR(Status)) {
+ switch (Status) {
+ case EFI_BUFFER_TOO_SMALL:
+ break;
+ case EFI_INVALID_PARAMETER:
+ return Status;
+ default:
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ *Buffer = CoreAllocateBootServicesPool (BufferSize);
+ if (*Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CoreLocateHandle (
+ SearchType,
+ Protocol,
+ SearchKey,
+ &BufferSize,
+ *Buffer
+ );
+
+ *NumberHandles = BufferSize/sizeof(EFI_HANDLE);
+ if (EFI_ERROR(Status)) {
+ *NumberHandles = 0;
+ }
+
+ return Status;
+}
+
+
diff --git a/Core/CORE_DXE/memdata.c b/Core/CORE_DXE/memdata.c
new file mode 100644
index 0000000..580b0bd
--- /dev/null
+++ b/Core/CORE_DXE/memdata.c
@@ -0,0 +1,41 @@
+/*++
+
+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:
+
+ memdata.c
+
+Abstract:
+
+ Global data used in memory service
+
+
+Revision History
+
+--*/
+
+#include "imem.h"
+
+
+//
+// MemoryLock - synchronizes access to the memory map and pool lists
+//
+EFI_LOCK gMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
+
+//
+// MemoryMap - the current memory map
+//
+EFI_LIST_ENTRY gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap);
+
+//
+// MemoryLastConvert - the last memory descriptor used for a conversion request
+//
+MEMORY_MAP *gMemoryLastConvert;
diff --git a/Core/CORE_DXE/pool.c b/Core/CORE_DXE/pool.c
new file mode 100644
index 0000000..359c46c
--- /dev/null
+++ b/Core/CORE_DXE/pool.c
@@ -0,0 +1,620 @@
+/*++
+
+Copyright (c) 2004 - 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:
+
+ pool.c
+
+Abstract:
+
+ EFI Memory pool management
+
+Revision History
+
+--*/
+
+#include "imem.h"
+
+#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Index;
+ EFI_LIST_ENTRY Link;
+} POOL_FREE;
+
+
+#define POOL_HEAD_SIGNATURE EFI_SIGNATURE_32('p','h','d','0')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Size;
+ EFI_MEMORY_TYPE Type;
+ UINTN Reserved;
+ CHAR8 Data[1];
+} POOL_HEAD;
+
+#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data)
+
+#define POOL_TAIL_SIGNATURE EFI_SIGNATURE_32('p','t','a','l')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Size;
+} POOL_TAIL;
+
+
+#define POOL_SHIFT 7
+
+#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL))
+
+#define HEAD_TO_TAIL(a) \
+ ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));
+
+
+#define SIZE_TO_LIST(a) ((a) >> POOL_SHIFT)
+#define LIST_TO_SIZE(a) ((a+1) << POOL_SHIFT)
+
+#define MAX_POOL_LIST SIZE_TO_LIST(DEFAULT_PAGE_ALLOCATION)
+#define MAX_POOL_SIZE (EFI_MAX_ADDRESS - POOL_OVERHEAD)
+
+//
+// Globals
+//
+
+#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t')
+typedef struct {
+ INTN Signature;
+ UINTN Used;
+ EFI_MEMORY_TYPE MemoryType;
+ EFI_LIST_ENTRY FreeList[MAX_POOL_LIST];
+ EFI_LIST_ENTRY Link;
+} POOL;
+
+
+POOL PoolHead[EfiMaxMemoryType];
+EFI_LIST_ENTRY PoolHeadList;
+
+//
+//
+//
+
+VOID
+CoreInitializePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called to initialize the pool.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Type;
+ UINTN Index;
+
+ for (Type=0; Type < EfiMaxMemoryType; Type++) {
+ PoolHead[Type].Signature = 0;
+ PoolHead[Type].Used = 0;
+ PoolHead[Type].MemoryType = Type;
+ for (Index=0; Index < MAX_POOL_LIST; Index++) {
+ InitializeListHead (&PoolHead[Type].FreeList[Index]);
+ }
+ }
+ InitializeListHead (&PoolHeadList);
+}
+
+
+POOL *
+LookupPoolHead (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+/*++
+
+Routine Description:
+
+ Look up pool head for specified memory type.
+
+Arguments:
+
+ MemoryType - Memory type of which pool head is looked for
+
+Returns:
+
+ Pointer of Corresponding pool head.
+
+--*/
+{
+ EFI_LIST_ENTRY *Link;
+ POOL *Pool;
+ UINTN Index;
+
+ if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) {
+ return &PoolHead[MemoryType];
+ }
+
+ if (MemoryType < 0) {
+
+ for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) {
+ Pool = CR(Link, POOL, Link, POOL_SIGNATURE);
+ if (Pool->MemoryType == MemoryType) {
+ return Pool;
+ }
+ }
+
+ Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));
+ if (Pool == NULL) {
+ return NULL;
+ }
+
+ Pool->Signature = POOL_SIGNATURE;
+ Pool->Used = 0;
+ Pool->MemoryType = MemoryType;
+ for (Index=0; Index < MAX_POOL_LIST; Index++) {
+ InitializeListHead (&Pool->FreeList[Index]);
+ }
+
+ InsertHeadList (&PoolHeadList, &Pool->Link);
+
+ return Pool;
+ }
+
+ return NULL;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Allocate pool of a particular type.
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+ Buffer - The address to return a pointer to the allocated pool
+
+Returns:
+
+ EFI_INVALID_PARAMETER - PoolType not valid
+
+ EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed.
+
+ EFI_SUCCESS - Pool successfully allocated.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // If it's not a valid type, fail it
+ //
+ if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) ||
+ PoolType == EfiConventionalMemory) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+//*** AMI PORTING BEGIN ***//
+// UEFI spec update - return EFI_INVALID_PARAMETER if Buffer is NULL
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+//*** AMI PORTING END *****//
+
+ *Buffer = NULL;
+ //
+ // As we need to reserve memory for other resources, we can't expect to allocate
+ // all memory( EFI_MAX_ADDRESS - POOL_OVERHEAD + 1) using this function,
+ // the following check operation is only used to make sure the allocated pool size will
+ // not rool over from a very large number to a very small number.
+ //
+ if (Size > MAX_POOL_SIZE) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Acquire the memory lock and make the allocation
+ //
+ Status = CoreAcquireLockOrFail (&gMemoryLock);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Buffer = CoreAllocatePoolI (PoolType, Size);
+ CoreReleaseMemoryLock ();
+ return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
+}
+
+
+VOID *
+CoreAllocatePoolI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Internal function to allocate pool of a particular type.
+
+ N.B. Caller must have the memory lock held
+
+
+Arguments:
+
+ PoolType - Type of pool to allocate
+
+ Size - The amount of pool to allocate
+
+Returns:
+
+ The allocate pool, or NULL
+
+--*/
+{
+ POOL *Pool;
+ POOL_FREE *Free;
+ POOL_HEAD *Head;
+ POOL_TAIL *Tail;
+ CHAR8 *NewPage;
+ VOID *Buffer;
+ UINTN Index;
+ UINTN FSize;
+ UINTN offset;
+ UINTN Adjustment;
+ UINTN NoPages;
+
+ ASSERT_LOCKED (&gMemoryLock);
+
+ //
+ // Adjust the size by the pool header & tail overhead
+ //
+
+ //
+ // Adjusting the Size to be of proper alignment so that
+ // we don't get an unaligned access fault later when
+ // pool_Tail is being initialized
+ //
+ ALIGN_VARIABLE (Size, Adjustment);
+
+ Size += POOL_OVERHEAD;
+ Index = SIZE_TO_LIST(Size);
+ Pool = LookupPoolHead (PoolType);
+ if (Pool== NULL) {
+ return NULL;
+ }
+ Head = NULL;
+
+ //
+ // If allocation is over max size, just allocate pages for the request
+ // (slow)
+ //
+ if (Index >= MAX_POOL_LIST) {
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
+ NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
+ Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);
+ goto Done;
+ }
+
+ //
+ // If there's no free pool in the proper list size, go get some more pages
+ //
+ if (IsListEmpty (&Pool->FreeList[Index])) {
+
+ //
+ // Get another page
+ //
+ NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
+ if (NewPage == NULL) {
+ goto Done;
+ }
+
+ //
+ // Carve up new page into free pool blocks
+ //
+ offset = 0;
+ while (offset < DEFAULT_PAGE_ALLOCATION) {
+ ASSERT (Index < MAX_POOL_LIST);
+ FSize = LIST_TO_SIZE(Index);
+
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ Free->Signature = POOL_FREE_SIGNATURE;
+ Free->Index = (UINT32)Index;
+ InsertHeadList (&Pool->FreeList[Index], &Free->Link);
+ offset += FSize;
+ }
+
+ Index -= 1;
+ }
+
+ ASSERT (offset == DEFAULT_PAGE_ALLOCATION);
+ Index = SIZE_TO_LIST(Size);
+ }
+
+ //
+ // Remove entry from free pool list
+ //
+ Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);
+ RemoveEntryList (&Free->Link);
+
+ Head = (POOL_HEAD *) Free;
+
+Done:
+ Buffer = NULL;
+
+ if (Head != NULL) {
+
+ //
+ // If we have a pool buffer, fill in the header & tail info
+ //
+ Head->Signature = POOL_HEAD_SIGNATURE;
+ Head->Size = (UINT32) Size;
+ Head->Type = (EFI_MEMORY_TYPE) PoolType;
+ Tail = HEAD_TO_TAIL (Head);
+ Tail->Signature = POOL_TAIL_SIGNATURE;
+ Tail->Size = (UINT32) Size;
+ Buffer = Head->Data;
+ DEBUG_SET_MEMORY (Buffer, Size - POOL_OVERHEAD);
+
+ DEBUG (
+ (EFI_D_POOL,
+ "AllocatePool: Type %x, Addr %x (len %x) %,d\n",
+ (UINTN)PoolType,
+ Buffer,
+ Size - POOL_OVERHEAD,
+ Pool->Used)
+ );
+
+ //
+ // Account the allocation
+ //
+ Pool->Used += Size;
+
+ } else {
+ DEBUG ((EFI_D_ERROR | EFI_D_POOL, "AllocatePool: failed to allocate %d bytes\n", Size));
+ }
+
+ return Buffer;
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreFreePool (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Frees pool.
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer is not a valid value.
+
+ EFI_SUCCESS - Pool successfully freed.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (NULL == Buffer) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireMemoryLock ();
+ Status = CoreFreePoolI (Buffer);
+ CoreReleaseMemoryLock ();
+ return Status;
+}
+
+
+EFI_STATUS
+CoreFreePoolI (
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Internal function to free a pool entry.
+
+ N.B. Caller must have the memory lock held
+
+
+Arguments:
+
+ Buffer - The allocated pool entry to free
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Buffer not valid
+
+ EFI_SUCCESS - Buffer successfully freed.
+
+--*/
+{
+ POOL *Pool;
+ POOL_HEAD *Head;
+ POOL_TAIL *Tail;
+ POOL_FREE *Free;
+ UINTN Index;
+ UINTN NoPages;
+ UINTN Size;
+ CHAR8 *NewPage;
+ UINTN FSize;
+ UINTN offset;
+ BOOLEAN AllFree;
+
+ ASSERT(NULL != Buffer);
+ //
+ // Get the head & tail of the pool entry
+ //
+ Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);
+ ASSERT(NULL != Head);
+
+ if (Head->Signature != POOL_HEAD_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tail = HEAD_TO_TAIL (Head);
+ ASSERT(NULL != Tail);
+
+ //
+ // Debug
+ //
+ ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
+ ASSERT (Head->Size == Tail->Size);
+ ASSERT_LOCKED (&gMemoryLock);
+
+ if (Tail->Signature != POOL_TAIL_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Head->Size != Tail->Size) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Determine the pool type and account for it
+ //
+ Size = Head->Size;
+ Pool = LookupPoolHead (Head->Type);
+ if (Pool == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Pool->Used -= Size;
+ DEBUG ((EFI_D_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, (UINTN)Head->Size - POOL_OVERHEAD, Pool->Used));
+
+ //
+ // Determine the pool list
+ //
+ Index = SIZE_TO_LIST(Size);
+ DEBUG_SET_MEMORY (Head, Size);
+
+ //
+ // If it's not on the list, it must be pool pages
+ //
+ if (Index >= MAX_POOL_LIST) {
+
+ //
+ // Return the memory pages back to free memory
+ //
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
+ NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
+ CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);
+
+ } else {
+
+ //
+ // Put the pool entry onto the free pool list
+ //
+ Free = (POOL_FREE *) Head;
+ ASSERT(NULL != Free);
+ Free->Signature = POOL_FREE_SIGNATURE;
+ Free->Index = (UINT32)Index;
+ InsertHeadList (&Pool->FreeList[Index], &Free->Link);
+
+ //
+ // See if all the pool entries in the same page as Free are freed pool
+ // entries
+ //
+ NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));
+ Free = (POOL_FREE *) &NewPage[0];
+ ASSERT(NULL != Free);
+
+ if (Free->Signature == POOL_FREE_SIGNATURE) {
+
+ Index = Free->Index;
+
+ AllFree = TRUE;
+ offset = 0;
+
+ while ((offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {
+ FSize = LIST_TO_SIZE(Index);
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ ASSERT(NULL != Free);
+ if (Free->Signature != POOL_FREE_SIGNATURE) {
+ AllFree = FALSE;
+ }
+ offset += FSize;
+ }
+ Index -= 1;
+ }
+
+ if (AllFree) {
+
+ //
+ // All of the pool entries in the same page as Free are free pool
+ // entries
+ // Remove all of these pool entries from the free loop lists.
+ //
+ Free = (POOL_FREE *) &NewPage[0];
+ ASSERT(NULL != Free);
+ Index = Free->Index;
+ offset = 0;
+
+ while (offset < DEFAULT_PAGE_ALLOCATION) {
+ FSize = LIST_TO_SIZE(Index);
+ while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
+ Free = (POOL_FREE *) &NewPage[offset];
+ ASSERT(NULL != Free);
+ RemoveEntryList (&Free->Link);
+ offset += FSize;
+ }
+ Index -= 1;
+ }
+
+ //
+ // Free the page
+ //
+ CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION));
+ }
+ }
+ }
+
+ //
+ // If this is an OS specific memory type, then check to see if the last
+ // portion of that memory type has been freed. If it has, then free the
+ // list entry for that memory type
+ //
+ if (Pool->MemoryType < 0 && Pool->Used == 0) {
+ RemoveEntryList (&Pool->Link);
+ CoreFreePoolI (Pool);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/timer.c b/Core/CORE_DXE/timer.c
new file mode 100644
index 0000000..28ce124
--- /dev/null
+++ b/Core/CORE_DXE/timer.c
@@ -0,0 +1,386 @@
+/*++
+
+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:
+
+ timer.c
+
+Abstract:
+
+ EFI Event support
+
+Revision History
+
+--*/
+
+
+#include "exec.h"
+
+//
+// Internal prototypes
+//
+STATIC
+UINT64
+CoreCurrentSystemTime (
+ VOID
+ );
+
+VOID
+EFIAPI
+CoreCheckTimers (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+STATIC
+VOID
+CoreInsertEventTimer (
+ IN IEVENT *Event
+ );
+
+//
+// Internal data
+//
+
+static EFI_LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
+static EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL - 1);
+static EFI_EVENT mEfiCheckTimerEvent;
+
+static EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL);
+static UINT64 mEfiSystemTime = 0;
+
+//
+// Timer functions
+//
+
+VOID
+CoreInitializeTimer (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes timer support
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = CoreCreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_HIGH_LEVEL - 1,
+ CoreCheckTimers,
+ NULL,
+ &mEfiCheckTimerEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+STATIC
+UINT64
+CoreCurrentSystemTime (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Returns the current system time
+
+Arguments:
+
+ None
+
+Returns:
+
+ Returns the current system time
+
+--*/
+{
+ UINT64 SystemTime;
+
+ CoreAcquireLock (&mEfiSystemTimeLock);
+ SystemTime = mEfiSystemTime;
+ CoreReleaseLock (&mEfiSystemTimeLock);
+ return SystemTime;
+}
+
+VOID
+EFIAPI
+CoreTimerTick (
+ IN UINT64 Duration
+ )
+/*++
+
+Routine Description:
+
+ Called by the platform code to process a tick.
+
+Arguments:
+
+ Duration - The number of 100ns elasped since the last call to TimerTick
+
+Returns:
+
+ None
+
+--*/
+{
+ IEVENT *Event;
+
+ //
+ // Check runtiem flag in case there are ticks while exiting boot services
+ //
+
+ CoreAcquireLock (&mEfiSystemTimeLock);
+
+ //
+ // Update the system time
+ //
+
+ mEfiSystemTime += Duration;
+
+ //
+ // If the head of the list is expired, fire the timer event
+ // to process it
+ //
+
+ if (!IsListEmpty (&mEfiTimerList)) {
+ Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+ }
+
+ CoreReleaseLock (&mEfiSystemTimeLock);
+}
+
+VOID
+EFIAPI
+CoreCheckTimers (
+ IN EFI_EVENT CheckEvent,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Checks the sorted timer list against the current system time.
+ Signals any expired event timer.
+
+Arguments:
+
+ CheckEvent - Not used
+
+ Context - Not used
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 SystemTime;
+ IEVENT *Event;
+
+ //
+ // Check the timer database for expired timers
+ //
+
+ CoreAcquireLock (&mEfiTimerLock);
+ SystemTime = CoreCurrentSystemTime ();
+
+ while (!IsListEmpty (&mEfiTimerList)) {
+ Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ //
+ // If this timer is not expired, then we're done
+ //
+
+ if (Event->u.Timer.TriggerTime > SystemTime) {
+ break;
+ }
+
+ //
+ // Remove this timer from the timer queue
+ //
+
+ RemoveEntryList (&Event->u.Timer.Link);
+ Event->u.Timer.Link.ForwardLink = NULL;
+
+ //
+ // Signal it
+ //
+ CoreSignalEvent (Event);
+
+ //
+ // If this is a periodic timer, set it
+ //
+ if (Event->u.Timer.Period) {
+
+ //
+ // Compute the timers new trigger time
+ //
+
+ Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;
+
+ //
+ // If that's before now, then reset the timer to start from now
+ //
+ if (Event->u.Timer.TriggerTime <= SystemTime) {
+ Event->u.Timer.TriggerTime = SystemTime;
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+
+ //
+ // Add the timer
+ //
+
+ CoreInsertEventTimer (Event);
+ }
+ }
+
+ CoreReleaseLock (&mEfiTimerLock);
+}
+
+STATIC
+VOID
+CoreInsertEventTimer (
+ IN IEVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ Inserts the timer event
+
+Arguments:
+
+ Event - Points to the internal structure of timer event to be installed
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 TriggerTime;
+ EFI_LIST_ENTRY *Link;
+ IEVENT *Event2;
+
+ ASSERT_LOCKED (&mEfiTimerLock);
+
+ //
+ // Get the timer's trigger time
+ //
+
+ TriggerTime = Event->u.Timer.TriggerTime;
+
+ //
+ // Insert the timer into the timer database in assending sorted order
+ //
+
+ for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {
+ Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
+
+ if (Event2->u.Timer.TriggerTime > TriggerTime) {
+ break;
+ }
+ }
+
+ InsertTailList (Link, &Event->u.Timer.Link);
+}
+
+
+EFI_BOOTSERVICE
+EFI_STATUS
+EFIAPI
+CoreSetTimer (
+ IN EFI_EVENT UserEvent,
+ IN EFI_TIMER_DELAY Type,
+ IN UINT64 TriggerTime
+ )
+/*++
+
+Routine Description:
+
+ Sets the type of timer and the trigger time for a timer event.
+
+Arguments:
+
+ UserEvent - The timer event that is to be signaled at the specified time
+ Type - The type of time that is specified in TriggerTime
+ TriggerTime - The number of 100ns units until the timer expires
+
+Returns:
+
+ EFI_SUCCESS - The event has been set to be signaled at the requested time
+ EFI_INVALID_PARAMETER - Event or Type is not valid
+
+--*/
+{
+ IEVENT *Event;
+
+ Event = UserEvent;
+
+ if (Event == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Event->Signature != EVENT_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Type < 0 || Type >= TimerTypeMax || !(Event->Type & EFI_EVENT_TIMER)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquireLock (&mEfiTimerLock);
+
+ //
+ // If the timer is queued to the timer database, remove it
+ //
+
+ if (Event->u.Timer.Link.ForwardLink != NULL) {
+ RemoveEntryList (&Event->u.Timer.Link);
+ Event->u.Timer.Link.ForwardLink = NULL;
+ }
+
+ Event->u.Timer.TriggerTime = 0;
+ Event->u.Timer.Period = 0;
+
+ if (Type != TimerCancel) {
+
+ if (Type == TimerPeriodic) {
+ Event->u.Timer.Period = TriggerTime;
+ }
+
+ Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
+ CoreInsertEventTimer (Event);
+
+ if (TriggerTime == 0) {
+ CoreSignalEvent (mEfiCheckTimerEvent);
+ }
+ }
+
+ CoreReleaseLock (&mEfiTimerLock);
+ return EFI_SUCCESS;
+}
diff --git a/Core/CORE_DXE/tpl.c b/Core/CORE_DXE/tpl.c
new file mode 100644
index 0000000..3ac99fc
--- /dev/null
+++ b/Core/CORE_DXE/tpl.c
@@ -0,0 +1,198 @@
+/*++
+
+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:
+
+ tpl.c
+
+Abstract:
+
+ Task priority function
+
+--*/
+
+#include "exec.h"
+
+STATIC
+VOID
+CoreSetInterruptState (
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ Set Interrupt State
+
+Arguments:
+
+ Enable - The state of enable or disable interrupt
+
+Returns:
+
+ None
+
+--*/
+
+{
+ if (gCpu != NULL) {
+ if (Enable) {
+ gCpu->EnableInterrupt(gCpu);
+ } else {
+ gCpu->DisableInterrupt(gCpu);
+ }
+ }
+}
+
+//
+// Return the highest set bit
+//
+UINTN
+CoreHighestSetBit (
+ IN UINTN Number
+ )
+/*++
+
+Routine Description:
+
+ Return the highest set bit
+
+Arguments:
+
+ Number - The value to check
+
+Returns:
+
+ Bit position of the highest set bit
+
+--*/
+{
+ UINTN msb;
+
+ msb = 31;
+ while ((msb > 0) && ((Number & ((UINTN)1 << msb)) == 0)) {
+ msb--;
+ }
+
+ return msb;
+}
+
+
+EFI_BOOTSERVICE
+EFI_TPL
+EFIAPI
+CoreRaiseTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Raise the task priority level to the new level.
+ High level is implemented by disabling processor interrupts.
+
+Arguments:
+
+ NewTpl - New task priority level
+
+Returns:
+
+ The previous task priority level
+
+--*/
+{
+ EFI_TPL OldTpl;
+
+ OldTpl = gEfiCurrentTpl;
+ ASSERT (OldTpl <= NewTpl);
+ ASSERT (VALID_TPL (NewTpl));
+
+ //
+ // If raising to high level, disable interrupts
+ //
+ if (NewTpl >= EFI_TPL_HIGH_LEVEL && OldTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (FALSE);
+ }
+
+ //
+ // Set the new value
+ //
+ gEfiCurrentTpl = NewTpl;
+
+ return OldTpl;
+}
+
+
+EFI_BOOTSERVICE
+VOID
+EFIAPI
+CoreRestoreTpl (
+ IN EFI_TPL NewTpl
+ )
+/*++
+
+Routine Description:
+
+ Lowers the task priority to the previous value. If the new
+ priority unmasks events at a higher priority, they are dispatched.
+
+Arguments:
+
+ NewTpl - New, lower, task priority
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_TPL OldTpl;
+
+ OldTpl = gEfiCurrentTpl;
+ ASSERT (NewTpl <= OldTpl);
+ ASSERT (VALID_TPL (NewTpl));
+
+ //
+ // If lowering below HIGH_LEVEL, make sure
+ // interrupts are enabled
+ //
+
+ if (OldTpl >= EFI_TPL_HIGH_LEVEL && NewTpl < EFI_TPL_HIGH_LEVEL) {
+ gEfiCurrentTpl = EFI_TPL_HIGH_LEVEL;
+ }
+
+ //
+ // Dispatch any pending events
+ //
+
+ while ((-2 << NewTpl) & gEventPending) {
+ gEfiCurrentTpl = CoreHighestSetBit (gEventPending);
+ if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (TRUE);
+ }
+ CoreDispatchEventNotifies (gEfiCurrentTpl);
+ }
+
+ //
+ // Set the new value
+ //
+
+ gEfiCurrentTpl = NewTpl;
+
+ //
+ // If lowering below HIGH_LEVEL, make sure
+ // interrupts are enabled
+ //
+ if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) {
+ CoreSetInterruptState (TRUE);
+ }
+
+}