\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
//\r
// <ConfigHdr> Template\r
//\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
}\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
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
return ConfigResp;\r
}\r
\r
-/**\r
- Uses the ConfigToBlock() service of the Config Routing Protocol to \r
- convert <ConfigResp> to a block. The block is allocated using\r
- AllocatePool(). The caller is responsible for freeing the block\r
- using FreePool().\r
-\r
- If ConfigResp is NULL, then ASSERT().\r
-\r
- @param[in] ConfigResp Pointer to a Null-terminated Unicode string.\r
- @param[in] BufferSize Length in bytes of buffer to hold retrived data. \r
-\r
- @retval NULL The block could not be generated..\r
- @retval Other Pointer to the allocated block.\r
-\r
-**/\r
-UINT8 *\r
-EFIAPI\r
-InternalHiiConfigToBlock (\r
- IN EFI_STRING ConfigResp,\r
- IN UINTN BlockSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *Progress;\r
- UINT8 *Block;\r
-\r
- ASSERT (ConfigResp != NULL);\r
-\r
- //\r
- // Allocate a buffer to hold the <ConfigResp> conversion\r
- //\r
- Block = AllocateZeroPool (BlockSize);\r
- if (Block == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Convert <ConfigResp> to a buffer\r
- //\r
- Status = gHiiConfigRouting->ConfigToBlock (\r
- gHiiConfigRouting,\r
- ConfigResp,\r
- Block,\r
- &BlockSize,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Block);\r
- return NULL;\r
- }\r
-\r
- //\r
- // Return converted buffer\r
- //\r
- return Block;\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
if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {\r
return NULL;\r
}\r
- }\r
-\r
- ResultsDataSize = 0;\r
-\r
- if (SetResultsData != NULL) {\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 hexidecimal 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
+ hexidecimal 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 hexidecimal 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
+\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
+ String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
+ if (String == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Start with L"GUID="\r
+ //\r
+ ReturnString = StrCpy (String, L"GUID=");\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
+ String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Append L"&NAME="\r
+ //\r
+ StrCpy (String, 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
+ String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Append L"&PATH="\r
+ //\r
+ StrCpy (String, 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
+ String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\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
+ StrnCpy (TemStr, 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
+ break;\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
+ This function shares the same logic to parse ConfigAltResp string \r
+ for setting default value and validating current setting.\r
+\r
+ @param ConfigResp \r
+ @param HiiPackageList \r
+ @param PackageListLength \r
+ @param VarGuid\r
+ @param VarName\r
+ \r
+ @retval EFI_SUCCESS\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
+ )\r
+{ \r
+ IFR_BLOCK_DATA *CurrentBlockArray;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *NewBlockData;\r
+ IFR_BLOCK_DATA VarBlockData;\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ UINT8 *TmpBuffer;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ UINT64 VarValue;\r
+ LIST_ENTRY *Link;\r
+ UINT8 *VarBuffer;\r
+ UINTN MaxBufferSize;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
+ UINT32 PackageOffset;\r
+ UINT8 *PackageData;\r
+ UINTN IfrOffset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\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
+ \r
+ //\r
+ // 1. Get the current setting to current block data array and Convert them into VarBuffer\r
+ //\r
+\r
+ //\r
+ // Skip ConfigHdr string\r
+ //\r
+ StringPtr = ConfigResp;\r
+ StringPtr = StrStr (ConfigResp, L"&OFFSET");\r
+ if (StringPtr == NULL) {\r
+ //\r
+ // No ConfigBlock value is requied to be validated.\r
+ // EFI_SUCCESS directly return.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ //\r
+ // Initialize the local variables.\r
+ //\r
+ Index = 0;\r
+ VarStoreName = NULL;\r
+ Status = EFI_SUCCESS;\r
+ BlockData = NULL;\r
+ NewBlockData = NULL;\r
+ TmpBuffer = NULL;\r
+ MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+ VarBuffer = AllocateZeroPool (MaxBufferSize);\r
+ if (VarBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Init CurrentBlockArray\r
+ //\r
+ CurrentBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (CurrentBlockArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&CurrentBlockArray->Entry);\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 ((UINTN) (Offset + Width) > MaxBufferSize) {\r
+ VarBuffer = ReallocatePool (\r
+ MaxBufferSize,\r
+ Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
+ VarBuffer\r
+ );\r
+ if (VarBuffer == 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 (VarBuffer + 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 = CurrentBlockArray->Entry.ForwardLink; Link != &CurrentBlockArray->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 == &CurrentBlockArray->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 = CurrentBlockArray->Entry.ForwardLink;\r
+ while ((Link != &CurrentBlockArray->Entry) && (Link->ForwardLink != &CurrentBlockArray->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
+ if (IsListEmpty (&CurrentBlockArray->Entry)) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 2. Check IFR value is in block data, then Validate Vaule\r
+ //\r
+ ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
+ VarValue = 0;\r
+ IfrVarStore = NULL;\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ while (PackageOffset < PackageListLength) {\r
+ CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
+ \r
+ //\r
+ // Parse IFR opcode from the form package.\r
+ //\r
+ if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ IfrOffset = sizeof (PacakgeHeader);\r
+ PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+ while (IfrOffset < PacakgeHeader.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 (IfrVarStore != NULL) {\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
+ break;\r
+ case EFI_IFR_FORM_OP:\r
+ //\r
+ // Check the matched VarStoreId is found.\r
+ //\r
+ if (IfrVarStore == NULL) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\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
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
+ if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset by Question header and Width by DataType Flags\r
+ //\r
+ Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\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) > IfrVarStore->Size) {\r
+ //\r
+ // This question exceeds the var store size. \r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get the current value for oneof opcode\r
+ //\r
+ VarValue = 0;\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ //\r
+ // Set Block Data, to be checked in the following Oneof option opcode.\r
+ //\r
+ VarBlockData.Offset = Offset;\r
+ VarBlockData.Width = Width;\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
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
+ if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset by Question header and Width by DataType Flags\r
+ //\r
+ Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\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) > IfrVarStore->Size) {\r
+ //\r
+ // This question exceeds the var store size. \r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check the current value is in the numeric range.\r
+ //\r
+ VarValue = 0;\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\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
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ break;\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
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
+ if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset by Question header\r
+ //\r
+ Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ Width = sizeof (BOOLEAN);\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) > IfrVarStore->Size) {\r
+ //\r
+ // This question exceeds the var store size. \r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Boolean type, only 1 and 0 is valid.\r
+ //\r
+ if (*(VarBuffer + Offset) > 1) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done; \r
+ }\r
+ \r
+ break;\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // Check current string length is less than maxsize\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 != IfrVarStore->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\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) > IfrVarStore->Size) {\r
+ //\r
+ // This question exceeds the var store size. \r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Check current string length is less than maxsize\r
+ //\r
+ if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done; \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
+ if (VarValue == IfrOneOfOption->Value.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
+\r
+ break;\r
+ case EFI_IFR_END_OP:\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.OpCode == EFI_IFR_ONE_OF_OP) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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 += PacakgeHeader.Length; \r
+ }\r
+\r
+Done:\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
+ This function shares the same logic to parse ConfigAltResp string \r
+ 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 TURE 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
+ EFI_STRING_ID DefaultName;\r
+\r
+ UINT8 *PackageData;\r
+ UINTN IfrOffset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINT32 PackageOffset; \r
+ UINTN PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PacakgeHeader;\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
+ PackageData = 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
+ \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 DefaultName string ID by parsing the PacakgeList \r
+ //\r
+\r
+ //\r
+ // 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
+ // Parse the form package and get the default name string ID.\r
+ //\r
+ if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Status = EFI_NOT_FOUND;\r
+ while (PackageOffset < PackageListLength) {\r
+ CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
+ \r
+ //\r
+ // Parse IFR opcode to get default store opcode\r
+ //\r
+ if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ IfrOffset = sizeof (PacakgeHeader);\r
+ PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+ while (IfrOffset < PacakgeHeader.Length) {\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
+ //\r
+ // Match DefaultId to find its DefaultName\r
+ //\r
+ if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {\r
+ if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {\r
+ DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\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 += PacakgeHeader.Length; \r
+ }\r
+ \r
+ //\r
+ // Not found the matched default string ID\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_SUCCESS;\r
+ goto NextConfigAltResp;\r
+ }\r
+ }\r
+ \r
//\r
- // Request to to set data in the uncommitted browser state information\r
+ // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+ // Get the default configuration string according to the found defaultname string ID.\r
//\r
- ResultsData = SetResultsData;\r
- } else {\r
+ Status = gHiiConfigRouting->GetAltConfig (\r
+ gHiiConfigRouting,\r
+ ConfigAltResp,\r
+ VarGuid,\r
+ VarName,\r
+ DevicePath,\r
+ (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL, // it can be NULL to get the current setting.\r
+ &ConfigResp\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_SUCCESS;\r
+ goto NextConfigAltResp;\r
+ }\r
+ \r
//\r
- // Retrieve the length of the buffer required ResultsData from the Browser Callback\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
- Status = mUefiFormBrowser2->BrowserCallback (\r
- mUefiFormBrowser2,\r
- &ResultsDataSize,\r
- &TempResultsData,\r
- TRUE,\r
- VariableGuid,\r
- VariableName\r
- );\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- return NULL;\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);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
}\r
\r
+NextConfigAltResp:\r
//\r
- // Allocate the ResultsData buffer\r
+ // Free the allocated pacakge buffer and the got ConfigResp string.\r
//\r
- ResultsData = AllocateZeroPool (ResultsDataSize);\r
- if (ResultsData == NULL) {\r
- return NULL;\r
+ if (HiiPackageList != NULL) {\r
+ FreePool (HiiPackageList);\r
+ HiiPackageList = 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
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ ConfigResp = NULL;\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
+ // Free the allocated buffer.\r
+ //\r
+ FreePool (VarGuid);\r
+ VarGuid = NULL;\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 hexidecimal 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
- hexidecimal 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 hexidecimal 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
+ FreePool (VarName);\r
+ VarName = NULL;\r
+ \r
+ FreePool (DevicePath);\r
+ DevicePath = NULL;\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
+ // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\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
+ // 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
- // Compute the size of the device path in bytes\r
+ // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0" \r
+ // | 1 | StrLen (ConfigHdr) | 8 | 1 |\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
- String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
- if (String == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Start with L"GUID="\r
- //\r
- ReturnString = StrCpy (String, L"GUID=");\r
- String += StrLen (String);\r
-\r
- if (Guid != NULL) {\r
+ ConfigAltHdr = AllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16));\r
+ if (ConfigAltHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StrCpy (ConfigAltHdr, L"&");\r
+ StrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr);\r
+ StrCat (ConfigAltHdr, L"&ALTCFG=");\r
+ \r
//\r
- // Append Guid converted to <HexCh>32\r
+ // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
//\r
- for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
- String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+ while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
+ StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
+ if (*StringPtr == L'\0') {\r
+ break;\r
+ }\r
}\r
- }\r
- \r
- //\r
- // Append L"&NAME="\r
- //\r
- StrCpy (String, L"&NAME=");\r
- String += StrLen (String);\r
-\r
- if (Name != NULL) {\r
+ \r
//\r
- // Append Name converted to <Char>NameLength\r
+ // Free the allocated ConfigAltHdr string\r
//\r
- for (; *Name != L'\0'; Name++) {\r
- String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\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
- //\r
- // Append L"&PATH="\r
- //\r
- StrCpy (String, L"&PATH=");\r
- String += StrLen (String);\r
+ if (VarName != NULL) {\r
+ FreePool (VarName);\r
+ }\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
- String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
}\r
\r
- //\r
- // Null terminate the Unicode string\r
- //\r
- *String = L'\0';\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
\r
- //\r
- // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
- //\r
- return InternalHiiLowerConfigString (ReturnString);\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 ExtractConfig 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 TURE 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 TURE 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
//\r
VA_START (Args, BlockNameArray);\r
while (TRUE) {\r
- AltCfgId = VA_ARG (Args, UINT16);\r
+ AltCfgId = VA_ARG (Args, UINTN);\r
Buffer = VA_ARG (Args, UINT8 *);\r
if (Buffer == NULL) {\r
break;\r
//\r
VA_START (Args, BlockNameArray);\r
while (TRUE) {\r
- AltCfgId = VA_ARG (Args, UINT16);\r
+ AltCfgId = VA_ARG (Args, UINTN);\r
Buffer = VA_ARG (Args, UINT8 *);\r
if (Buffer == NULL) {\r
break;\r
\r
/**\r
Retrieves uncommited data from the Form Browser and converts it to a binary\r
- buffer. The returned buffer is allocated using AllocatePool(). The caller\r
- is responsible for freeing the returned buffer using FreePool().\r
+ buffer.\r
\r
@param[in] VariableName Pointer to a Null-terminated Unicode string. This \r
is an optional parameter that may be NULL.\r
@param[in] VariableGuid Pointer to an EFI_GUID structure. This is an optional \r
parameter that may be NULL.\r
@param[in] BufferSize Length in bytes of buffer to hold retrived data. \r
+ @param[out] Block Buffer of data to be updated.\r
\r
- @retval NULL The uncommitted data could not be retrieved.\r
- @retval Other A pointer to a buffer containing the uncommitted data.\r
+ @retval FALSE The uncommitted data could not be retrieved.\r
+ @retval TRUE The uncommitted data was retrieved.\r
\r
**/\r
-UINT8 *\r
+BOOLEAN\r
EFIAPI\r
HiiGetBrowserData (\r
IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
IN CONST CHAR16 *VariableName, OPTIONAL\r
- IN UINTN BlockSize\r
+ IN UINTN BlockSize,\r
+ OUT UINT8 *Block\r
)\r
{\r
EFI_STRING ResultsData;\r
UINTN Size;\r
EFI_STRING ConfigResp;\r
- UINT8 *Block;\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 NULL;\r
+ return FALSE;\r
}\r
\r
//\r
//\r
FreePool (ResultsData);\r
if (ConfigResp == NULL) {\r
- return NULL;\r
+ return FALSE;\r
}\r
\r
//\r
// Convert <ConfigResp> to a buffer\r
//\r
- Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);\r
+ Status = gHiiConfigRouting->ConfigToBlock (\r
+ gHiiConfigRouting,\r
+ ConfigResp,\r
+ Block,\r
+ &BlockSize,\r
+ &Progress\r
+ );\r
+ //\r
+ // Free the allocated buffer\r
+ //\r
FreePool (ConfigResp);\r
\r
- return Block;\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
}\r
\r
/**\r
**/\r
UINT8 *\r
EFIAPI\r
-InternalHiiCreateRawOpCodes (\r
+HiiCreateRawOpCodes (\r
IN VOID *OpCodeHandle,\r
IN UINT8 *RawBuffer,\r
IN UINTN RawBufferSize\r
ASSERT (RawOpCodeHandle != NULL);\r
\r
RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
- return InternalHiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
+ return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
}\r
\r
/**\r
BOOLEAN GetFormSet;\r
BOOLEAN GetForm;\r
BOOLEAN Updated;\r
- EFI_IFR_OP_HEADER *AddOpCode;\r
- UINT32 UpdatePackageLength;\r
+ UINTN UpdatePackageLength;\r
\r
CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
//\r
// The matched Form is found, and Update data in this form\r
//\r
- if (GetFormSet && GetForm && !Updated) {\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
return EFI_NOT_FOUND;\r
}\r
}\r
+\r
//\r
// Insert the updated data\r
//\r
- UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
- AddOpCode = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);\r
- AddSize = UpdateIfrOpHdr->Length;\r
- while (AddSize < OpCodeBufferStart->Position) {\r
- CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
- BufferPos += AddOpCode->Length;\r
- UpdatePackageLength += AddOpCode->Length;\r
-\r
- AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);\r
- AddSize += AddOpCode->Length; \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
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
// Update the package length.\r
//\r
- PackageHeader.Length = UpdatePackageLength;\r
+ PackageHeader.Length = (UINT32) UpdatePackageLength;\r
CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
\r
return EFI_SUCCESS;\r