+/**\r
+ This function allows a caller to extract the form set opcode form the Hii Handle.\r
+ The returned buffer is allocated using AllocatePool().The caller is responsible \r
+ for freeing the allocated buffer using FreePool().\r
+\r
+ @param Handle The HII handle.\r
+ @param Buffer On return, opints to a pointer which point to the buffer that contain the formset opcode.\r
+ @param BufferSize On return, points to the length of the buffer.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
+ @retval EFI_NOT_FOUND Can't find the package data for the input Handle.\r
+ @retval EFI_INVALID_PARAMETER The input parameters are not correct.\r
+ @retval EFI_SUCCESS Get the formset opcode from the hii handle sucessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetFormSetFromHiiHandle(\r
+ IN EFI_HII_HANDLE Handle,\r
+ OUT EFI_IFR_FORM_SET **Buffer,\r
+ OUT UINTN *BufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN PackageListSize;\r
+ UINTN TempSize;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ EFI_IFR_FORM_SET *FormSetBuffer;\r
+ EFI_IFR_FORM_SET *TempBuffer;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ TempSize = 0;\r
+ FormSetBuffer = NULL;\r
+ TempBuffer = NULL;\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ PackageListSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
+ if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+ return Status;\r
+ }\r
+\r
+ HiiPackageList = AllocatePool (PackageListSize);\r
+ if (HiiPackageList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *) HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ Offset += PackageHeader.Length;\r
+\r
+ if (PackageHeader.Type != EFI_HII_PACKAGE_FORMS) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Search FormSet Opcode in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+\r
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_FORM_SET_OP) {\r
+ continue;\r
+ }\r
+\r
+ if (FormSetBuffer != NULL){\r
+ TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, FormSetBuffer);\r
+ CopyMem (TempBuffer + TempSize, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+ FreePool(FormSetBuffer);\r
+ } else {\r
+ TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, OpCodeData);\r
+ }\r
+ TempSize += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ FormSetBuffer = TempBuffer;\r
+\r
+ Status = EFI_SUCCESS;\r
+ //\r
+ //One form package has one formset, exit current form package to search other form package in the packagelist.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+ FreePool (HiiPackageList);\r
+\r
+ *BufferSize = TempSize;\r
+ *Buffer = FormSetBuffer;\r
+\r
+ return Status;\r
+}\r
+\r