/** @file\r
HII Library implementation that uses DXE protocols and services.\r
\r
- Copyright (c) 2006 - 2008, Intel Corporation<BR>\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
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\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
+\r
+#include "InternalHiiLib.h"\r
+\r
+#define GUID_CONFIG_STRING_TYPE 0x00\r
+#define NAME_CONFIG_STRING_TYPE 0x01\r
+#define PATH_CONFIG_STRING_TYPE 0x02\r
+\r
+#define ACTION_SET_DEFAUTL_VALUE 0x01\r
+#define ACTION_VALIDATE_SETTING 0x02\r
+\r
+#define HII_LIB_DEFAULT_VARSTORE_SIZE 0x200\r
+\r
+typedef struct {\r
+ LIST_ENTRY Entry; // Link to Block array\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ UINT8 OpCode;\r
+ UINT8 Scope;\r
+} IFR_BLOCK_DATA;\r
+\r
+typedef struct {\r
+ EFI_VARSTORE_ID VarStoreId;\r
+ UINT16 Size;\r
+} IFR_VARSTORAGE_DATA;\r
+\r
+//\r
+// <ConfigHdr> Template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";\r
+\r
+EFI_FORM_BROWSER2_PROTOCOL *mUefiFormBrowser2 = NULL;\r
+\r
+//\r
+// Template used to mark the end of a list of packages\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER mEndOfPakageList = {\r
+ sizeof (EFI_HII_PACKAGE_HEADER),\r
+ EFI_HII_PACKAGE_END\r
+};\r
+\r
+/**\r
+ Extract Hii package list GUID for given HII handle.\r
+\r
+ If HiiHandle could not be found in the 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
+InternalHiiExtractGuidFromHiiHandle (\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 (Handle != NULL);\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, 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 = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (HiiPackageList);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Extract GUID\r
+ //\r
+ CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Registers a list of packages in the HII Database and returns the HII Handle\r
+ associated with that registration. If an HII Handle has already been registered\r
+ with the same PackageListGuid and DeviceHandle, then NULL is returned. If there\r
+ are not enough resources to perform the registration, then NULL is returned.\r
+ If an empty list of packages is passed in, then NULL is returned. If the size of\r
+ the list of package is 0, then NULL is returned.\r
+\r
+ The variable arguments are pointers which point to package header that defined\r
+ by UEFI VFR compiler and StringGather tool.\r
+\r
+ #pragma pack (push, 1)\r
+ typedef struct {\r
+ UINT32 BinaryLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ } EDKII_AUTOGEN_PACKAGES_HEADER;\r
+ #pragma pack (pop)\r
+\r
+ @param[in] PackageListGuid The GUID of the package list.\r
+ @param[in] DeviceHandle If not NULL, the Device Handle on which\r
+ an instance of DEVICE_PATH_PROTOCOL is installed.\r
+ This Device Handle uniquely defines the device that\r
+ the added packages are associated with.\r
+ @param[in] ... The variable argument list that contains pointers\r
+ to packages terminated by a NULL.\r
+\r
+ @retval NULL A HII Handle has already been registered in the HII Database with\r
+ the same PackageListGuid and DeviceHandle.\r
+ @retval NULL The HII Handle could not be created.\r
+ @retval NULL An empty list of packages was passed in.\r
+ @retval NULL All packages are empty.\r
+ @retval Other The HII Handle associated with the newly registered package list.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+EFIAPI\r
+HiiAddPackages (\r
+ IN CONST EFI_GUID *PackageListGuid,\r
+ IN EFI_HANDLE DeviceHandle OPTIONAL,\r
+ ...\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VA_LIST Args;\r
+ UINT32 *Package;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ UINT32 Length;\r
+ UINT8 *Data;\r
+\r
+ ASSERT (PackageListGuid != NULL);\r
+\r
+ //\r
+ // Calculate the length of all the packages in the variable argument list\r
+ //\r
+ for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
+ Length += (ReadUnaligned32 (Package) - sizeof (UINT32));\r
+ }\r
+ VA_END (Args);\r
+\r
+ //\r
+ // If there are no packages in the variable argument list or all the packages\r
+ // are empty, then return a NULL HII Handle\r
+ //\r
+ if (Length == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Add the length of the Package List Header and the terminating Package Header\r
+ //\r
+ Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);\r
+\r
+ //\r
+ // Allocate the storage for the entire Package List\r
+ //\r
+ PackageListHeader = AllocateZeroPool (Length);\r
+\r
+ //\r
+ // If the Package List can not be allocated, then return a NULL HII Handle\r
+ //\r
+ if (PackageListHeader == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Fill in the GUID and Length of the Package List Header\r
+ //\r
+ CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);\r
+ PackageListHeader->PackageLength = Length;\r
+\r
+ //\r
+ // Initialize a pointer to the beginning if the Package List data\r
+ //\r
+ Data = (UINT8 *)(PackageListHeader + 1);\r
+\r
+ //\r
+ // Copy the data from each package in the variable argument list\r
+ //\r
+ for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
+ Length = ReadUnaligned32 (Package) - sizeof (UINT32);\r
+ CopyMem (Data, Package + 1, Length);\r
+ Data += Length;\r
+ }\r
+ VA_END (Args);\r
+\r
+ //\r
+ // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list\r
+ //\r
+ CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));\r
+\r
+ //\r
+ // Register the package list with the HII Database\r
+ //\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageListHeader,\r
+ DeviceHandle,\r
+ &HiiHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ HiiHandle = NULL;\r
+ }\r
+\r
+ //\r
+ // Free the allocated package list\r
+ //\r
+ FreePool (PackageListHeader);\r
+\r
+ //\r
+ // Return the new HII Handle\r
+ //\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ Removes a package list from the HII database.\r
+\r
+ If HiiHandle is NULL, then ASSERT.\r
+ If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.\r
+\r
+ @param[in] HiiHandle The handle that was previously registered in the HII database\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiRemovePackages (\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+ Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+/**\r
+ Retrieves the array of all the HII Handles or the HII handles of a specific\r
+ package list GUID in the HII Database.\r
+ This array is terminated with a NULL HII Handle.\r
+ This function allocates the returned array using AllocatePool().\r
+ The caller is responsible for freeing the array with FreePool().\r
+\r
+ @param[in] PackageListGuid An optional parameter that is used to request\r
+ HII Handles associated with a specific\r
+ Package List GUID. If this parameter is NULL,\r
+ then all the HII Handles in the HII Database\r
+ are returned. If this parameter is not NULL,\r
+ then zero or more HII Handles associated with\r
+ PackageListGuid are returned.\r
+\r
+ @retval NULL No HII handles were found in the HII database\r
+ @retval NULL The array of HII Handles could not be retrieved\r
+ @retval Other A pointer to the NULL terminated array of HII Handles\r
+\r
+**/\r
+EFI_HII_HANDLE *\r
+EFIAPI\r
+HiiGetHiiHandles (\r
+ IN CONST EFI_GUID *PackageListGuid OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleBufferLength;\r
+ EFI_HII_HANDLE TempHiiHandleBuffer;\r
+ EFI_HII_HANDLE *HiiHandleBuffer;\r
+ EFI_GUID Guid;\r
+ UINTN Index1;\r
+ UINTN Index2;\r
+\r
+ //\r
+ // Retrieve the size required for the buffer of all HII handles.\r
+ //\r
+ HandleBufferLength = 0;\r
+ Status = gHiiDatabase->ListPackageLists (\r
+ gHiiDatabase,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &HandleBufferLength,\r
+ &TempHiiHandleBuffer\r
+ );\r
+\r
+ //\r
+ // If ListPackageLists() returns EFI_SUCCESS for a zero size,\r
+ // then there are no HII handles in the HII database. If ListPackageLists()\r
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII\r
+ // handles in the HII database.\r
+ //\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // Return NULL if the size can not be retrieved, or if there are no HII\r
+ // handles in the HII Database\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator\r
+ //\r
+ HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));\r
+ if (HiiHandleBuffer == NULL) {\r
+ //\r
+ // Return NULL if allocation fails.\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve the array of HII Handles in the HII Database\r
+ //\r
+ Status = gHiiDatabase->ListPackageLists (\r
+ gHiiDatabase,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &HandleBufferLength,\r
+ HiiHandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Free the buffer and return NULL if the HII handles can not be retrieved.\r
+ //\r
+ FreePool (HiiHandleBuffer);\r
+ return NULL;\r
+ }\r
+\r
+ if (PackageListGuid == NULL) {\r
+ //\r
+ // Return the NULL terminated array of HII handles in the HII Database\r
+ //\r
+ return HiiHandleBuffer;\r
+ } else {\r
+ for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) {\r
+ Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (CompareGuid (&Guid, PackageListGuid)) {\r
+ HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1];\r
+ }\r
+ }\r
+ if (Index2 > 0) {\r
+ HiiHandleBuffer[Index2] = NULL;\r
+ return HiiHandleBuffer;\r
+ } else {\r
+ FreePool (HiiHandleBuffer);\r
+ return NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\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, points 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 successfully.\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
+ UINT8 *FormSetBuffer;\r
+ UINT8 *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 = ReallocatePool (\r
+ TempSize,\r
+ TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length,\r
+ FormSetBuffer\r
+ );\r
+ if (TempBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ CopyMem (TempBuffer + TempSize, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+ FormSetBuffer = NULL;\r
+ } else {\r
+ TempBuffer = AllocatePool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+ if (TempBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ CopyMem (TempBuffer, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\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
+Done:\r
+ FreePool (HiiPackageList);\r
+\r
+ *BufferSize = TempSize;\r
+ *Buffer = (EFI_IFR_FORM_SET *)FormSetBuffer;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for\r
+ hex digits that appear between a '=' and a '&' in a config string.\r
+\r
+ If ConfigString is NULL, then ASSERT().\r
+\r
+ @param[in] ConfigString Pointer to a Null-terminated Unicode string.\r
+\r
+ @return Pointer to the Null-terminated Unicode result string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiLowerConfigString (\r
+ IN EFI_STRING ConfigString\r
+ )\r
+{\r
+ EFI_STRING String;\r
+ BOOLEAN Lower;\r
+\r
+ ASSERT (ConfigString != NULL);\r
+\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+ if (*String == L'=') {\r
+ Lower = TRUE;\r
+ } else if (*String == L'&') {\r
+ Lower = FALSE;\r
+ } else if (Lower && *String >= L'A' && *String <= L'F') {\r
+ *String = (CHAR16) (*String - L'A' + L'a');\r
+ }\r
+ }\r
+\r
+ return ConfigString;\r
+}\r
+\r
+/**\r
+ Uses the BlockToConfig() service of the Config Routing Protocol to\r
+ convert <ConfigRequest> and a buffer to a <ConfigResp>\r
+\r
+ If ConfigRequest is NULL, then ASSERT().\r
+ If Block is NULL, then ASSERT().\r
+\r
+ @param[in] ConfigRequest Pointer to a Null-terminated Unicode string.\r
+ @param[in] Block Pointer to a block of data.\r
+ @param[in] BlockSize The zie, in bytes, of Block.\r
+\r
+ @retval NULL The <ConfigResp> string could not be generated.\r
+ @retval Other Pointer to the Null-terminated Unicode <ConfigResp> string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiBlockToConfig (\r
+ IN CONST EFI_STRING ConfigRequest,\r
+ IN CONST UINT8 *Block,\r
+ IN UINTN BlockSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING ConfigResp;\r
+ CHAR16 *Progress;\r
+\r
+ ASSERT (ConfigRequest != NULL);\r
+ ASSERT (Block != NULL);\r
+\r
+ //\r
+ // Convert <ConfigRequest> to <ConfigResp>\r
+ //\r
+ Status = gHiiConfigRouting->BlockToConfig (\r
+ gHiiConfigRouting,\r
+ ConfigRequest,\r
+ Block,\r
+ BlockSize,\r
+ &ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ return ConfigResp;\r
+}\r
+\r
+/**\r
+ Uses the BrowserCallback() service of the Form Browser Protocol to retrieve\r
+ or set uncommitted data. If sata i being retrieved, then the buffer is\r
+ allocated using AllocatePool(). The caller is then responsible for freeing\r
+ the buffer using FreePool().\r
+\r
+ @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
+ parameter that may be NULL.\r
+ @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
+ is an optional parameter that may be NULL.\r
+ @param[in] SetResultsData If not NULL, then this parameter specified the buffer\r
+ of uncommited data to set. If this parameter is NULL,\r
+ then the caller is requesting to get the uncommited data\r
+ from the Form Browser.\r
+\r
+ @retval NULL The uncommitted data could not be retrieved.\r
+ @retval Other A pointer to a buffer containing the uncommitted data.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiBrowserCallback (\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName, OPTIONAL\r
+ IN CONST EFI_STRING SetResultsData OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ResultsDataSize;\r
+ EFI_STRING ResultsData;\r
+ CHAR16 TempResultsData;\r
+\r
+ //\r
+ // Locate protocols\r
+ //\r
+ if (mUefiFormBrowser2 == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);\r
+ if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ ResultsDataSize = 0;\r
+\r
+ if (SetResultsData != NULL) {\r
+ //\r
+ // Request to to set data in the uncommitted browser state information\r
+ //\r
+ ResultsData = SetResultsData;\r
+ } else {\r
+ //\r
+ // Retrieve the length of the buffer required ResultsData from the Browser Callback\r
+ //\r
+ Status = mUefiFormBrowser2->BrowserCallback (\r
+ mUefiFormBrowser2,\r
+ &ResultsDataSize,\r
+ &TempResultsData,\r
+ TRUE,\r
+ VariableGuid,\r
+ VariableName\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // No Resluts Data, only allocate one char for '\0'\r
+ //\r
+ ResultsData = AllocateZeroPool (sizeof (CHAR16));\r
+ return ResultsData;\r
+ }\r
+\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Allocate the ResultsData buffer\r
+ //\r
+ ResultsData = AllocateZeroPool (ResultsDataSize);\r
+ if (ResultsData == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Retrieve or set the ResultsData from the Browser Callback\r
+ //\r
+ Status = mUefiFormBrowser2->BrowserCallback (\r
+ mUefiFormBrowser2,\r
+ &ResultsDataSize,\r
+ ResultsData,\r
+ (BOOLEAN)(SetResultsData == NULL),\r
+ VariableGuid,\r
+ VariableName\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ return ResultsData;\r
+}\r
+\r
+/**\r
+ Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing\r
+ information that includes a GUID, an optional Unicode string name, and a device\r
+ path. The string returned is allocated with AllocatePool(). The caller is\r
+ responsible for freeing the allocated string with FreePool().\r
+\r
+ The format of a <ConfigHdr> is as follows:\r
+\r
+ GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
+\r
+ @param[in] Guid Pointer to an EFI_GUID that is the routing information\r
+ GUID. Each of the 16 bytes in Guid is converted to\r
+ a 2 Unicode character hexadecimal string. This is\r
+ an optional parameter that may be NULL.\r
+ @param[in] Name Pointer to a Null-terminated Unicode string that is\r
+ the routing information NAME. This is an optional\r
+ parameter that may be NULL. Each 16-bit Unicode\r
+ character in Name is converted to a 4 character Unicode\r
+ hexadecimal string.\r
+ @param[in] DriverHandle The driver handle which supports a Device Path Protocol\r
+ that is the routing information PATH. Each byte of\r
+ the Device Path associated with DriverHandle is converted\r
+ to a 2 Unicode character hexadecimal string.\r
+\r
+ @retval NULL DriverHandle does not support the Device Path Protocol.\r
+ @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+HiiConstructConfigHdr (\r
+ IN CONST EFI_GUID *Guid, OPTIONAL\r
+ IN CONST CHAR16 *Name, OPTIONAL\r
+ IN EFI_HANDLE DriverHandle\r
+ )\r
+{\r
+ UINTN NameLength;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN DevicePathSize;\r
+ CHAR16 *String;\r
+ CHAR16 *ReturnString;\r
+ UINTN Index;\r
+ UINT8 *Buffer;\r
+ UINTN MaxLen;\r
+\r
+ //\r
+ // Compute the length of Name in Unicode characters.\r
+ // If Name is NULL, then the length is 0.\r
+ //\r
+ NameLength = 0;\r
+ if (Name != NULL) {\r
+ NameLength = StrLen (Name);\r
+ }\r
+\r
+ DevicePath = NULL;\r
+ DevicePathSize = 0;\r
+ //\r
+ // Retrieve DevicePath Protocol associated with DriverHandle\r
+ //\r
+ if (DriverHandle != NULL) {\r
+ DevicePath = DevicePathFromHandle (DriverHandle);\r
+ if (DevicePath == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // Compute the size of the device path in bytes\r
+ //\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+ }\r
+\r
+ //\r
+ // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
+ // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
+ //\r
+ MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
+ String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Start with L"GUID="\r
+ //\r
+ StrCpyS (String, MaxLen, L"GUID=");\r
+ ReturnString = String;\r
+ String += StrLen (String);\r
+\r
+ if (Guid != NULL) {\r
+ //\r
+ // Append Guid converted to <HexCh>32\r
+ //\r
+ for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
+ UnicodeValueToStringS (\r
+ String,\r
+ MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *(Buffer++),\r
+ 2\r
+ );\r
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Append L"&NAME="\r
+ //\r
+ StrCatS (ReturnString, MaxLen, L"&NAME=");\r
+ String += StrLen (String);\r
+\r
+ if (Name != NULL) {\r
+ //\r
+ // Append Name converted to <Char>NameLength\r
+ //\r
+ for (; *Name != L'\0'; Name++) {\r
+ UnicodeValueToStringS (\r
+ String,\r
+ sizeof (CHAR16) * MaxLen - ((UINTN)String - (UINTN)ReturnString),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *Name,\r
+ 4\r
+ );\r
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Append L"&PATH="\r
+ //\r
+ StrCatS (ReturnString, MaxLen, L"&PATH=");\r
+ String += StrLen (String);\r
+\r
+ //\r
+ // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
+ //\r
+ for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
+ UnicodeValueToStringS (\r
+ String,\r
+ sizeof (CHAR16) * MaxLen - ((UINTN)String - (UINTN)ReturnString),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *(Buffer++),\r
+ 2\r
+ );\r
+ String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
+ }\r
+\r
+ //\r
+ // Null terminate the Unicode string\r
+ //\r
+ *String = L'\0';\r
+\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ return InternalHiiLowerConfigString (ReturnString);\r
+}\r
+\r
+/**\r
+ Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path\r
+ to binary buffer from <ConfigHdr>.\r
+\r
+ This is a internal function.\r
+\r
+ @param String UEFI configuration string.\r
+ @param Flag Flag specifies what type buffer will be retrieved.\r
+ @param Buffer Binary of Guid, Name or Device path.\r
+\r
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
+ @retval EFI_SUCCESS The buffer data is retrieved and translated to\r
+ binary format.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalHiiGetBufferFromString (\r
+ IN EFI_STRING String,\r
+ IN UINT8 Flag,\r
+ OUT UINT8 **Buffer\r
+ )\r
+{\r
+ UINTN Length;\r
+ EFI_STRING ConfigHdr;\r
+ CHAR16 *StringPtr;\r
+ UINT8 *DataBuffer;\r
+ CHAR16 TemStr[5];\r
+ UINTN Index;\r
+ UINT8 DigitUint8;\r
+\r
+ if (String == NULL || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DataBuffer = NULL;\r
+ StringPtr = NULL;\r
+ ConfigHdr = String;\r
+ //\r
+ // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element\r
+ // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.\r
+ //\r
+ for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
+\r
+ switch (Flag) {\r
+ case GUID_CONFIG_STRING_TYPE:\r
+ case PATH_CONFIG_STRING_TYPE:\r
+ //\r
+ // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order\r
+ // as the device path and Guid resides in RAM memory.\r
+ // Translate the data into binary.\r
+ //\r
+ DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
+ if (DataBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Convert binary byte one by one\r
+ //\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index ++) {\r
+ TemStr[0] = ConfigHdr[Index];\r
+ DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ DataBuffer [Index/2] = DigitUint8;\r
+ } else {\r
+ DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8);\r
+ }\r
+ }\r
+\r
+ *Buffer = DataBuffer;\r
+ break;\r
+\r
+ case NAME_CONFIG_STRING_TYPE:\r
+ //\r
+ // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"\r
+ //\r
+\r
+ //\r
+ // Add the tailling char L'\0'\r
+ //\r
+ DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16));\r
+ if (DataBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Convert character one by one\r
+ //\r
+ StringPtr = (CHAR16 *) DataBuffer;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index += 4) {\r
+ StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), ConfigHdr + Index, 4);\r
+ StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+ }\r
+ //\r
+ // Add tailing L'\0' character\r
+ //\r
+ StringPtr[Index/4] = L'\0';\r
+\r
+ *Buffer = DataBuffer;\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function checks VarOffset and VarWidth is in the block range.\r
+\r
+ @param BlockArray The block array is to be checked.\r
+ @param VarOffset Offset of var to the structure\r
+ @param VarWidth Width of var.\r
+\r
+ @retval TRUE This Var is in the block range.\r
+ @retval FALSE This Var is not in the block range.\r
+**/\r
+BOOLEAN\r
+BlockArrayCheck (\r
+ IN IFR_BLOCK_DATA *BlockArray,\r
+ IN UINT16 VarOffset,\r
+ IN UINT16 VarWidth\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *BlockData;\r
+\r
+ //\r
+ // No Request Block array, all vars are got.\r
+ //\r
+ if (BlockArray == NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check the input var is in the request block range.\r
+ //\r
+ for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
+ or WIDTH or VALUE.\r
+ <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+\r
+ @param ValueString String in <BlockConfig> format and points to the\r
+ first character of <Number>.\r
+ @param ValueData The output value. Caller takes the responsibility\r
+ to free memory.\r
+ @param ValueLength Length of the <Number>, in characters.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
+ structures.\r
+ @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
+ successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiGetValueOfNumber (\r
+ IN EFI_STRING ValueString,\r
+ OUT UINT8 **ValueData,\r
+ OUT UINTN *ValueLength\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ UINT8 *Buf;\r
+ UINT8 DigitUint8;\r
+ UINTN Index;\r
+ CHAR16 TemStr[2];\r
+\r
+ ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);\r
+ ASSERT (*ValueString != L'\0');\r
+\r
+ //\r
+ // Get the length of value string\r
+ //\r
+ StringPtr = ValueString;\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+ Length = StringPtr - ValueString;\r
+\r
+ //\r
+ // Allocate buffer to store the value\r
+ //\r
+ Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
+ if (Buf == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Convert character one by one to the value buffer\r
+ //\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index ++) {\r
+ TemStr[0] = ValueString[Length - Index - 1];\r
+ DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ Buf [Index/2] = DigitUint8;\r
+ } else {\r
+ Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the converted value and string length.\r
+ //\r
+ *ValueData = Buf;\r
+ *ValueLength = Length;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get value from config request resp string.\r
+\r
+ @param ConfigElement ConfigResp string contains the current setting.\r
+ @param VarName The variable name which need to get value.\r
+ @param VarValue The return value.\r
+\r
+ @retval EFI_SUCCESS Get the value for the VarName\r
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
+**/\r
+EFI_STATUS\r
+GetValueFromRequest (\r
+ IN CHAR16 *ConfigElement,\r
+ IN CHAR16 *VarName,\r
+ OUT UINT64 *VarValue\r
+ )\r
+{\r
+ UINT8 *TmpBuffer;\r
+ CHAR16 *StringPtr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Find VarName related string.\r
+ //\r
+ StringPtr = StrStr (ConfigElement, VarName);\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ //\r
+ // Skip the "VarName=" string\r
+ //\r
+ StringPtr += StrLen (VarName) + 1;\r
+\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *VarValue = 0;\r
+ CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));\r
+\r
+ FreePool (TmpBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This internal function parses IFR data to validate current setting.\r
+\r
+ Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;\r
+ else the VarBuffer and CurrentBlockArray is valid.\r
+\r
+ @param HiiPackageList Point to Hii package list.\r
+ @param PackageListLength The length of the pacakge.\r
+ @param VarGuid Guid of the buffer storage.\r
+ @param VarName Name of the buffer storage.\r
+ @param VarBuffer The data buffer for the storage.\r
+ @param CurrentBlockArray The block array from the config Requst string.\r
+ @param RequestElement The config string for this storage.\r
+ @param HiiHandle The HiiHandle for this formset.\r
+ @param NameValueType Whether current storage is name/value varstore or not.\r
+\r
+ @retval EFI_SUCCESS The current setting is valid.\r
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+ValidateQuestionFromVfr (\r
+ IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
+ IN UINTN PackageListLength,\r
+ IN EFI_GUID *VarGuid,\r
+ IN CHAR16 *VarName,\r
+ IN UINT8 *VarBuffer,\r
+ IN IFR_BLOCK_DATA *CurrentBlockArray,\r
+ IN CHAR16 *RequestElement,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN BOOLEAN NameValueType\r
+ )\r
+{\r
+ IFR_BLOCK_DATA VarBlockData;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ UINT64 VarValue;\r
+ EFI_IFR_TYPE_VALUE TmpValue;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT32 PackageOffset;\r
+ UINT8 *PackageData;\r
+ UINTN IfrOffset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\r
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueStore;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+ IFR_VARSTORAGE_DATA VarStoreData;\r
+ EFI_IFR_ONE_OF *IfrOneOf;\r
+ EFI_IFR_NUMERIC *IfrNumeric;\r
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
+ EFI_IFR_CHECKBOX *IfrCheckBox;\r
+ EFI_IFR_STRING *IfrString;\r
+ CHAR8 *VarStoreName;\r
+ UINTN Index;\r
+ CHAR16 *QuestionName;\r
+ CHAR16 *StringPtr;\r
+ UINT16 BitOffset;\r
+ UINT16 BitWidth;\r
+ UINT16 TotalBits;\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ BOOLEAN QuestionReferBitField;\r
+ UINT32 BufferValue;\r
+\r
+ //\r
+ // Initialize the local variables.\r
+ //\r
+ Index = 0;\r
+ VarStoreName = NULL;\r
+ Status = EFI_SUCCESS;\r
+ VarValue = 0;\r
+ IfrVarStore = NULL;\r
+ IfrNameValueStore = NULL;\r
+ IfrEfiVarStore = NULL;\r
+ ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
+ ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
+ BitOffset = 0;\r
+ BitWidth = 0;\r
+ QuestionReferBitField = FALSE;\r
+\r
+ //\r
+ // Check IFR value is in block data, then Validate Value\r
+ //\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ while (PackageOffset < PackageListLength) {\r
+ CopyMem (&PackageHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PackageHeader));\r
+\r
+ //\r
+ // Parse IFR opcode from the form package.\r
+ //\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ IfrOffset = sizeof (PackageHeader);\r
+ PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+ while (IfrOffset < PackageHeader.Length) {\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
+ //\r
+ // Validate current setting to the value built in IFR opcode\r
+ //\r
+ switch (IfrOpHdr->OpCode) {\r
+ case EFI_IFR_VARSTORE_OP:\r
+ //\r
+ // VarStoreId has been found. No further found.\r
+ //\r
+ if (VarStoreData.VarStoreId != 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Find the matched VarStoreId to the input VarGuid and VarName\r
+ //\r
+ IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
+ if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) {\r
+ VarStoreName = (CHAR8 *) IfrVarStore->Name;\r
+ for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
+ if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // The matched VarStore is found.\r
+ //\r
+ if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
+ IfrVarStore = NULL;\r
+ }\r
+ } else {\r
+ IfrVarStore = NULL;\r
+ }\r
+\r
+ if (IfrVarStore != NULL) {\r
+ VarStoreData.VarStoreId = IfrVarStore->VarStoreId;\r
+ VarStoreData.Size = IfrVarStore->Size;\r
+ }\r
+ break;\r
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+ //\r
+ // VarStoreId has been found. No further found.\r
+ //\r
+ if (VarStoreData.VarStoreId != 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Find the matched VarStoreId to the input VarGuid\r
+ //\r
+ IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
+ if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {\r
+ IfrNameValueStore = NULL;\r
+ }\r
+\r
+ if (IfrNameValueStore != NULL) {\r
+ VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;\r
+ }\r
+ break;\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+ //\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStoreData.VarStoreId != 0) {\r
+ break;\r
+ }\r
+\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
+\r
+ //\r
+ // If the length is small than the structure, this is from old efi\r
+ // varstore definition. Old efi varstore get config directly from\r
+ // GetVariable function.\r
+ //\r
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+ break;\r
+ }\r
+\r
+ if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {\r
+ VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;\r
+ for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
+ if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // The matched VarStore is found.\r
+ //\r
+ if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
+ IfrEfiVarStore = NULL;\r
+ }\r
+ } else {\r
+ IfrEfiVarStore = NULL;\r
+ }\r
+\r
+ if (IfrEfiVarStore != NULL) {\r
+ //\r
+ // Find the matched VarStore\r
+ //\r
+ VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;\r
+ VarStoreData.Size = IfrEfiVarStore->Size;\r
+ }\r
+ break;\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+ //\r
+ // Check the matched VarStoreId is found.\r
+ //\r
+ if (VarStoreData.VarStoreId == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ break;\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Check whether current value is the one of option.\r
+ //\r
+\r
+ //\r
+ // OneOf question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreData.VarStoreId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
+ if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ if (NameValueType) {\r
+ QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);\r
+ ASSERT (QuestionName != NULL);\r
+\r
+ if (StrStr (RequestElement, QuestionName) == NULL) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ //\r
+ // Get Offset by Question header and Width by DataType Flags\r
+ //\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the byte offset/width for bit field.\r
+ //\r
+ BitOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+ BitWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+ Offset = BitOffset / 8;\r
+ TotalBits = BitOffset % 8 + BitWidth;\r
+ Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+ } else {\r
+ Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+ }\r
+ //\r
+ // Check whether this question is in current block array.\r
+ //\r
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if ((Offset + Width) > VarStoreData.Size) {\r
+ //\r
+ // This question exceeds the var store size.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Get the current value for oneof opcode\r
+ //\r
+ VarValue = 0;\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the value in bit fields.\r
+ //\r
+ StartBit = BitOffset % 8;\r
+ EndBit = StartBit + BitWidth - 1;\r
+ CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+ VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+ } else {\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ }\r
+ }\r
+ //\r
+ // Set Block Data, to be checked in the following Oneof option opcode.\r
+ //\r
+ VarBlockData.OpCode = IfrOpHdr->OpCode;\r
+ VarBlockData.Scope = IfrOpHdr->Scope;\r
+ break;\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Check the current value is in the numeric range.\r
+ //\r
+\r
+ //\r
+ // Numeric question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreData.VarStoreId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
+ if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ if (NameValueType) {\r
+ QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);\r
+ ASSERT (QuestionName != NULL);\r
+\r
+ if (StrStr (RequestElement, QuestionName) == NULL) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ //\r
+ // Get Offset by Question header and Width by DataType Flags\r
+ //\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the byte offset/width for bit field.\r
+ //\r
+ BitOffset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+ BitWidth = IfrNumeric->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+ Offset = BitOffset / 8;\r
+ TotalBits = BitOffset % 8 + BitWidth;\r
+ Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+ } else {\r
+ Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
+ }\r
+ //\r
+ // Check whether this question is in current block array.\r
+ //\r
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if ((Offset + Width) > VarStoreData.Size) {\r
+ //\r
+ // This question exceeds the var store size.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check the current value is in the numeric range.\r
+ //\r
+ VarValue = 0;\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the value in the bit fields.\r
+ //\r
+ StartBit = BitOffset % 8;\r
+ EndBit = StartBit + BitWidth - 1;\r
+ CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+ VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+ } else {\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ }\r
+ }\r
+ if ( QuestionReferBitField) {\r
+ //\r
+ // Value in bit fields was stored as UINt32 type.\r
+ //\r
+ if ((IfrNumeric->Flags & EDKII_IFR_DISPLAY_BIT) == 0) {\r
+ if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ if (VarValue < IfrNumeric->data.u32.MinValue || VarValue > IfrNumeric->data.u32.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ } else {\r
+ if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {\r
+ switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ }\r
+ } else {\r
+ switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
+ //\r
+ // Not in the valid range.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ //\r
+ // Check value is BOOLEAN type, only 0 and 1 is valid.\r
+ //\r
+\r
+ //\r
+ // CheckBox question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreData.VarStoreId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
+ if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ if (NameValueType) {\r
+ QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);\r
+ ASSERT (QuestionName != NULL);\r
+\r
+ if (StrStr (RequestElement, QuestionName) == NULL) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ //\r
+ // Get Offset by Question header\r
+ //\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the byte offset/width for bit field.\r
+ //\r
+ BitOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ BitWidth = 1;\r
+ Offset = BitOffset / 8;\r
+ TotalBits = BitOffset % 8 + BitWidth;\r
+ Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+ } else {\r
+ Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) sizeof (BOOLEAN);\r
+ }\r
+ //\r
+ // Check whether this question is in current block array.\r
+ //\r
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if ((Offset + Width) > VarStoreData.Size) {\r
+ //\r
+ // This question exceeds the var store size.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check the current value is in the numeric range.\r
+ //\r
+ VarValue = 0;\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Get the value in bit fields.\r
+ //\r
+ StartBit = BitOffset % 8;\r
+ EndBit = StartBit + BitWidth - 1;\r
+ CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+ VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+ } else {\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ }\r
+ }\r
+ //\r
+ // Boolean type, only 1 and 0 is valid.\r
+ //\r
+ if (VarValue > 1) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // Check current string length is less than maxsize\r
+ //\r
+\r
+ //\r
+ // CheckBox question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreData.VarStoreId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
+ if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+ break;\r
+ }\r
+ //\r
+ // Get the Max size of the string.\r
+ //\r
+ Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
+ if (NameValueType) {\r
+ QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);\r
+ ASSERT (QuestionName != NULL);\r
+\r
+ StringPtr = StrStr (RequestElement, QuestionName);\r
+ if (StringPtr == NULL) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Skip the VarName.\r
+ //\r
+ StringPtr += StrLen (QuestionName);\r
+\r
+ //\r
+ // Skip the "=".\r
+ //\r
+ StringPtr += 1;\r
+\r
+ //\r
+ // Check current string length is less than maxsize\r
+ // e.g Config String: "0041004200430044", Unicode String: "ABCD". Unicode String length = Config String length / 4.\r
+ // Config string format in UEFI spec.\r
+ // <NvConfig> ::= <Label>'='<String>\r
+ // <String> ::= [<Char>]+\r
+ // <Char> ::= <HexCh>4\r
+ //\r
+ if (StrLen (StringPtr) / 4 > IfrString->MaxSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
+ //\r
+ // Check whether this question is in current block array.\r
+ //\r
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+ //\r
+ // This question is not in the current configuration string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if ((Offset + Width) > VarStoreData.Size) {\r
+ //\r
+ // This question exceeds the var store size.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check current string length is less than maxsize\r
+ //\r
+ if (StrLen ((CHAR16 *) (VarBuffer + Offset)) > IfrString->MaxSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ //\r
+ // Opcode Scope is zero. This one of option is not to be checked.\r
+ //\r
+ if (VarBlockData.Scope == 0) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Only check for OneOf and OrderList opcode\r
+ //\r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
+ if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
+ //\r
+ // Check current value is the value of one of option.\r
+ //\r
+ ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
+ ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+ CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ if (VarValue == TmpValue.u64) {\r
+ //\r
+ // The value is one of option value.\r
+ // Set OpCode to Zero, don't need check again.\r
+ //\r
+ VarBlockData.OpCode = 0;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_IFR_END_OP:\r
+ QuestionReferBitField = FALSE;\r
+ //\r
+ // Decrease opcode scope for the validated opcode\r
+ //\r
+ if (VarBlockData.Scope > 0) {\r
+ VarBlockData.Scope --;\r
+ }\r
+\r
+ //\r
+ // OneOf value doesn't belong to one of option value.\r
+ //\r
+ if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ case EFI_IFR_GUID_OP:\r
+ if (CompareGuid ((EFI_GUID *)((UINT8*)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+ QuestionReferBitField = TRUE;\r
+ }\r
+ break;\r
+ default:\r
+ //\r
+ // Increase Scope for the validated opcode\r
+ //\r
+ if (VarBlockData.Scope > 0) {\r
+ VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);\r
+ }\r
+ break;\r
+ }\r
+ //\r
+ // Go to the next opcode\r
+ //\r
+ IfrOffset += IfrOpHdr->Length;\r
+ }\r
+ //\r
+ // Only one form is in a package list.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Go to next package.\r
+ //\r
+ PackageOffset += PackageHeader.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This internal function parses IFR data to validate current setting.\r
+\r
+ @param ConfigElement ConfigResp element string contains the current setting.\r
+ @param CurrentBlockArray Current block array.\r
+ @param VarBuffer Data buffer for this varstore.\r
+\r
+ @retval EFI_SUCCESS The current setting is valid.\r
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+GetBlockDataInfo (\r
+ IN CHAR16 *ConfigElement,\r
+ OUT IFR_BLOCK_DATA **CurrentBlockArray,\r
+ OUT UINT8 **VarBuffer\r
+ )\r
+{\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *NewBlockData;\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ UINT8 *TmpBuffer;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ LIST_ENTRY *Link;\r
+ UINTN MaxBufferSize;\r
+ EFI_STATUS Status;\r
+ IFR_BLOCK_DATA *BlockArray;\r
+ UINT8 *DataBuffer;\r
+\r
+ //\r
+ // Initialize the local variables.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ BlockData = NULL;\r
+ NewBlockData = NULL;\r
+ TmpBuffer = NULL;\r
+ BlockArray = NULL;\r
+ MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+ DataBuffer = AllocateZeroPool (MaxBufferSize);\r
+ if (DataBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Init BlockArray\r
+ //\r
+ BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&BlockArray->Entry);\r
+\r
+ StringPtr = StrStr (ConfigElement, L"&OFFSET=");\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ //\r
+ // Parse each <RequestElement> if exists\r
+ // Only <BlockName> format is supported by this help function.\r
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
+ //\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
+ //\r
+ // Skip the &OFFSET= string\r
+ //\r
+ StringPtr += StrLen (L"&OFFSET=");\r
+\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ Offset = 0;\r
+ CopyMem (\r
+ &Offset,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+ );\r
+ FreePool (TmpBuffer);\r
+ TmpBuffer = NULL;\r
+\r
+ StringPtr += Length;\r
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ StringPtr += StrLen (L"&WIDTH=");\r
+\r
+ //\r
+ // Get Width\r
+ //\r
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ Width = 0;\r
+ CopyMem (\r
+ &Width,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+ );\r
+ FreePool (TmpBuffer);\r
+ TmpBuffer = NULL;\r
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ StringPtr += StrLen (L"&VALUE=");\r
+\r
+ //\r
+ // Get Value\r
+ //\r
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether VarBuffer is enough\r
+ //\r
+ if ((UINT32)Offset + Width > MaxBufferSize) {\r
+ DataBuffer = ReallocatePool (\r
+ MaxBufferSize,\r
+ Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
+ DataBuffer\r
+ );\r
+ if (DataBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+ }\r
+\r
+ //\r
+ // Update the Block with configuration info\r
+ //\r
+ CopyMem (DataBuffer + Offset, TmpBuffer, Width);\r
+ FreePool (TmpBuffer);\r
+ TmpBuffer = NULL;\r
+\r
+ //\r
+ // Set new Block Data\r
+ //\r
+ NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (NewBlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ NewBlockData->Offset = Offset;\r
+ NewBlockData->Width = Width;\r
+\r
+ //\r
+ // Insert the new block data into the block data array.\r
+ //\r
+ for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (NewBlockData->Offset == BlockData->Offset) {\r
+ if (NewBlockData->Width > BlockData->Width) {\r
+ BlockData->Width = NewBlockData->Width;\r
+ }\r
+ FreePool (NewBlockData);\r
+ break;\r
+ } else if (NewBlockData->Offset < BlockData->Offset) {\r
+ //\r
+ // Insert new block data as the previous one of this link.\r
+ //\r
+ InsertTailList (Link, &NewBlockData->Entry);\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Insert new block data into the array tail.\r
+ //\r
+ if (Link == &BlockArray->Entry) {\r
+ InsertTailList (Link, &NewBlockData->Entry);\r
+ }\r
+\r
+ //\r
+ // If '\0', parsing is finished.\r
+ //\r
+ if (*StringPtr == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Go to next ConfigBlock\r
+ //\r
+ }\r
+\r
+ //\r
+ // Merge the aligned block data into the single block data.\r
+ //\r
+ Link = BlockArray->Entry.ForwardLink;\r
+ while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
+ if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
+ BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);\r
+ }\r
+ RemoveEntryList (Link->ForwardLink);\r
+ FreePool (NewBlockData);\r
+ continue;\r
+ }\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ *VarBuffer = DataBuffer;\r
+ *CurrentBlockArray = BlockArray;\r
+ return EFI_SUCCESS;\r
+\r
+Done:\r
+ if (DataBuffer != NULL) {\r
+ FreePool (DataBuffer);\r
+ }\r
+\r
+ if (BlockArray != NULL) {\r
+ //\r
+ // Free Link Array CurrentBlockArray\r
+ //\r
+ while (!IsListEmpty (&BlockArray->Entry)) {\r
+ BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ FreePool (BlockData);\r
+ }\r
+ FreePool (BlockArray);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This internal function parses IFR data to validate current setting.\r
+\r
+ @param ConfigResp ConfigResp string contains the current setting.\r
+ @param HiiPackageList Point to Hii package list.\r
+ @param PackageListLength The length of the pacakge.\r
+ @param VarGuid Guid of the buffer storage.\r
+ @param VarName Name of the buffer storage.\r
+ @param HiiHandle The HiiHandle for this package.\r
+\r
+ @retval EFI_SUCCESS The current setting is valid.\r
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.\r
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiValidateCurrentSetting (\r
+ IN EFI_STRING ConfigResp,\r
+ IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
+ IN UINTN PackageListLength,\r
+ IN EFI_GUID *VarGuid,\r
+ IN CHAR16 *VarName,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ EFI_STATUS Status;\r
+ IFR_BLOCK_DATA *CurrentBlockArray;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ UINT8 *VarBuffer;\r
+ BOOLEAN NameValueType;\r
+\r
+ CurrentBlockArray = NULL;\r
+ VarBuffer = NULL;\r
+ StringPtr = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // If StringPtr != NULL, get the request elements.\r
+ //\r
+ if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {\r
+ Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ NameValueType = FALSE;\r
+ } else {\r
+ //\r
+ // Skip header part.\r
+ //\r
+ StringPtr = StrStr (ConfigResp, L"PATH=");\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ if (StrStr (StringPtr, L"&") != NULL) {\r
+ NameValueType = TRUE;\r
+ } else {\r
+ //\r
+ // Not found Request element, return success.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Status = ValidateQuestionFromVfr(\r
+ HiiPackageList,\r
+ PackageListLength,\r
+ VarGuid,\r
+ VarName,\r
+ VarBuffer,\r
+ CurrentBlockArray,\r
+ ConfigResp,\r
+ HiiHandle,\r
+ NameValueType\r
+ );\r
+\r
+ if (VarBuffer != NULL) {\r
+ FreePool (VarBuffer);\r
+ }\r
+\r
+ if (CurrentBlockArray != NULL) {\r
+ //\r
+ // Free Link Array CurrentBlockArray\r
+ //\r
+ while (!IsListEmpty (&CurrentBlockArray->Entry)) {\r
+ BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ FreePool (BlockData);\r
+ }\r
+ FreePool (CurrentBlockArray);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check whether the ConfigRequest string has the request elements.\r
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
+\r
+ @param ConfigRequest The input config request string.\r
+\r
+ @retval TRUE The input include config request elements.\r
+ @retval FALSE The input string not includes.\r
+\r
+**/\r
+BOOLEAN\r
+GetElementsFromRequest (\r
+ IN EFI_STRING ConfigRequest\r
+ )\r
+{\r
+ EFI_STRING TmpRequest;\r
+\r
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
+ ASSERT (TmpRequest != NULL);\r
+\r
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ This function parses the input ConfigRequest string and its matched IFR code\r
+ string for setting default value and validating current setting.\r
+\r
+ 1. For setting default action, Reset the default value specified by DefaultId\r
+ to the driver configuration got by Request string.\r
+ 2. For validating current setting, Validate the current configuration\r
+ by parsing HII form IFR opcode.\r
+\r
+ NULL request string support depends on the ExportConfig interface of\r
+ HiiConfigRouting protocol in UEFI specification.\r
+\r
+ @param Request A null-terminated Unicode string in\r
+ <MultiConfigRequest> format. It can be NULL.\r
+ If it is NULL, all current configuration for the\r
+ entirety of the current HII database will be validated.\r
+ If it is NULL, all configuration for the\r
+ entirety of the current HII database will be reset.\r
+ @param DefaultId Specifies the type of defaults to retrieve only for setting default action.\r
+ @param ActionType Action supports setting defaults and validate current setting.\r
+\r
+ @retval TRUE Action runs successfully.\r
+ @retval FALSE Action is not valid or Action can't be executed successfully..\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalHiiIfrValueAction (\r
+ IN CONST EFI_STRING Request, OPTIONAL\r
+ IN UINT16 DefaultId,\r
+ IN UINT8 ActionType\r
+ )\r
+{\r
+ EFI_STRING ConfigAltResp;\r
+ EFI_STRING ConfigAltHdr;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING Progress;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING StringHdr;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HANDLE TempDriverHandle;\r
+ EFI_HII_HANDLE *HiiHandleBuffer;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ UINT32 Index;\r
+ EFI_GUID *VarGuid;\r
+ EFI_STRING VarName;\r
+\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN PackageListLength;\r
+ UINTN MaxLen;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+\r
+ ConfigAltResp = NULL;\r
+ ConfigResp = NULL;\r
+ VarGuid = NULL;\r
+ VarName = NULL;\r
+ DevicePath = NULL;\r
+ ConfigAltHdr = NULL;\r
+ HiiHandleBuffer = NULL;\r
+ Index = 0;\r
+ TempDriverHandle = NULL;\r
+ HiiHandle = NULL;\r
+ HiiPackageList = NULL;\r
+\r
+ //\r
+ // Only support set default and validate setting action.\r
+ //\r
+ if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Get the full requested value and deault value string.\r
+ //\r
+ if (Request != NULL) {\r
+ Status = gHiiConfigRouting->ExtractConfig (\r
+ gHiiConfigRouting,\r
+ Request,\r
+ &Progress,\r
+ &ConfigAltResp\r
+ );\r
+ } else {\r
+ Status = gHiiConfigRouting->ExportConfig (\r
+ gHiiConfigRouting,\r
+ &ConfigAltResp\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ StringPtr = ConfigAltResp;\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ while (*StringPtr != L'\0') {\r
+ //\r
+ // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
+ //\r
+ StringHdr = StringPtr;\r
+\r
+ //\r
+ // Get Guid value\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ StringPtr += StrLen (L"GUID=");\r
+ Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get Name value VarName\r
+ //\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == L'\0') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ StringPtr += StrLen (L"&NAME=");\r
+ Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get Path value DevicePath\r
+ //\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == L'\0') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ StringPtr += StrLen (L"&PATH=");\r
+ Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get the Driver handle by the got device path.\r
+ //\r
+ TempDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Find the matched Hii Handle for the found Driver handle\r
+ //\r
+ HiiHandleBuffer = HiiGetHiiHandles (NULL);\r
+ if (HiiHandleBuffer == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {\r
+ gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);\r
+ if (TempDriverHandle == DriverHandle) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ HiiHandle = HiiHandleBuffer[Index];\r
+ FreePool (HiiHandleBuffer);\r
+\r
+ if (HiiHandle == NULL) {\r
+ //\r
+ // This request string has no its Hii package.\r
+ // Its default value and validating can't execute by parsing IFR data.\r
+ // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ goto NextConfigAltResp;\r
+ }\r
+\r
+ //\r
+ // 2. Get HiiPackage by HiiHandle\r
+ //\r
+ PackageListLength = 0;\r
+ HiiPackageList = NULL;\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
+\r
+ //\r
+ // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
+ //\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ HiiPackageList = AllocatePool (PackageListLength);\r
+ if (HiiPackageList == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get PackageList on HiiHandle\r
+ //\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+ // Get the default configuration string according to the default ID.\r
+ //\r
+ Status = gHiiConfigRouting->GetAltConfig (\r
+ gHiiConfigRouting,\r
+ ConfigAltResp,\r
+ VarGuid,\r
+ VarName,\r
+ DevicePath,\r
+ (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL, // it can be NULL to get the current setting.\r
+ &ConfigResp\r
+ );\r
+\r
+ //\r
+ // The required setting can't be found. So, it is not required to be validated and set.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_SUCCESS;\r
+ goto NextConfigAltResp;\r
+ }\r
+ //\r
+ // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.\r
+ //\r
+ if (!GetElementsFromRequest (ConfigResp)) {\r
+ goto NextConfigAltResp;\r
+ }\r
+\r
+ //\r
+ // 4. Set the default configuration information or Validate current setting by parse IFR code.\r
+ // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
+ //\r
+ if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
+ //\r
+ // Set the default configuration information.\r
+ //\r
+ Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);\r
+ } else {\r
+ //\r
+ // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
+ //\r
+ Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+NextConfigAltResp:\r
+ //\r
+ // Free the allocated pacakge buffer and the got ConfigResp string.\r
+ //\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ HiiPackageList = NULL;\r
+ }\r
+\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ ConfigResp = NULL;\r
+ }\r
+\r
+ //\r
+ // Free the allocated buffer.\r
+ //\r
+ FreePool (VarGuid);\r
+ VarGuid = NULL;\r
+\r
+ FreePool (VarName);\r
+ VarName = NULL;\r
+\r
+ FreePool (DevicePath);\r
+ DevicePath = NULL;\r
+\r
+ //\r
+ // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
+ //\r
+\r
+ //\r
+ // Get and Skip ConfigHdr\r
+ //\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == L'\0') {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0"\r
+ // | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
+ //\r
+ MaxLen = 1 + StringPtr - StringHdr + 8 + 1;\r
+ ConfigAltHdr = AllocateZeroPool ( MaxLen * sizeof (CHAR16));\r
+ if (ConfigAltHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StrCpyS (ConfigAltHdr, MaxLen, L"&");\r
+ StrnCatS (ConfigAltHdr, MaxLen, StringHdr, StringPtr - StringHdr);\r
+ StrCatS (ConfigAltHdr, MaxLen, L"&ALTCFG=");\r
+\r
+ //\r
+ // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
+ //\r
+ while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
+ StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
+ if (*StringPtr == L'\0') {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free the allocated ConfigAltHdr string\r
+ //\r
+ FreePool (ConfigAltHdr);\r
+ if (*StringPtr == L'\0') {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Find &GUID as the next ConfigHdr\r
+ //\r
+ StringPtr = StrStr (StringPtr, L"&GUID");\r
+ if (StringPtr == NULL) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Skip char '&'\r
+ //\r
+ StringPtr ++;\r
+ }\r
+\r
+Done:\r
+ if (VarGuid != NULL) {\r
+ FreePool (VarGuid);\r
+ }\r
+\r
+ if (VarName != NULL) {\r
+ FreePool (VarName);\r
+ }\r
+\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
+\r
+ if (ConfigAltResp != NULL) {\r
+ FreePool (ConfigAltResp);\r
+ }\r
+\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Validate the current configuration by parsing HII form IFR opcode.\r
+\r
+ NULL request string support depends on the ExportConfig interface of\r
+ HiiConfigRouting protocol in UEFI specification.\r
+\r
+ @param Request A null-terminated Unicode string in\r
+ <MultiConfigRequest> format. It can be NULL.\r
+ If it is NULL, all current configuration for the\r
+ entirety of the current HII database will be validated.\r
+\r
+ @retval TRUE Current configuration is valid.\r
+ @retval FALSE Current configuration is invalid.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiValidateSettings (\r
+ IN CONST EFI_STRING Request OPTIONAL\r
+ )\r
+{\r
+ return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);\r
+}\r
+\r
+/**\r
+ Reset the default value specified by DefaultId to the driver\r
+ configuration got by Request string.\r
+\r
+ NULL request string support depends on the ExportConfig interface of\r
+ HiiConfigRouting protocol in UEFI specification.\r
+\r
+ @param Request A null-terminated Unicode string in\r
+ <MultiConfigRequest> format. It can be NULL.\r
+ If it is NULL, all configuration for the\r
+ entirety of the current HII database will be reset.\r
+ @param DefaultId Specifies the type of defaults to retrieve.\r
+\r
+ @retval TRUE The default value is set successfully.\r
+ @retval FALSE The default value can't be found and set.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiSetToDefaults (\r
+ IN CONST EFI_STRING Request, OPTIONAL\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);\r
+}\r
+\r
+/**\r
+ Determines if two values in config strings match.\r
+\r
+ Compares the substring between StartSearchString and StopSearchString in\r
+ FirstString to the substring between StartSearchString and StopSearchString\r
+ in SecondString. If the two substrings match, then TRUE is returned. If the\r
+ two substrings do not match, then FALSE is returned.\r
+\r
+ If FirstString is NULL, then ASSERT().\r
+ If SecondString is NULL, then ASSERT().\r
+ If StartSearchString is NULL, then ASSERT().\r
+ If StopSearchString is NULL, then ASSERT().\r
+\r
+ @param FirstString Pointer to the first Null-terminated Unicode string.\r
+ @param SecondString Pointer to the second Null-terminated Unicode string.\r
+ @param StartSearchString Pointer to the Null-terminated Unicode string that\r
+ marks the start of the value string to compare.\r
+ @param StopSearchString Pointer to the Null-terminated Unicode string that\r
+ marks the end of the value string to compare.\r
+\r
+ @retval FALSE StartSearchString is not present in FirstString.\r
+ @retval FALSE StartSearchString is not present in SecondString.\r
+ @retval FALSE StopSearchString is not present in FirstString.\r
+ @retval FALSE StopSearchString is not present in SecondString.\r
+ @retval FALSE The length of the substring in FirstString is not the\r
+ same length as the substring in SecondString.\r
+ @retval FALSE The value string in FirstString does not matche the\r
+ value string in SecondString.\r
+ @retval TRUE The value string in FirstString matches the value\r
+ string in SecondString.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalHiiCompareSubString (\r
+ IN CHAR16 *FirstString,\r
+ IN CHAR16 *SecondString,\r
+ IN CHAR16 *StartSearchString,\r
+ IN CHAR16 *StopSearchString\r
+ )\r
+{\r
+ CHAR16 *EndFirstString;\r
+ CHAR16 *EndSecondString;\r
+\r
+ ASSERT (FirstString != NULL);\r
+ ASSERT (SecondString != NULL);\r
+ ASSERT (StartSearchString != NULL);\r
+ ASSERT (StopSearchString != NULL);\r
+\r
+ FirstString = StrStr (FirstString, StartSearchString);\r
+ if (FirstString == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ SecondString = StrStr (SecondString, StartSearchString);\r
+ if (SecondString == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ EndFirstString = StrStr (FirstString, StopSearchString);\r
+ if (EndFirstString == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ EndSecondString = StrStr (SecondString, StopSearchString);\r
+ if (EndSecondString == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);\r
+}\r
+\r
+/**\r
+ Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.\r
+\r
+ If ConfigHdr is NULL, then ASSERT().\r
+\r
+ @param[in] ConfigHdr Either <ConfigRequest> or <ConfigResp>.\r
+ @param[in] Guid GUID of the storage.\r
+ @param[in] Name NAME of the storage.\r
+\r
+ @retval TRUE Routing information matches <ConfigHdr>.\r
+ @retval FALSE Routing information does not match <ConfigHdr>.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiIsConfigHdrMatch (\r
+ IN CONST EFI_STRING ConfigHdr,\r
+ IN CONST EFI_GUID *Guid, OPTIONAL\r
+ IN CONST CHAR16 *Name OPTIONAL\r
+ )\r
+{\r
+ EFI_STRING CompareConfigHdr;\r
+ BOOLEAN Result;\r
+\r
+ ASSERT (ConfigHdr != NULL);\r
+\r
+ //\r
+ // Use Guid and Name to generate a <ConfigHdr> string\r
+ //\r
+ CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);\r
+ if (CompareConfigHdr == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ Result = TRUE;\r
+ if (Guid != NULL) {\r
+ //\r
+ // Compare GUID value strings\r
+ //\r
+ Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");\r
+ }\r
+\r
+ if (Result && Name != NULL) {\r
+ //\r
+ // Compare NAME value strings\r
+ //\r
+ Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");\r
+ }\r
+\r
+ //\r
+ // Free the <ConfigHdr> string\r
+ //\r
+ FreePool (CompareConfigHdr);\r
+\r
+ return Result;\r
+}\r
+\r
+/**\r
+ Retrieves uncommitted data from the Form Browser and converts it to a binary\r
+ buffer.\r
+\r
+ @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
+ parameter that may be NULL.\r
+ @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
+ is an optional parameter that may be NULL.\r
+ @param[in] BufferSize Length in bytes of buffer to hold retrieved data.\r
+ @param[out] Buffer Buffer of data to be updated.\r
+\r
+ @retval FALSE The uncommitted data could not be retrieved.\r
+ @retval TRUE The uncommitted data was retrieved.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiGetBrowserData (\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName, OPTIONAL\r
+ IN UINTN BufferSize,\r
+ OUT UINT8 *Buffer\r
+ )\r
+{\r
+ EFI_STRING ResultsData;\r
+ UINTN Size;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STATUS Status;\r
+ CHAR16 *Progress;\r
+\r
+ //\r
+ // Retrieve the results data from the Browser Callback\r
+ //\r
+ ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
+ if (ResultsData == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'\r
+ //\r
+ Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);\r
+ Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);\r
+ ConfigResp = AllocateZeroPool (Size);\r
+ UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);\r
+\r
+ //\r
+ // Free the allocated buffer\r
+ //\r
+ FreePool (ResultsData);\r
+ if (ConfigResp == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Convert <ConfigResp> to a buffer\r
+ //\r
+ Status = gHiiConfigRouting->ConfigToBlock (\r
+ gHiiConfigRouting,\r
+ ConfigResp,\r
+ Buffer,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ //\r
+ // Free the allocated buffer\r
+ //\r
+ FreePool (ConfigResp);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Updates uncommitted data in the Form Browser.\r
+\r
+ If Buffer is NULL, then ASSERT().\r
+\r
+ @param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional\r
+ parameter that may be NULL.\r
+ @param[in] VariableName Pointer to a Null-terminated Unicode string. This\r
+ is an optional parameter that may be NULL.\r
+ @param[in] BufferSize Length, in bytes, of Buffer.\r
+ @param[in] Buffer Buffer of data to commit.\r
+ @param[in] RequestElement An optional field to specify which part of the\r
+ buffer data will be send back to Browser. If NULL,\r
+ the whole buffer of data will be committed to\r
+ Browser.\r
+ <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
+\r
+ @retval FALSE The uncommitted data could not be updated.\r
+ @retval TRUE The uncommitted data was updated.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiSetBrowserData (\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName, OPTIONAL\r
+ IN UINTN BufferSize,\r
+ IN CONST UINT8 *Buffer,\r
+ IN CONST CHAR16 *RequestElement OPTIONAL\r
+ )\r
+{\r
+ UINTN Size;\r
+ EFI_STRING ConfigRequest;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING ResultsData;\r
+\r
+ ASSERT (Buffer != NULL);\r
+\r
+ //\r
+ // Construct <ConfigRequest>\r
+ //\r
+ if (RequestElement == NULL) {\r
+ //\r
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+ //\r
+ Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);\r
+ ConfigRequest = AllocateZeroPool (Size);\r
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);\r
+ } else {\r
+ //\r
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+ // followed by <RequestElement> followed by a Null-terminator\r
+ //\r
+ Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);\r
+ Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);\r
+ ConfigRequest = AllocateZeroPool (Size);\r
+ UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);\r
+ }\r
+ if (ConfigRequest == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Convert <ConfigRequest> to <ConfigResp>\r
+ //\r
+ ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);\r
+ FreePool (ConfigRequest);\r
+ if (ConfigResp == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Set data in the uncommitted browser state information\r
+ //\r
+ ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);\r
+ FreePool (ConfigResp);\r
+\r
+ return (BOOLEAN)(ResultsData != NULL);\r
+}\r
+\r
+/////////////////////////////////////////\r
+/////////////////////////////////////////\r
+/// IFR Functions\r
+/////////////////////////////////////////\r
+/////////////////////////////////////////\r
+\r
+#define HII_LIB_OPCODE_ALLOCATION_SIZE 0x200\r
+\r
+typedef struct {\r
+ UINT8 *Buffer;\r
+ UINTN BufferSize;\r
+ UINTN Position;\r
+} HII_LIB_OPCODE_BUFFER;\r
+\r
+///\r
+/// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {\r
+ 1, // EFI_IFR_TYPE_NUM_SIZE_8\r
+ 2, // EFI_IFR_TYPE_NUM_SIZE_16\r
+ 4, // EFI_IFR_TYPE_NUM_SIZE_32\r
+ 8, // EFI_IFR_TYPE_NUM_SIZE_64\r
+ 1, // EFI_IFR_TYPE_BOOLEAN\r
+ 3, // EFI_IFR_TYPE_TIME\r
+ 4, // EFI_IFR_TYPE_DATE\r
+ 2 // EFI_IFR_TYPE_STRING\r
+};\r
+\r
+/**\r
+ Allocates and returns a new OpCode Handle. OpCode Handles must be freed with\r
+ HiiFreeOpCodeHandle().\r
+\r
+ @retval NULL There are not enough resources to allocate a new OpCode Handle.\r
+ @retval Other A new OpCode handle.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+HiiAllocateOpCodeHandle (\r
+ VOID\r
+ )\r
+{\r
+ HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
+\r
+ OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));\r
+ if (OpCodeBuffer == NULL) {\r
+ return NULL;\r
+ }\r
+ OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);\r
+ if (OpCodeBuffer->Buffer == NULL) {\r
+ FreePool (OpCodeBuffer);\r
+ return NULL;\r
+ }\r
+ OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;\r
+ OpCodeBuffer->Position = 0;\r
+ return (VOID *)OpCodeBuffer;\r
+}\r
+\r
+/**\r
+ Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().\r
+ When an OpCode Handle is freed, all of the opcodes associated with the OpCode\r
+ Handle are also freed.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiFreeOpCodeHandle (\r
+ VOID *OpCodeHandle\r
+ )\r
+{\r
+ HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
+\r
+ ASSERT (OpCodeHandle != NULL);\r
+\r
+ OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
+ if (OpCodeBuffer->Buffer != NULL) {\r
+ FreePool (OpCodeBuffer->Buffer);\r
+ }\r
+ FreePool (OpCodeBuffer);\r
+}\r
+\r
+/**\r
+ Internal function gets the current position of opcode buffer.\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+\r
+ @return Current position of opcode buffer.\r
+**/\r
+UINTN\r
+EFIAPI\r
+InternalHiiOpCodeHandlePosition (\r
+ IN VOID *OpCodeHandle\r
+ )\r
+{\r
+ return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Position;\r
+}\r
+\r
+/**\r
+ Internal function gets the start pointer of opcode buffer.\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+\r
+ @return Pointer to the opcode buffer base.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiOpCodeHandleBuffer (\r
+ IN VOID *OpCodeHandle\r
+ )\r
+{\r
+ return ((HII_LIB_OPCODE_BUFFER *)OpCodeHandle)->Buffer;\r
+}\r
+\r
+/**\r
+ Internal function reserves the enough buffer for current opcode.\r
+ When the buffer is not enough, Opcode buffer will be extended.\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] Size Size of current opcode.\r
+\r
+ @return Pointer to the current opcode.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiGrowOpCodeHandle (\r
+ IN VOID *OpCodeHandle,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ HII_LIB_OPCODE_BUFFER *OpCodeBuffer;\r
+ UINT8 *Buffer;\r
+\r
+ ASSERT (OpCodeHandle != NULL);\r
+\r
+ OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
+ if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {\r
+ Buffer = ReallocatePool (\r
+ OpCodeBuffer->BufferSize,\r
+ OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
+ OpCodeBuffer->Buffer\r
+ );\r
+ ASSERT (Buffer != NULL);\r
+ OpCodeBuffer->Buffer = Buffer;\r
+ OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
+ }\r
+ Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;\r
+ OpCodeBuffer->Position += Size;\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Internal function creates opcode based on the template opcode.\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] OpCodeTemplate Pointer to the template buffer of opcode.\r
+ @param[in] OpCode OpCode IFR value.\r
+ @param[in] OpCodeSize Size of opcode.\r
+ @param[in] ExtensionSize Size of extended opcode.\r
+ @param[in] Scope Scope bit of opcode.\r
+\r
+ @return Pointer to the current opcode with opcode data.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiCreateOpCodeExtended (\r
+ IN VOID *OpCodeHandle,\r
+ IN VOID *OpCodeTemplate,\r
+ IN UINT8 OpCode,\r
+ IN UINTN OpCodeSize,\r
+ IN UINTN ExtensionSize,\r
+ IN UINT8 Scope\r
+ )\r
+{\r
+ EFI_IFR_OP_HEADER *Header;\r
+ UINT8 *Buffer;\r
+\r
+ ASSERT (OpCodeTemplate != NULL);\r
+ ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);\r
+\r
+ Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;\r
+ Header->OpCode = OpCode;\r
+ Header->Scope = Scope;\r
+ Header->Length = (UINT8)(OpCodeSize + ExtensionSize);\r
+ Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);\r
+ return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);\r
+}\r
+\r
+/**\r
+ Internal function creates opcode based on the template opcode for the normal opcode.\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] OpCodeTemplate Pointer to the template buffer of opcode.\r
+ @param[in] OpCode OpCode IFR value.\r
+ @param[in] OpCodeSize Size of opcode.\r
+\r
+ @return Pointer to the current opcode with opcode data.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiCreateOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN VOID *OpCodeTemplate,\r
+ IN UINT8 OpCode,\r
+ IN UINTN OpCodeSize\r
+ )\r
+{\r
+ return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);\r
+}\r
+\r
+/**\r
+ Append raw opcodes to an OpCodeHandle.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If RawBuffer is NULL, then ASSERT();\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] RawBuffer Buffer of opcodes to append.\r
+ @param[in] RawBufferSize The size, in bytes, of Buffer.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the appended opcodes.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateRawOpCodes (\r
+ IN VOID *OpCodeHandle,\r
+ IN UINT8 *RawBuffer,\r
+ IN UINTN RawBufferSize\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+\r
+ ASSERT (RawBuffer != NULL);\r
+\r
+ Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);\r
+ return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);\r
+}\r
+\r
+/**\r
+ Append opcodes from one OpCode Handle to another OpCode handle.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If RawOpCodeHandle is NULL, then ASSERT();\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] RawOpCodeHandle Handle to the buffer of opcodes.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the appended opcodes.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiAppendOpCodes (\r
+ IN VOID *OpCodeHandle,\r
+ IN VOID *RawOpCodeHandle\r
+ )\r
+{\r
+ HII_LIB_OPCODE_BUFFER *RawOpCodeBuffer;\r
+\r
+ ASSERT (RawOpCodeHandle != NULL);\r
+\r
+ RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
+ return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_END_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateEndOpCode (\r
+ IN VOID *OpCodeHandle\r
+ )\r
+{\r
+ EFI_IFR_END OpCode;\r
+\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If Type is invalid, then ASSERT().\r
+ If Flags is invalid, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] StringId StringId for the option\r
+ @param[in] Flags Flags for the option\r
+ @param[in] Type Type for the option\r
+ @param[in] Value Value for the option\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateOneOfOptionOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN UINT16 StringId,\r
+ IN UINT8 Flags,\r
+ IN UINT8 Type,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ EFI_IFR_ONE_OF_OPTION OpCode;\r
+\r
+ ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Option = StringId;\r
+ OpCode.Flags = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
+ OpCode.Type = Type;\r
+ CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
+\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]);\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_DEFAULT_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If Type is invalid, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] DefaultId DefaultId for the default\r
+ @param[in] Type Type for the default\r
+ @param[in] Value Value for the default\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateDefaultOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN UINT16 DefaultId,\r
+ IN UINT8 Type,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ EFI_IFR_DEFAULT OpCode;\r
+\r
+ ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Type = Type;\r
+ OpCode.DefaultId = DefaultId;\r
+ CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
+\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]);\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_GUID opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If Guid is NULL, then ASSERT().\r
+ If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] Guid Pointer to EFI_GUID of this guided opcode.\r
+ @param[in] GuidOpCode Pointer to an EFI_IFR_GUID opcode. This is an\r
+ optional parameter that may be NULL. If this\r
+ parameter is NULL, then the GUID extension\r
+ region of the created opcode is filled with zeros.\r
+ If this parameter is not NULL, then the GUID\r
+ extension region of GuidData will be copied to\r
+ the GUID extension region of the created opcode.\r
+ @param[in] OpCodeSize The size, in bytes, of created opcode. This value\r
+ must be >= sizeof(EFI_IFR_GUID).\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateGuidOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN CONST VOID *GuidOpCode, OPTIONAL\r
+ IN UINTN OpCodeSize\r
+ )\r
+{\r
+ EFI_IFR_GUID OpCode;\r
+ EFI_IFR_GUID *OpCodePointer;\r
+\r
+ ASSERT (Guid != NULL);\r
+ ASSERT (OpCodeSize >= sizeof (OpCode));\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);\r
+\r
+ OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (\r
+ OpCodeHandle,\r
+ &OpCode,\r
+ EFI_IFR_GUID_OP,\r
+ sizeof (OpCode),\r
+ OpCodeSize - sizeof (OpCode),\r
+ 0\r
+ );\r
+ if (OpCodePointer != NULL && GuidOpCode != NULL) {\r
+ CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));\r
+ }\r
+ return (UINT8 *)OpCodePointer;\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_ACTION_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] QuestionConfig String ID for configuration\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateActionOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN EFI_STRING_ID QuestionConfig\r
+ )\r
+{\r
+ EFI_IFR_ACTION OpCode;\r
+\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.QuestionConfig = QuestionConfig;\r
+\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+ Create EFI_IFR_SUBTITLE_OP opcode.\r
+\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in Flags, then ASSERT().\r
+ If Scope > 1, then ASSERT().\r
+\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] Flags Subtitle opcode flags\r
+ @param[in] Scope 1 if this opcpde is the beginning of a new scope.\r
+ 0 if this opcode is within the current scope.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateSubTitleOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 Flags,\r
+ IN UINT8 Scope\r
+ )\r
+{\r
+ EFI_IFR_SUBTITLE OpCode;\r
+\r
+ ASSERT (Scope <= 1);\r
+ ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);\r
\r
-#include "InternalHiiLib.h"\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Statement.Prompt = Prompt;\r
+ OpCode.Statement.Help = Help;\r
+ OpCode.Flags = Flags;\r
\r
-CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt = NULL;\r
-CONST EFI_HII_STRING_PROTOCOL *mHiiStringProt = NULL;\r
+ return InternalHiiCreateOpCodeExtended (\r
+ OpCodeHandle,\r
+ &OpCode,\r
+ EFI_IFR_SUBTITLE_OP,\r
+ sizeof (OpCode),\r
+ 0,\r
+ Scope\r
+ );\r
+}\r
\r
/**\r
- This function locate Hii relative protocols for later usage.\r
- \r
- The constructor function caches the protocol pointer of HII Database Protocol\r
- and Hii String Protocol.\r
- \r
- It will ASSERT() if either of the protocol can't be located.\r
+ Create EFI_IFR_REF_OP opcode.\r
\r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
\r
- @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] FormId Destination Form ID\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] QuestionId Question ID\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_STATUS\r
+UINT8 *\r
EFIAPI\r
-HiiLibConstructor (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+HiiCreateGotoOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_FORM_ID FormId,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN EFI_QUESTION_ID QuestionId\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_IFR_REF OpCode;\r
\r
- Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt);\r
- ASSERT_EFI_ERROR (Status);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
- Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt);\r
- ASSERT_EFI_ERROR (Status);\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.FormId = FormId;\r
\r
- return EFI_SUCCESS;\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\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
+ Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.\r
\r
- #pragma pack (push, 1)\r
- typedef struct {\r
- UINT32 BinaryLength;\r
- EFI_HII_PACKAGE_HEADER PackageHeader;\r
- } EDKII_AUTOGEN_PACKAGES_HEADER;\r
- #pragma pack (pop)\r
+ When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.\r
+ When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.\r
+ When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.\r
+ When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.\r
\r
- If there is not enough resource for the new package list,\r
- the function will ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then 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
+ @param[in] OpCodeHandle The handle to the buffer of opcodes.\r
+ @param[in] RefFormId The Destination Form ID.\r
+ @param[in] Prompt The string ID for Prompt.\r
+ @param[in] Help The string ID for Help.\r
+ @param[in] QuestionFlags The flags in Question Header\r
+ @param[in] QuestionId Question ID.\r
+ @param[in] RefQuestionId The question on the form to which this link is referring.\r
+ If its value is zero, then the link refers to the top of the form.\r
+ @param[in] RefFormSetId The form set to which this link is referring. If its value is NULL, and RefDevicePath is\r
+ zero, then the link is to the current form set.\r
+ @param[in] RefDevicePath The string identifier that specifies the string containing the text representation of\r
+ the device path to which the form set containing the form specified by FormId.\r
+ If its value is zero, then the link refers to the current page.\r
\r
- @return The pointer to the package list header.\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\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
+UINT8 *\r
+EFIAPI\r
+HiiCreateGotoExOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_FORM_ID RefFormId,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_QUESTION_ID RefQuestionId,\r
+ IN EFI_GUID *RefFormSetId, OPTIONAL\r
+ IN EFI_STRING_ID RefDevicePath\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
+ EFI_IFR_REF4 OpCode;\r
+ UINTN OpCodeSize;\r
\r
- MarkerBackup = Marker;\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
- //\r
- // Count the length of the final package list.\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
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.FormId = RefFormId;\r
+ OpCode.QuestionId = RefQuestionId;\r
+ OpCode.DevicePath = RefDevicePath;\r
+ if (RefFormSetId != NULL) {\r
+ CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId));\r
}\r
\r
//\r
- // Include the length of EFI_HII_PACKAGE_END\r
- //\r
- PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
- PackageListHeader = AllocateZeroPool (PackageListLength);\r
- ASSERT (PackageListHeader != NULL);\r
- \r
- CopyGuid (&PackageListHeader->PackageListGuid, GuidId);\r
- PackageListHeader->PackageLength = PackageListLength;\r
-\r
- PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
-\r
- Marker = MarkerBackup;\r
- //\r
- // Prepare the final package list.\r
+ // Cacluate OpCodeSize based on the input Ref value.\r
+ // Try to use the small OpCode to save size.\r
//\r
- for (Index = 0; Index < NumberOfPackages; Index++) {\r
- PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
- //\r
- // CopyMem is used for UINT32 to cover the unaligned address access.\r
- //\r
- CopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
- PackageLength -= sizeof (UINT32);\r
- PackageArray += sizeof (UINT32);\r
- CopyMem (PackageListData, PackageArray, PackageLength);\r
- PackageListData += PackageLength;\r
+ OpCodeSize = sizeof (EFI_IFR_REF);\r
+ if (RefDevicePath != 0) {\r
+ OpCodeSize = sizeof (EFI_IFR_REF4);\r
+ } else if (RefFormSetId != NULL) {\r
+ OpCodeSize = sizeof (EFI_IFR_REF3);\r
+ } else if (RefQuestionId != 0) {\r
+ OpCodeSize = sizeof (EFI_IFR_REF2);\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
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);\r
}\r
\r
/**\r
- Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
+ Create EFI_IFR_CHECKBOX_OP opcode.\r
\r
- If GuidId is NULL, then ASSERT.\r
- If not enough resource to complete the operation, then ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in CheckBoxFlags, then ASSERT().\r
\r
- @param NumberOfPackages Number of packages.\r
- @param GuidId Package GUID.\r
- @param ... Variable argument list for packages to be assembled.\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] CheckBoxFlags Flags for checkbox opcode\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
\r
- @return Pointer of EFI_HII_PACKAGE_LIST_HEADER.\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_HII_PACKAGE_LIST_HEADER *\r
+UINT8 *\r
EFIAPI\r
-HiiLibPreparePackageList (\r
- IN UINTN NumberOfPackages,\r
- IN CONST EFI_GUID *GuidId,\r
- ...\r
+HiiCreateCheckBoxOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 CheckBoxFlags,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
)\r
{\r
- EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
- VA_LIST Marker;\r
+ EFI_IFR_CHECKBOX OpCode;\r
+ UINTN Position;\r
\r
- ASSERT (GuidId != NULL);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
- VA_START (Marker, GuidId);\r
- PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
- VA_END (Marker);\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = CheckBoxFlags;\r
\r
- return PackageListHeader;\r
-}\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));\r
+ }\r
\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\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 through HiiHandle.\r
+ Create EFI_IFR_NUMERIC_OP opcode.\r
\r
- If HiiHandle is NULL, then ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in NumericFlags, 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
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] NumericFlags Flags for numeric opcode\r
+ @param[in] Minimum Numeric minimum value\r
+ @param[in] Maximum Numeric maximum value\r
+ @param[in] Step Numeric step for edit\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\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
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_STATUS\r
+UINT8 *\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
+HiiCreateNumericOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 NumericFlags,\r
+ IN UINT64 Minimum,\r
+ IN UINT64 Maximum,\r
+ IN UINT64 Step,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
)\r
{\r
- VA_LIST Args;\r
- EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
- EFI_STATUS Status;\r
+ EFI_IFR_NUMERIC OpCode;\r
+ UINTN Position;\r
+ UINTN Length;\r
\r
- ASSERT (HiiHandle != NULL);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
\r
- VA_START (Args, HiiHandle);\r
- PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
+ Length = 0;\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = NumericFlags;\r
\r
- Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
- if (HiiHandle != NULL) {\r
- if (EFI_ERROR (Status)) {\r
- *HiiHandle = NULL;\r
- }\r
+ switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ OpCode.data.u8.MinValue = (UINT8)Minimum;\r
+ OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
+ OpCode.data.u8.Step = (UINT8)Step;\r
+ Length = 3;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ OpCode.data.u16.MinValue = (UINT16)Minimum;\r
+ OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
+ OpCode.data.u16.Step = (UINT16)Step;\r
+ Length = 6;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ OpCode.data.u32.MinValue = (UINT32)Minimum;\r
+ OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
+ OpCode.data.u32.Step = (UINT32)Step;\r
+ Length = 12;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ OpCode.data.u64.MinValue = Minimum;\r
+ OpCode.data.u64.MaxValue = Maximum;\r
+ OpCode.data.u64.Step = Step;\r
+ Length = 24;\r
+ break;\r
}\r
\r
- FreePool (PackageListHeader);\r
- VA_END (Args);\r
- \r
- return Status;\r
+ Length += OFFSET_OF (EFI_IFR_NUMERIC, data);\r
+\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length);\r
+ }\r
+\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
/**\r
- Removes a package list from the default HII database.\r
+ Create EFI_IFR_STRING_OP opcode.\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
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in StringFlags, 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
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] StringFlags Flags for string opcode\r
+ @param[in] MinSize String minimum length\r
+ @param[in] MaxSize String maximum length\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
+\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-VOID\r
+UINT8 *\r
EFIAPI\r
-HiiLibRemovePackages (\r
- IN EFI_HII_HANDLE HiiHandle\r
+HiiCreateStringOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 StringFlags,\r
+ IN UINT8 MinSize,\r
+ IN UINT8 MaxSize,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- ASSERT (IsHiiHandleRegistered (HiiHandle));\r
+ EFI_IFR_STRING OpCode;\r
+ UINTN Position;\r
\r
- Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.MinSize = MinSize;\r
+ OpCode.MaxSize = MaxSize;\r
+ OpCode.Flags = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);\r
+\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));\r
+ }\r
\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\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
+ Create EFI_IFR_ONE_OF_OP opcode.\r
\r
- If HandleBufferLength is NULL, then ASSERT.\r
- If HiiHandleBuffer is NULL, then ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in OneOfFlags, 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
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] OneOfFlags Flags for oneof opcode\r
+ @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
\r
- @retval EFI_SUCCESS Get an array of Hii Handles successfully.\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_STATUS\r
+UINT8 *\r
EFIAPI\r
-HiiLibGetHiiHandles (\r
- IN OUT UINTN *HandleBufferLength,\r
- OUT EFI_HII_HANDLE **HiiHandleBuffer\r
+HiiCreateOneOfOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 OneOfFlags,\r
+ IN VOID *OptionsOpCodeHandle,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_IFR_ONE_OF OpCode;\r
+ UINTN Position;\r
+ UINTN Length;\r
\r
- ASSERT (HandleBufferLength != NULL);\r
- ASSERT (HiiHandleBuffer != NULL);\r
+ ASSERT (OptionsOpCodeHandle != NULL);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
\r
- *HandleBufferLength = 0;\r
- *HiiHandleBuffer = NULL;\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = OneOfFlags;\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
- HandleBufferLength,\r
- *HiiHandleBuffer\r
- );\r
- \r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- *HiiHandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
- ASSERT (*HiiHandleBuffer != NULL);\r
- Status = mHiiDatabaseProt->ListPackageLists (\r
- mHiiDatabaseProt,\r
- EFI_HII_PACKAGE_TYPE_ALL,\r
- NULL,\r
- HandleBufferLength,\r
- *HiiHandleBuffer\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- FreePool (*HiiHandleBuffer);\r
- *HiiHandleBuffer = NULL;\r
- }\r
- }\r
+ Length = OFFSET_OF (EFI_IFR_ONE_OF, data);\r
+ Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3;\r
\r
- return Status;\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
+ if (DefaultsOpCodeHandle != NULL) {\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ }\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
/**\r
- Extract Hii package list GUID for given HII handle.\r
+ Create EFI_IFR_ORDERED_LIST_OP opcode.\r
\r
- If HiiHandle could not be found in the default HII database, then ASSERT.\r
- If Guid is NULL, then ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in OrderedListFlags, then ASSERT().\r
\r
- @param Handle Hii handle\r
- @param Guid Package list GUID\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] OrderedListFlags Flags for ordered list opcode\r
+ @param[in] DataType Type for option value\r
+ @param[in] MaxContainers Maximum count for options in this ordered list\r
+ @param[in] OptionsOpCodeHandle Handle for a buffer of ONE_OF_OPTION opcodes.\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
\r
- @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_STATUS\r
+UINT8 *\r
EFIAPI\r
-HiiLibExtractGuidFromHiiHandle (\r
- IN EFI_HII_HANDLE Handle,\r
- OUT EFI_GUID *Guid\r
+HiiCreateOrderedListOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId,\r
+ IN UINT16 VarOffset,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 OrderedListFlags,\r
+ IN UINT8 DataType,\r
+ IN UINT8 MaxContainers,\r
+ IN VOID *OptionsOpCodeHandle,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\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
+ EFI_IFR_ORDERED_LIST OpCode;\r
+ UINTN Position;\r
\r
- //\r
- // Get HII PackageList\r
- //\r
- BufferSize = 0;\r
- HiiPackageList = NULL;\r
+ ASSERT (OptionsOpCodeHandle != NULL);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\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
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.MaxContainers = MaxContainers;\r
+ OpCode.Flags = OrderedListFlags;\r
\r
- Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- FreePool (HiiPackageList);\r
- return Status;\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
+ if (DefaultsOpCodeHandle != NULL) {\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
}\r
-\r
- //\r
- // Extract GUID\r
- //\r
- CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
-\r
- FreePool (HiiPackageList);\r
-\r
- return EFI_SUCCESS;\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
/**\r
- Find HII Handle in the default HII database associated with given Device Path.\r
+ Create EFI_IFR_TEXT_OP opcode.\r
\r
- If DevicePath is NULL, then ASSERT.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
\r
- @param DevicePath Device Path associated with the HII package list\r
- handle.\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] Prompt String ID for Prompt.\r
+ @param[in] Help String ID for Help.\r
+ @param[in] TextTwo String ID for TextTwo.\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
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_HII_HANDLE\r
+UINT8 *\r
EFIAPI\r
-HiiLibDevicePathToHiiHandle (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+HiiCreateTextOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN EFI_STRING_ID TextTwo\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
+ EFI_IFR_TEXT OpCode;\r
\r
- ASSERT (DevicePath != NULL);\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Statement.Prompt = Prompt;\r
+ OpCode.Statement.Help = Help;\r
+ OpCode.TextTwo = TextTwo;\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
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));\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
+ Create EFI_IFR_DATE_OP opcode.\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
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in DateFlags, then ASSERT().\r
\r
- if (DriverHandle == NULL) {\r
- return NULL;\r
- }\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID, optional. If DateFlags is not\r
+ QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair, optional. If DateFlags is not\r
+ QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] DateFlags Flags for date opcode\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
\r
- //\r
- // Retrieve all Hii Handles from HII database\r
- //\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
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
- if (EFI_ERROR (Status)) {\r
- FreePool (HiiHandles);\r
- return NULL;\r
- }\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateDateOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
+ IN UINT16 VarOffset, OPTIONAL\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 DateFlags,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
+ )\r
+{\r
+ EFI_IFR_DATE OpCode;\r
+ UINTN Position;\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
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+ ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);\r
+\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = DateFlags;\r
+\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));\r
}\r
\r
- FreePool (HiiHandles);\r
- return HiiHandle;\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
/**\r
- Exports the contents of one or all package lists in the HII database into a buffer.\r
-\r
- If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database, \r
- then ASSERT.\r
- If PackageListHeader is NULL, then ASSERT.\r
- If PackageListSize is NULL, then ASSERT.\r
+ Create EFI_IFR_TIME_OP opcode.\r
\r
- @param Handle The HII Handle.\r
- @param PackageListHeader A pointer to a buffer that will contain the results of \r
- the export function.\r
- @param PackageListSize On output, the length of the buffer that is required for the exported data.\r
+ If OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+ If any reserved bits are set in TimeFlags, then ASSERT().\r
\r
- @retval EFI_SUCCESS Package exported.\r
+ @param[in] OpCodeHandle Handle to the buffer of opcodes.\r
+ @param[in] QuestionId Question ID\r
+ @param[in] VarStoreId Storage ID, optional. If TimeFlags is not\r
+ QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] VarOffset Offset in Storage or String ID of the name (VarName)\r
+ for this name/value pair, optional. If TimeFlags is not\r
+ QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+ @param[in] Prompt String ID for Prompt\r
+ @param[in] Help String ID for Help\r
+ @param[in] QuestionFlags Flags in Question Header\r
+ @param[in] TimeFlags Flags for time opcode\r
+ @param[in] DefaultsOpCodeHandle Handle for a buffer of DEFAULT opcodes. This\r
+ is an optional parameter that may be NULL.\r
\r
- @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations.\r
+ @retval NULL There is not enough space left in Buffer to add the opcode.\r
+ @retval Other A pointer to the created opcode.\r
\r
**/\r
-EFI_STATUS \r
+UINT8 *\r
EFIAPI\r
-HiiLibExportPackageLists (\r
- IN EFI_HII_HANDLE Handle,\r
- OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,\r
- OUT UINTN *PackageListSize\r
+HiiCreateTimeOpCode (\r
+ IN VOID *OpCodeHandle,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN EFI_VARSTORE_ID VarStoreId, OPTIONAL\r
+ IN UINT16 VarOffset, OPTIONAL\r
+ IN EFI_STRING_ID Prompt,\r
+ IN EFI_STRING_ID Help,\r
+ IN UINT8 QuestionFlags,\r
+ IN UINT8 TimeFlags,\r
+ IN VOID *DefaultsOpCodeHandle OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;\r
+ EFI_IFR_TIME OpCode;\r
+ UINTN Position;\r
\r
- ASSERT (PackageListSize != NULL);\r
- ASSERT (PackageListHeader != NULL);\r
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+ ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);\r
\r
- if (Handle != NULL) {\r
- ASSERT (IsHiiHandleRegistered (Handle));\r
- }\r
-\r
- Size = 0;\r
- PackageListHdr = NULL;\r
- Status = mHiiDatabaseProt->ExportPackageLists (\r
- mHiiDatabaseProt,\r
- Handle,\r
- &Size,\r
- PackageListHdr\r
- );\r
- ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);\r
- \r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- PackageListHdr = AllocateZeroPool (Size);\r
- \r
- if (PackageListHeader == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- } else {\r
- Status = mHiiDatabaseProt->ExportPackageLists (\r
- mHiiDatabaseProt,\r
- Handle,\r
- &Size,\r
- PackageListHdr\r
- );\r
- }\r
- }\r
+ ZeroMem (&OpCode, sizeof (OpCode));\r
+ OpCode.Question.Header.Prompt = Prompt;\r
+ OpCode.Question.Header.Help = Help;\r
+ OpCode.Question.QuestionId = QuestionId;\r
+ OpCode.Question.VarStoreId = VarStoreId;\r
+ OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+ OpCode.Question.Flags = QuestionFlags;\r
+ OpCode.Flags = TimeFlags;\r
\r
- if (!EFI_ERROR (Status)) {\r
- *PackageListHeader = PackageListHdr;\r
- *PackageListSize = Size;\r
- } else {\r
- FreePool (PackageListHdr);\r
+ if (DefaultsOpCodeHandle == NULL) {\r
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));\r
}\r
\r
- return Status;\r
+ Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+ InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);\r
+ InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+ HiiCreateEndOpCode (OpCodeHandle);\r
+ return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
}\r
\r
/**\r
- \r
- This function returns a list of the package handles of the \r
- specified type that are currently active in the HII database. The \r
- pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package \r
- handles to be listed.\r
-\r
- If HandleBufferLength is NULL, then ASSERT.\r
- If HandleBuffer is NULL, the ASSERT.\r
- If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is\r
- NULL, then ASSERT.\r
- If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not\r
- NULL, then ASSERT.\r
- \r
- \r
- @param PackageType Specifies the package type of the packages\r
- to list or EFI_HII_PACKAGE_TYPE_ALL for\r
- all packages to be listed.\r
- \r
- @param PackageGuid If PackageType is\r
- EFI_HII_PACKAGE_TYPE_GUID, then this is\r
- the pointer to the GUID which must match\r
- the Guid field of\r
- EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it\r
- must be NULL.\r
- \r
- @param HandleBufferLength On output, the length of the handle buffer\r
- that is required for the handles found.\r
-\r
- @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned.\r
- The caller is responcible to free this pointer allocated.\r
-\r
- @retval EFI_SUCCESS The matching handles are outputed successfully.\r
- HandleBufferLength is updated with the actual length.\r
- @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation.\r
- @retval EFI_NOT_FOUND No matching handle could not be found in database.\r
+ This is the internal worker function to update the data in\r
+ a form specified by FormSetGuid, FormId and Label.\r
+\r
+ @param[in] FormSetGuid The optional Formset GUID.\r
+ @param[in] FormId The Form ID.\r
+ @param[in] Package The package header.\r
+ @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR\r
+ opcodes to be inserted or replaced in the form.\r
+ @param[in] OpCodeBufferEnd An OpCcode buffer that contains the IFR opcode\r
+ that marks the end of a replace operation in the form.\r
+ @param[out] TempPackage The resultant package.\r
+\r
+ @retval EFI_SUCCESS The function completes successfully.\r
+ @retval EFI_NOT_FOUND The updated opcode or endopcode is not found.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HiiLibListPackageLists (\r
- IN UINT8 PackageType,\r
- IN CONST EFI_GUID *PackageGuid,\r
- IN OUT UINTN *HandleBufferLength,\r
- OUT EFI_HII_HANDLE **HandleBuffer\r
+InternalHiiUpdateFormPackageData (\r
+ IN EFI_GUID *FormSetGuid, OPTIONAL\r
+ IN EFI_FORM_ID FormId,\r
+ IN EFI_HII_PACKAGE_HEADER *Package,\r
+ IN HII_LIB_OPCODE_BUFFER *OpCodeBufferStart,\r
+ IN HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd, OPTIONAL\r
+ OUT EFI_HII_PACKAGE_HEADER *TempPackage\r
)\r
{\r
- EFI_STATUS Status;\r
- \r
- ASSERT (HandleBufferLength != NULL);\r
- ASSERT (HandleBuffer != NULL);\r
- \r
- *HandleBufferLength = 0;\r
- *HandleBuffer = NULL;\r
-\r
- if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {\r
- ASSERT (PackageGuid != NULL);\r
- } else {\r
- ASSERT (PackageGuid == NULL);\r
- }\r
+ UINTN AddSize;\r
+ UINT8 *BufferPos;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINTN Offset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_IFR_OP_HEADER *UpdateIfrOpHdr;\r
+ BOOLEAN GetFormSet;\r
+ BOOLEAN GetForm;\r
+ BOOLEAN Updated;\r
+ UINTN UpdatePackageLength;\r
+\r
+ CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ BufferPos = (UINT8 *) (TempPackage + 1);\r
+\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
+ GetForm = FALSE;\r
+ Updated = FALSE;\r
+\r
+ while (Offset < PackageHeader.Length) {\r
+ CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
+ BufferPos += IfrOpHdr->Length;\r
+ UpdatePackageLength += IfrOpHdr->Length;\r
\r
- Status = mHiiDatabaseProt->ListPackageLists (\r
- mHiiDatabaseProt,\r
- PackageType,\r
- PackageGuid,\r
- HandleBufferLength,\r
- *HandleBuffer\r
- );\r
- if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
//\r
- // No packages is registered to UEFI HII Database, just return.\r
- // \r
+ // Find the matched FormSet and Form\r
//\r
- return Status;\r
+ if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {\r
+ if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
+ GetFormSet = TRUE;\r
+ } else {\r
+ GetFormSet = FALSE;\r
+ }\r
+ } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {\r
+ if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
+ GetForm = TRUE;\r
+ } else {\r
+ GetForm = FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // The matched Form is found, and Update data in this form\r
+ //\r
+ if (GetFormSet && GetForm) {\r
+ UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
+ if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
+ (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
+ //\r
+ // Remove the original data when End OpCode buffer exist.\r
+ //\r
+ if (OpCodeBufferEnd != NULL) {\r
+ Offset += IfrOpHdr->Length;\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
+ UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;\r
+ while (Offset < PackageHeader.Length) {\r
+ //\r
+ // Search the matched end opcode\r
+ //\r
+ if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
+ (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
+ break;\r
+ }\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Offset += IfrOpHdr->Length;\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
+ }\r
+\r
+ if (Offset >= PackageHeader.Length) {\r
+ //\r
+ // The end opcode is not found.\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Insert the updated data\r
+ //\r
+ AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;\r
+ CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);\r
+ BufferPos += OpCodeBufferStart->Position - AddSize;\r
+ UpdatePackageLength += OpCodeBufferStart->Position - AddSize;\r
+\r
+ if (OpCodeBufferEnd != NULL) {\r
+ //\r
+ // Add the end opcode\r
+ //\r
+ CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
+ BufferPos += IfrOpHdr->Length;\r
+ UpdatePackageLength += IfrOpHdr->Length;\r
+ }\r
+\r
+ //\r
+ // Copy the left package data.\r
+ //\r
+ Offset += IfrOpHdr->Length;\r
+ CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);\r
+ UpdatePackageLength += PackageHeader.Length - Offset;\r
+\r
+ //\r
+ // Set update flag\r
+ //\r
+ Updated = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Offset += IfrOpHdr->Length;\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
}\r
\r
- *HandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
- \r
- if (*HandleBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ if (!Updated) {\r
+ //\r
+ // The updated opcode buffer is not found.\r
+ //\r
+ return EFI_NOT_FOUND;\r
}\r
- \r
- return mHiiDatabaseProt->ListPackageLists (\r
- mHiiDatabaseProt,\r
- PackageType,\r
- PackageGuid,\r
- HandleBufferLength,\r
- *HandleBuffer\r
- );\r
- \r
+ //\r
+ // Update the package length.\r
+ //\r
+ PackageHeader.Length = (UINT32) UpdatePackageLength;\r
+ CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ return EFI_SUCCESS;\r
}\r
+\r
/**\r
- This function check if the Hii Handle is a valid handle registered\r
- in the HII database.\r
+ This function updates a form that has previously been registered with the HII\r
+ Database. This function will perform at most one update operation.\r
+\r
+ The form to update is specified by Handle, FormSetGuid, and FormId. Binary\r
+ comparisons of IFR opcodes are performed from the beginning of the form being\r
+ updated until an IFR opcode is found that exactly matches the first IFR opcode\r
+ specified by StartOpCodeHandle. The following rules are used to determine if\r
+ an insert, replace, or delete operation is performed.\r
+\r
+ 1) If no matches are found, then NULL is returned.\r
+ 2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes\r
+ from StartOpCodeHandle except the first opcode are inserted immediately after\r
+ the matching IFR opcode in the form to be updated.\r
+ 3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made\r
+ from the matching IFR opcode until an IFR opcode exactly matches the first\r
+ IFR opcode specified by EndOpCodeHandle. If no match is found for the first\r
+ IFR opcode specified by EndOpCodeHandle, then NULL is returned. If a match\r
+ is found, then all of the IFR opcodes between the start match and the end\r
+ match are deleted from the form being updated and all of the IFR opcodes\r
+ from StartOpCodeHandle except the first opcode are inserted immediately after\r
+ the matching start IFR opcode. If StartOpCcodeHandle only contains one\r
+ IFR instruction, then the result of this operation will delete all of the IFR\r
+ opcodes between the start end matches.\r
\r
- @param HiiHandle The HII Handle.\r
+ If HiiHandle is NULL, then ASSERT().\r
+ If StartOpCodeHandle is NULL, then ASSERT().\r
+\r
+ @param[in] HiiHandle The HII Handle of the form to update.\r
+ @param[in] FormSetGuid The Formset GUID of the form to update. This\r
+ is an optional parameter that may be NULL.\r
+ If it is NULL, all FormSet will be updated.\r
+ @param[in] FormId The ID of the form to update.\r
+ @param[in] StartOpCodeHandle An OpCode Handle that contains the set of IFR\r
+ opcodes to be inserted or replaced in the form.\r
+ The first IFR instruction in StartOpCodeHandle\r
+ is used to find matching IFR opcode in the\r
+ form.\r
+ @param[in] EndOpCodeHandle An OpCcode Handle that contains the IFR opcode\r
+ that marks the end of a replace operation in\r
+ the form. This is an optional parameter that\r
+ may be NULL. If it is NULL, then an the IFR\r
+ opcodes specified by StartOpCodeHandle are\r
+ inserted into the form.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory resource is allocated.\r
+ @retval EFI_NOT_FOUND The following cases will return EFI_NOT_FOUND.\r
+ 1) The form specified by HiiHandle, FormSetGuid,\r
+ and FormId could not be found in the HII Database.\r
+ 2) No IFR opcodes in the target form match the first\r
+ IFR opcode in StartOpCodeHandle.\r
+ 3) EndOpCOde is not NULL, and no IFR opcodes in the\r
+ target form following a matching start opcode match\r
+ the first IFR opcode in EndOpCodeHandle.\r
+ @retval EFI_SUCCESS The matched form is updated by StartOpcode.\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
+EFI_STATUS\r
+EFIAPI\r
+HiiUpdateForm (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid, OPTIONAL\r
+ IN EFI_FORM_ID FormId,\r
+ IN VOID *StartOpCodeHandle,\r
+ IN VOID *EndOpCodeHandle OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN BufferSize;\r
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINT32 PackageListLength;\r
+ UINT32 Offset;\r
+ EFI_HII_PACKAGE_LIST_HEADER *UpdatePackageList;\r
+ UINTN BufferSize;\r
+ UINT8 *UpdateBufferPos;\r
+ EFI_HII_PACKAGE_HEADER *Package;\r
+ EFI_HII_PACKAGE_HEADER *TempPackage;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ BOOLEAN Updated;\r
+ HII_LIB_OPCODE_BUFFER *OpCodeBufferStart;\r
+ HII_LIB_OPCODE_BUFFER *OpCodeBufferEnd;\r
\r
+ //\r
+ // Input update data can't be NULL.\r
+ //\r
ASSERT (HiiHandle != NULL);\r
+ ASSERT (StartOpCodeHandle != NULL);\r
+ UpdatePackageList = NULL;\r
+ TempPackage = NULL;\r
+ HiiPackageList = NULL;\r
\r
- HiiPackageList = NULL;\r
+ //\r
+ // Retrieve buffer data from Opcode Handle\r
+ //\r
+ OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle;\r
+ OpCodeBufferEnd = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle;\r
+\r
+ //\r
+ // Get the original package list\r
+ //\r
BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ //\r
+ // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
+ //\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return Status;\r
+ }\r
+\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ if (HiiPackageList == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
\r
- Status = mHiiDatabaseProt->ExportPackageLists (\r
- mHiiDatabaseProt,\r
- HiiHandle,\r
- &BufferSize,\r
- HiiPackageList\r
- );\r
+ Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Finish;\r
+ }\r
\r
- return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
-}\r
+ //\r
+ // Calculate and allocate space for retrieval of IFR data\r
+ //\r
+ BufferSize += OpCodeBufferStart->Position;\r
+ UpdatePackageList = AllocateZeroPool (BufferSize);\r
+ if (UpdatePackageList == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // Allocate temp buffer to store the temp updated package buffer\r
+ //\r
+ TempPackage = AllocateZeroPool (BufferSize);\r
+ if (TempPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
+ UpdateBufferPos = (UINT8 *) UpdatePackageList;\r
\r
+ //\r
+ // Copy the package list header\r
+ //\r
+ CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+ UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+ //\r
+ // Go through each package to find the matched package and update one by one\r
+ //\r
+ Updated = FALSE;\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
+ while (Offset < PackageListLength) {\r
+ Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ Offset += Package->Length;\r
+\r
+ if (Package->Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Check this package is the matched package.\r
+ //\r
+ Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPackage);\r
+ //\r
+ // The matched package is found. Its package buffer will be updated by the input new data.\r
+ //\r
+ if (!EFI_ERROR(Status)) {\r
+ //\r
+ // Set Update Flag\r
+ //\r
+ Updated = TRUE;\r
+ //\r
+ // Add updated package buffer\r
+ //\r
+ Package = TempPackage;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add pacakge buffer\r
+ //\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ CopyMem (UpdateBufferPos, Package, PackageHeader.Length);\r
+ UpdateBufferPos += PackageHeader.Length;\r
+ }\r
+\r
+ if (Updated) {\r
+ //\r
+ // Update package list length\r
+ //\r
+ BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;\r
+ WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);\r
+\r
+ //\r
+ // Update Package to show form\r
+ //\r
+ Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);\r
+ } else {\r
+ //\r
+ // Not matched form is found and updated.\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+\r
+Finish:\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ }\r
+\r
+ if (UpdatePackageList != NULL) {\r
+ FreePool (UpdatePackageList);\r
+ }\r
+\r
+ if (TempPackage != NULL) {\r
+ FreePool (TempPackage);\r
+ }\r
+\r
+ return Status;\r
+}\r