\r
**/\r
\r
-//\r
-// The package level header files this module uses\r
-//\r
-#include <PiDxe.h>\r
-//\r
-// The Library classes this module consumes\r
-//\r
-#include <Library/HiiLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
+#include "InternalHiiLib.h"\r
+\r
+CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt;\r
+CONST EFI_HII_STRING_PROTOCOL *mHiiStringProt;\r
+BOOLEAN mHiiProtocolsInitialized = FALSE;\r
+\r
+\r
+/**\r
+\r
+ This function locate Hii relative protocols for later usage.\r
+\r
+**/\r
+VOID\r
+LocateHiiProtocols (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (mHiiProtocolsInitialized) {\r
+ //\r
+ // Only need to initialize the protocol instance once.\r
+ //\r
+ return;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mHiiProtocolsInitialized = TRUE;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This funciton build the package list based on the package number,\r
+ the GUID of the package list and the list of pointer which point to\r
+ package header that defined by UEFI VFR compiler and StringGather\r
+ tool.\r
+\r
+ #pragma pack (push, 1)\r
+ typedef struct {\r
+ UINT32 BinaryLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ } TIANO_AUTOGEN_PACKAGES_HEADER;\r
+ #pragma pack (pop)\r
+\r
+ If there is not enough resource for the new package list,\r
+ the function will ASSERT.\r
+\r
+ @param NumberOfPackages The number of packages be \r
+ @param GuidId The GUID for the package list to be generated.\r
+ @param Marker The variable argument list. Each entry represent a specific package header that is\r
+ generated by VFR compiler and StrGather tool. The first 4 bytes is a UINT32 value\r
+ that indicate the overall length of the package.\r
+\r
+ @return The pointer to the package list header.\r
+\r
+**/\r
+EFI_HII_PACKAGE_LIST_HEADER *\r
+InternalHiiLibPreparePackages (\r
+ IN UINTN NumberOfPackages,\r
+ IN CONST EFI_GUID *GuidId,\r
+ IN VA_LIST Marker\r
+ )\r
+{\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
+ UINT8 *PackageListData;\r
+ UINT32 PackageListLength;\r
+ UINT32 PackageLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT8 *PackageArray;\r
+ UINTN Index;\r
+ VA_LIST MarkerBackup;\r
+\r
+ PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+ MarkerBackup = Marker;\r
+ \r
+ for (Index = 0; Index < NumberOfPackages; Index++) {\r
+ CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));\r
+ //\r
+ // Do not count the BinaryLength field.\r
+ //\r
+ PackageListLength += (PackageLength - sizeof (UINT32));\r
+ }\r
+\r
+ //\r
+ // Include the lenght of EFI_HII_PACKAGE_END\r
+ //\r
+ PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageListHeader = AllocateZeroPool (PackageListLength);\r
+ ASSERT (PackageListHeader != NULL);\r
+ \r
+ CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));\r
+ PackageListHeader->PackageLength = PackageListLength;\r
+\r
+ PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+ Marker = MarkerBackup;\r
+ for (Index = 0; Index < NumberOfPackages; Index++) {\r
+ PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
+ CopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
+ PackageLength -= sizeof (UINT32);\r
+ PackageArray += sizeof (UINT32);\r
+ CopyMem (PackageListData, PackageArray, PackageLength);\r
+ PackageListData += PackageLength;\r
+ }\r
+\r
+ //\r
+ // Append EFI_HII_PACKAGE_END\r
+ //\r
+ PackageHeader.Type = EFI_HII_PACKAGE_END;\r
+ PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
+\r
+ return PackageListHeader;\r
+}\r
\r
/**\r
- This function allocates pool for an EFI_HII_PACKAGES structure\r
- with enough space for the variable argument list of package pointers.\r
- The allocated structure is initialized using NumberOfPackages, Guid,\r
- and the variable length argument list of package pointers.\r
+ Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
+\r
+ If GuidId is NULL, then ASSERT.\r
+ If not enough resource to complete the operation, then ASSERT.\r
\r
- @param NumberOfPackages The number of HII packages to prepare.\r
- @param Guid Package GUID.\r
+ @param NumberOfPackages Number of packages.\r
+ @param GuidId Package GUID.\r
+ @param ... Variable argument list for packages to be assembled.\r
\r
- @return The allocated and initialized packages.\r
+ @return EFI_HII_PACKAGE_LIST_HEADER Pointer of EFI_HII_PACKAGE_LIST_HEADER. The function will ASSERT if system has\r
+ not enough resource to complete the operation.\r
\r
**/\r
EFI_HII_PACKAGE_LIST_HEADER *\r
EFIAPI\r
-PreparePackages (\r
- IN CONST UINTN NumberOfPackages,\r
- IN CONST EFI_GUID *Guid OPTIONAL,\r
+HiiLibPreparePackageList (\r
+ IN UINTN NumberOfPackages,\r
+ IN CONST EFI_GUID *GuidId,\r
...\r
)\r
{\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
+ VA_LIST Marker;\r
+\r
+ ASSERT (GuidId != NULL);\r
+\r
+ VA_START (Marker, GuidId);\r
+ PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
+ VA_END (Marker);\r
+\r
+ return PackageListHeader;\r
+}\r
+\r
+\r
+/**\r
+ This function allocates pool for an EFI_HII_PACKAGE_LIST structure\r
+ with additional space that is big enough to host all packages described by the variable \r
+ argument list of package pointers. The allocated structure is initialized using NumberOfPackages, \r
+ GuidId, and the variable length argument list of package pointers.\r
+\r
+ Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The\r
+ Handle to the newly registered Package List is returned throught HiiHandle.\r
+\r
+ If HiiHandle is NULL, then ASSERT.\r
+\r
+ @param NumberOfPackages The number of HII packages to register.\r
+ @param GuidId Package List GUID ID.\r
+ @param DriverHandle Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed.\r
+ This DriverHandle uniquely defines the device that the added packages are associated with.\r
+ @param HiiHandle On output, the HiiHandle is update with the handle which can be used to retrieve the Package \r
+ List later. If the functions failed to add the package to the default HII database, this value will\r
+ be set to NULL.\r
+ @param ... The variable argument list describing all HII Package.\r
+\r
+ @return EFI_SUCCESS If the packages are successfully added to the default HII database.\r
+ @return EFI_OUT_OF_RESOURCE Not enough resource to complete the operation.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiLibAddPackages (\r
+ IN UINTN NumberOfPackages,\r
+ IN CONST EFI_GUID *GuidId,\r
+ IN EFI_HANDLE DriverHandle, OPTIONAL\r
+ OUT EFI_HII_HANDLE *HiiHandle,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Args;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+\r
+ LocateHiiProtocols ();\r
+\r
+ VA_START (Args, HiiHandle);\r
+ PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
+\r
+ Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
+ if (HiiHandle != NULL) {\r
+ if (EFI_ERROR (Status)) {\r
+ *HiiHandle = NULL;\r
+ }\r
+ }\r
+\r
+ FreePool (PackageListHeader);\r
+ VA_END (Args);\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Removes a package list from the default HII database.\r
+\r
+ If HiiHandle is NULL, then ASSERT.\r
+ If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT.\r
+\r
+ @param HiiHandle The handle that was previously registered to the data base that is requested for removal.\r
+ List later.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiLibRemovePackages (\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ASSERT (IsHiiHandleRegistered (HiiHandle));\r
+\r
+ LocateHiiProtocols ();\r
+\r
+ Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+/**\r
+ Determines the handles that are currently active in the database.\r
+ It's the caller's responsibility to free handle buffer.\r
+\r
+ If HandleBufferLength is NULL, then ASSERT.\r
+ If HiiHandleBuffer is NULL, then ASSERT.\r
+\r
+ @param HandleBufferLength On input, a pointer to the length of the handle\r
+ buffer. On output, the length of the handle buffer\r
+ that is required for the handles found.\r
+ @param HiiHandleBuffer Pointer to an array of Hii Handles returned.\r
+\r
+ @retval EFI_SUCCESS Get an array of Hii Handles successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiLibGetHiiHandles (\r
+ IN OUT UINTN *HandleBufferLength,\r
+ OUT EFI_HII_HANDLE **HiiHandleBuffer\r
+ )\r
+{\r
+ UINTN BufferLength;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (HandleBufferLength != NULL);\r
+ ASSERT (HiiHandleBuffer != NULL);\r
+\r
+ BufferLength = 0;\r
+\r
+ LocateHiiProtocols ();\r
+\r
+ //\r
+ // Try to find the actual buffer size for HiiHandle Buffer.\r
+ //\r
+ Status = mHiiDatabaseProt->ListPackageLists (\r
+ mHiiDatabaseProt,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferLength,\r
+ *HiiHandleBuffer\r
+ );\r
+\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ *HiiHandleBuffer = AllocateZeroPool (BufferLength);\r
+ Status = mHiiDatabaseProt->ListPackageLists (\r
+ mHiiDatabaseProt,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferLength,\r
+ *HiiHandleBuffer\r
+ );\r
+ //\r
+ // we should not fail here.\r
+ //\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ *HandleBufferLength = BufferLength;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Extract Hii package list GUID for given HII handle.\r
+\r
+ If HiiHandle could not be found in the default HII database, then ASSERT.\r
+ If Guid is NULL, then ASSERT.\r
+\r
+ @param Handle Hii handle\r
+ @param Guid Package list GUID\r
+\r
+ @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiLibExtractGuidFromHiiHandle (\r
+ IN EFI_HII_HANDLE Handle,\r
+ OUT EFI_GUID *Guid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+\r
+ ASSERT (Guid != NULL);\r
+ ASSERT (IsHiiHandleRegistered (Handle));\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+\r
+ LocateHiiProtocols ();\r
+\r
+ Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
+ ASSERT (Status != EFI_NOT_FOUND);\r
+ \r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Extract GUID\r
+ //\r
+ CopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Find HII Handle in the default HII database associated with given Device Path.\r
+\r
+ If DevicePath is NULL, then ASSERT.\r
+\r
+ @param DevicePath Device Path associated with the HII package list\r
+ handle.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+EFIAPI\r
+HiiLibDevicePathToHiiHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ UINTN BufferSize;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_HANDLE *Handles;\r
+ EFI_HANDLE Handle;\r
+ UINTN Size;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ ASSERT (DevicePath != NULL);\r
+\r
+ //\r
+ // Locate Device Path Protocol handle buffer\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search Driver Handle by Device Path\r
+ //\r
+ DriverHandle = NULL;\r
+ BufferSize = GetDevicePathSize (DevicePath);\r
+ for(Index = 0; Index < HandleCount; Index++) {\r
+ Handle = Handles[Index];\r
+ gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);\r
+\r
+ //\r
+ // Check whether DevicePath match\r
+ //\r
+ Size = GetDevicePathSize (TmpDevicePath);\r
+ if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {\r
+ DriverHandle = Handle;\r
+ break;\r
+ }\r
+ }\r
+ FreePool (Handles);\r
+\r
+ if (DriverHandle == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ LocateHiiProtocols ();\r
+\r
//\r
- // BugBug: Need more detail on UEFI spec.\r
+ // Retrieve all Hii Handles from HII database\r
//\r
- ASSERT (FALSE);\r
- return NULL;\r
+ BufferSize = 0x1000;\r
+ HiiHandles = AllocatePool (BufferSize);\r
+ ASSERT (HiiHandles != NULL);\r
+ Status = mHiiDatabaseProt->ListPackageLists (\r
+ mHiiDatabaseProt,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferSize,\r
+ HiiHandles\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (HiiHandles);\r
+ HiiHandles = AllocatePool (BufferSize);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ Status = mHiiDatabaseProt->ListPackageLists (\r
+ mHiiDatabaseProt,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferSize,\r
+ HiiHandles\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (HiiHandles);\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search Hii Handle by Driver Handle\r
+ //\r
+ HiiHandle = NULL;\r
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = mHiiDatabaseProt->GetPackageListHandle (\r
+ mHiiDatabaseProt,\r
+ HiiHandles[Index],\r
+ &Handle\r
+ );\r
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ This function check if the Hii Handle is a valid handle registered\r
+ in the HII database.\r
+\r
+ @param HiiHandle The HII Handle.\r
+\r
+ @retval TRUE If it is a valid HII handle.\r
+ @retval FALSE If it is a invalid HII handle.\r
+**/\r
+BOOLEAN\r
+IsHiiHandleRegistered (\r
+ EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+\r
+ HiiPackageList = NULL;\r
+ BufferSize = 0;\r
+\r
+ LocateHiiProtocols ();\r
+\r
+ Status = mHiiDatabaseProt->ExportPackageLists (\r
+ mHiiDatabaseProt,\r
+ HiiHandle,\r
+ &BufferSize,\r
+ HiiPackageList\r
+ );\r
+\r
+ return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
}\r
+\r