]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / UefiEfiIfrSupportLib / UefiIfrCommon.c
diff --git a/EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c b/EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c
new file mode 100644 (file)
index 0000000..7e9553f
--- /dev/null
@@ -0,0 +1,618 @@
+/*++\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+  UefiIfrCommon.c\r
+\r
+Abstract:\r
+\r
+  Common Library Routines to assist handle HII elements.\r
+\r
+--*/\r
+\r
+#include "UefiIfrLibrary.h"\r
+\r
+//\r
+// Hii vendor device path template\r
+//\r
+HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePathTemplate = {\r
+  {\r
+    {\r
+      {\r
+        HARDWARE_DEVICE_PATH,\r
+        HW_VENDOR_DP,\r
+        (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)),\r
+        (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8)\r
+      },\r
+      EFI_IFR_TIANO_GUID,\r
+    },\r
+    0\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    END_DEVICE_PATH_LENGTH,\r
+    0\r
+  }\r
+};\r
+\r
+//\r
+// Hii relative protocols\r
+//\r
+BOOLEAN  mHiiProtocolsInitialized = FALSE;\r
+\r
+EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL   *gIfrLibHiiString;\r
+\r
+VOID\r
+LocateHiiProtocols (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This function locate Hii relative protocols for later usage.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (mHiiProtocolsInitialized) {\r
+    return;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &gIfrLibHiiDatabase);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, &gIfrLibHiiString);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  mHiiProtocolsInitialized = TRUE;\r
+}\r
+\r
+EFI_HII_PACKAGE_LIST_HEADER *\r
+PreparePackageList (\r
+  IN UINTN                    NumberOfPackages,\r
+  IN EFI_GUID                 *GuidId,\r
+  ...\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
+\r
+Arguments:\r
+  NumberOfPackages  -  Number of packages.\r
+  GuidId            -  Package GUID.\r
+\r
+Returns:\r
+  Pointer of EFI_HII_PACKAGE_LIST_HEADER.\r
+\r
+--*/\r
+{\r
+  VA_LIST                     Marker;\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
+\r
+  PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+  VA_START (Marker, GuidId);\r
+  for (Index = 0; Index < NumberOfPackages; Index++) {\r
+    EfiCopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));\r
+    PackageListLength += (PackageLength - sizeof (UINT32));\r
+  }\r
+  VA_END (Marker);\r
+\r
+  //\r
+  // Include the lenght of EFI_HII_PACKAGE_END\r
+  //\r
+  PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
+  PackageListHeader = EfiLibAllocateZeroPool (PackageListLength);\r
+  ASSERT (PackageListHeader != NULL);\r
+  EfiCopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));\r
+  PackageListHeader->PackageLength = PackageListLength;\r
+\r
+  PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+  VA_START (Marker, GuidId);\r
+  for (Index = 0; Index < NumberOfPackages; Index++) {\r
+    PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
+    EfiCopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
+    PackageLength  -= sizeof (UINT32);\r
+    PackageArray += sizeof (UINT32);\r
+    EfiCopyMem (PackageListData, PackageArray, PackageLength);\r
+    PackageListData += PackageLength;\r
+  }\r
+  VA_END (Marker);\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
+  EfiCopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
+\r
+  return PackageListHeader;\r
+}\r
+\r
+EFI_STATUS\r
+CreateHiiDriverHandle (\r
+  OUT EFI_HANDLE               *DriverHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  The HII driver handle passed in for HiiDatabase.NewPackageList() requires\r
+  that there should be DevicePath Protocol installed on it.\r
+  This routine create a virtual Driver Handle by installing a vendor device\r
+  path on it, so as to use it to invoke HiiDatabase.NewPackageList().\r
+\r
+Arguments:\r
+  DriverHandle         - Handle to be returned\r
+\r
+Returns:\r
+  EFI_SUCCESS          - Handle destroy success.\r
+  EFI_OUT_OF_RESOURCES - Not enough memory.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  HII_VENDOR_DEVICE_PATH_NODE  *VendorDevicePath;\r
+  UINT64                       MonotonicCount;\r
+\r
+  VendorDevicePath = EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH), &mHiiVendorDevicePathTemplate);\r
+  if (VendorDevicePath == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  gBS->GetNextMonotonicCount (&MonotonicCount);\r
+  VendorDevicePath->MonotonicCount = (UINT32) MonotonicCount;\r
+\r
+  *DriverHandle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  VendorDevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyHiiDriverHandle (\r
+  IN EFI_HANDLE                 DriverHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Destroy the Driver Handle created by CreateHiiDriverHandle().\r
+\r
+Arguments:\r
+  DriverHandle - Handle returned by CreateHiiDriverHandle()\r
+\r
+Returns:\r
+  EFI_SUCCESS - Handle destroy success.\r
+  other       - Handle destroy fail.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &DevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  DevicePath\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_HII_HANDLE\r
+DevicePathToHiiHandle (\r
+  IN EFI_HII_DATABASE_PROTOCOL  *HiiDatabase,\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Find HII Handle associated with given Device Path.\r
+\r
+Arguments:\r
+  HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance.\r
+  DevicePath  - Device Path associated with the HII package list handle.\r
+\r
+Returns:\r
+  Handle - HII package list Handle associated with the Device Path.\r
+  NULL   - Hii Package list handle is not found.\r
+\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
+  //\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 = EfiDevicePathSize (DevicePath);\r
+  for(Index = 0; Index < HandleCount; Index++) {\r
+    Handle = Handles[Index];\r
+    gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, &TmpDevicePath);\r
+\r
+    //\r
+    // Check whether DevicePath match\r
+    //\r
+    Size = EfiDevicePathSize (TmpDevicePath);\r
+    if ((Size == BufferSize) && EfiCompareMem (DevicePath, TmpDevicePath, Size) == 0) {\r
+      DriverHandle = Handle;\r
+      break;\r
+    }\r
+  }\r
+  gBS->FreePool (Handles);\r
+\r
+  if (DriverHandle == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Retrieve all Hii Handles from HII database\r
+  //\r
+  BufferSize = 0x1000;\r
+  HiiHandles = EfiLibAllocatePool (BufferSize);\r
+  ASSERT (HiiHandles != NULL);\r
+  Status = HiiDatabase->ListPackageLists (\r
+                          HiiDatabase,\r
+                          EFI_HII_PACKAGE_TYPE_ALL,\r
+                          NULL,\r
+                          &BufferSize,\r
+                          HiiHandles\r
+                          );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    gBS->FreePool (HiiHandles);\r
+    HiiHandles = EfiLibAllocatePool (BufferSize);\r
+    ASSERT (HiiHandles != NULL);\r
+\r
+    Status = HiiDatabase->ListPackageLists (\r
+                            HiiDatabase,\r
+                            EFI_HII_PACKAGE_TYPE_ALL,\r
+                            NULL,\r
+                            &BufferSize,\r
+                            HiiHandles\r
+                            );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->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 = HiiDatabase->GetPackageListHandle (\r
+                            HiiDatabase,\r
+                            HiiHandles[Index],\r
+                            &Handle\r
+                            );\r
+    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+      HiiHandle = HiiHandles[Index];\r
+      break;\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (HiiHandles);\r
+  return HiiHandle;\r
+}\r
+\r
+EFI_STATUS\r
+GetHiiHandles (\r
+  IN OUT UINTN                     *HandleBufferLength,\r
+  OUT    EFI_HII_HANDLE            **HiiHandleBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Determines the handles that are currently active in the database.\r
+  It's the caller's responsibility to free handle buffer.\r
+\r
+Arguments:\r
+  HiiDatabase           - A pointer to the EFI_HII_DATABASE_PROTOCOL instance.\r
+  HandleBufferLength    - On input, a pointer to the length of the handle buffer. On output,\r
+                          the length of the handle buffer that is required for the handles found.\r
+  HiiHandleBuffer       - Pointer to an array of Hii Handles returned.\r
+\r
+Returns:\r
+  EFI_SUCCESS           - Get an array of Hii Handles successfully.\r
+  EFI_INVALID_PARAMETER - Hii is NULL.\r
+  EFI_NOT_FOUND         - Database not found.\r
+\r
+--*/\r
+{\r
+  UINTN       BufferLength;\r
+  EFI_STATUS  Status;\r
+\r
+  BufferLength = 0;\r
+\r
+  LocateHiiProtocols ();\r
+\r
+  //\r
+  // Try to find the actual buffer size for HiiHandle Buffer.\r
+  //\r
+  Status = gIfrLibHiiDatabase->ListPackageLists (\r
+                                 gIfrLibHiiDatabase,\r
+                                 EFI_HII_PACKAGE_TYPE_ALL,\r
+                                 NULL,\r
+                                 &BufferLength,\r
+                                 *HiiHandleBuffer\r
+                                 );\r
+\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      *HiiHandleBuffer = EfiLibAllocateZeroPool (BufferLength);\r
+      Status = gIfrLibHiiDatabase->ListPackageLists (\r
+                                     gIfrLibHiiDatabase,\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
+EFI_STATUS\r
+ExtractGuidFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      Handle,\r
+  OUT     EFI_GUID            *Guid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Extract Hii package list GUID for given HII handle.\r
+\r
+Arguments:\r
+  HiiHandle     - Hii handle\r
+  Guid          - Package list GUID\r
+\r
+Returns:\r
+  EFI_SUCCESS   - Successfully extract GUID from Hii database.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+\r
+  //\r
+  // Locate HII Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  &HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = EfiLibAllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Extract GUID\r
+  //\r
+  EfiCopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));\r
+\r
+  gBS->FreePool (HiiPackageList);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ExtractClassFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      Handle,\r
+  OUT     UINT16              *Class,\r
+  OUT     EFI_STRING_ID       *FormSetTitle,\r
+  OUT     EFI_STRING_ID       *FormSetHelp\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Extract formset class for given HII handle.\r
+\r
+Arguments:\r
+  HiiHandle       - Hii handle\r
+  Class           - Class of the formset\r
+  FormSetTitle    - Formset title string\r
+  FormSetHelp     - Formset help string\r
+\r
+Returns:\r
+  EFI_SUCCESS     - Successfully extract Class for specified Hii handle.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINT8                        *Package;\r
+  UINT8                        *FormSet;\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+\r
+  *Class = EFI_NON_DEVICE_CLASS;\r
+  *FormSetTitle = 0;\r
+  *FormSetHelp = 0;\r
+\r
+  //\r
+  // Locate HII Database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  &HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = EfiLibAllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  Offset2 = 0;\r
+  FormSet = NULL;\r
+  EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+      //\r
+      // Search Class Opcode in this Form Package\r
+      //\r
+      Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+      while (Offset2 < PackageHeader.Length) {\r
+        OpCodeData = Package + Offset2;\r
+\r
+        if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+          //\r
+          // Find FormSet OpCode\r
+          //\r
+          EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
+          EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
+        }\r
+\r
+        if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP) &&\r
+            (EfiCompareGuid (&mIfrVendorGuid, &((EFI_IFR_GUID *) OpCodeData)->Guid)) &&\r
+            (((EFI_IFR_GUID_CLASS *) OpCodeData)->ExtendOpCode == EFI_IFR_EXTEND_OP_CLASS)\r
+           ) {\r
+          //\r
+          // Find GUIDed Class OpCode\r
+          //\r
+          EfiCopyMem (Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));\r
+\r
+          //\r
+          // Till now, we ought to have found the formset Opcode\r
+          //\r
+          break;\r
+        }\r
+\r
+        Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      }\r
+\r
+      if (Offset2 < PackageHeader.Length) {\r
+        //\r
+        // Target formset found\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += PackageHeader.Length;\r
+  }\r
+\r
+  gBS->FreePool (HiiPackageList);\r
+\r
+  return EFI_SUCCESS;\r
+}\r