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
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
- @param ConfigResp ConfigResp string contains the current setting.\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
-EFIAPI\r
-InternalHiiValidateCurrentSetting (\r
- IN EFI_STRING ConfigResp,\r
+ValidateQuestionFromVfr (\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
+ 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
+ )
+{
+ IFR_BLOCK_DATA VarBlockData;
+ UINT16 Offset;
+ UINT16 Width;
+ UINT64 VarValue;
EFI_IFR_TYPE_VALUE TmpValue;\r
- LIST_ENTRY *Link;\r
- UINT8 *VarBuffer;\r
- UINTN MaxBufferSize;\r
EFI_STATUS Status;\r
EFI_HII_PACKAGE_HEADER PacakgeHeader;\r
UINT32 PackageOffset;\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_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
+ CHAR16 *QuestionName;\r
+ CHAR16 *StringPtr;\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 required 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
+ Index = 0;
+ VarStoreName = NULL;
+ Status = EFI_SUCCESS;
+ VarValue = 0;
+ IfrVarStore = NULL;
+ IfrNameValueStore = NULL;
+ IfrEfiVarStore = NULL;\r
+ ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
+ ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
\r
//\r
- // 2. Check IFR value is in block data, then Validate Value\r
+ // Check IFR value is in block data, then Validate Value\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
//\r
// Parse IFR opcode from the form package.\r
//\r
// Validate current setting to the value built in IFR opcode\r
//\r
switch (IfrOpHdr->OpCode) {\r
- case EFI_IFR_VARSTORE_OP: \r
+ case EFI_IFR_VARSTORE_OP:\r
//\r
// VarStoreId has been found. No further found.\r
//\r
- if (IfrVarStore != NULL) {\r
+ if (VarStoreData.VarStoreId != 0) {\r
break;\r
}\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_FORM_OP:\r
- case EFI_IFR_FORM_MAP_OP:\r
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
//\r
- // Check the matched VarStoreId is found.\r
+ // VarStoreId has been found. No further found.\r
//\r
- if (IfrVarStore == NULL) {\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
+ if (VarStoreData.VarStoreId != 0) {\r
+ break;\r
}\r
- break;\r
- case EFI_IFR_ONE_OF_OP:\r
//\r
- // Check whether current value is the one of option.\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
- //\r
- // OneOf question is not in IFR Form. This IFR form is not valid. \r
- //\r
- if (IfrVarStore == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
+ if (IfrNameValueStore != NULL) {\r
+ VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;\r
}\r
- // \r
- // Check whether this question is for the requested varstore.\r
+ break;\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
//\r
- IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
- if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStoreData.VarStoreId != 0) {\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
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
+\r
//\r
- // Check whether this question is in current block array.\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 (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
- //\r
- // This question is not in the current configuration string. Skip it.\r
- //\r
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
break;\r
}\r
- //\r
- // Check this var question is in the var storage \r
- //\r
- if ((Offset + Width) > IfrVarStore->Size) {\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
- // This question exceeds the var store size. \r
+ // The matched VarStore is found.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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
- // Get the current value for oneof opcode\r
+ // Check the matched VarStoreId is found.\r
//\r
- VarValue = 0;\r
- CopyMem (&VarValue, VarBuffer + Offset, Width);\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
+ 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) > 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
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ }\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
//\r
// Numeric question is not in IFR Form. This IFR form is not valid. \r
//\r
- if (IfrVarStore == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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 != IfrVarStore->VarStoreId) {\r
+ if (IfrNumeric->Question.VarStoreId != VarStoreData.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
+ 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
- // This question is not in the current configuration string. Skip it.\r
+ // Get Offset by Question header and Width by DataType Flags\r
//\r
- break;\r
- }\r
- //\r
- // Check this var question is in the var storage \r
- //\r
- if ((Offset + Width) > IfrVarStore->Size) {\r
+ Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
//\r
- // This question exceeds the var store size. \r
+ // Check whether this question is in current block array.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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
- CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ //\r
+ // Check the current value is in the numeric range.\r
+ //\r
+ VarValue = 0;\r
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\r
+ }\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
+ return EFI_INVALID_PARAMETER;\r
}\r
break;\r
case EFI_IFR_NUMERIC_SIZE_2:\r
//\r
// Not in the valid range.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
break;\r
case EFI_IFR_NUMERIC_SIZE_4:\r
//\r
// Not in the valid range.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
break;\r
case EFI_IFR_NUMERIC_SIZE_8:\r
//\r
// Not in the valid range.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
+ return EFI_INVALID_PARAMETER;\r
}\r
break;\r
}\r
//\r
// CheckBox question is not in IFR Form. This IFR form is not valid. \r
//\r
- if (IfrVarStore == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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 != IfrVarStore->VarStoreId) {\r
+ if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {\r
break;\r
}\r
- \r
- //\r
- // Get Offset by Question header\r
- //\r
- Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
- Width = (UINT16) sizeof (BOOLEAN);\r
- //\r
- // Check whether this question is in current block array.\r
- //\r
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\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
- // This question is not in the current configuration string. Skip it.\r
+ // Get Offset by Question header\r
//\r
- break;\r
- }\r
- //\r
- // Check this var question is in the var storage \r
- //\r
- if ((Offset + Width) > IfrVarStore->Size) {\r
+ Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ Width = (UINT16) sizeof (BOOLEAN);\r
//\r
- // This question exceeds the var store size. \r
+ // Check whether this question is in current block array.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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
+ CopyMem (&VarValue, VarBuffer + Offset, Width);\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
+ if (VarValue > 1) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
- \r
break;\r
case EFI_IFR_STRING_OP:\r
//\r
//\r
// CheckBox question is not in IFR Form. This IFR form is not valid. \r
//\r
- if (IfrVarStore == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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 != IfrVarStore->VarStoreId) {\r
+ if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {\r
break;\r
}\r
- \r
//\r
- // Get Offset/Width by Question header and OneOf Flags\r
+ // Get Width by 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
+ 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
+ //\r
+ // Skip the "=".\r
+ // \r
+ StringPtr += 1;\r
+ \r
+ //\r
+ // Check current string length is less than maxsize\r
+ //\r
+ if (StrSize (StringPtr) > Width) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
//\r
- // This question is not in the current configuration string. Skip it.\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 (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\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
- // Check this var question is in the var storage \r
+ // Only check for OneOf and OrderList opcode\r
//\r
- if ((Offset + Width) > IfrVarStore->Size) {\r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
+ if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
//\r
- // This question exceeds the var store size. \r
+ // Check current value is the value of one of option.\r
//\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\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
- \r
+ break;\r
+ case EFI_IFR_END_OP:\r
//\r
- // Check current string length is less than maxsize\r
+ // Decrease opcode scope for the validated opcode\r
//\r
- if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done; \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_ONE_OF_OPTION_OP:\r
+ default:\r
//\r
- // Opcode Scope is zero. This one of option is not to be checked. \r
+ // Increase Scope for the validated opcode\r
//\r
- if (VarBlockData.Scope == 0) {\r
- break;\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
+ 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;
+ UINTN MaxBufferSize;
+ EFI_STATUS Status;
+ IFR_BLOCK_DATA *BlockArray;
+ UINT8 *DataBuffer;
+
+ //
+ // Initialize the local variables.
+ //
+ Status = EFI_SUCCESS;
+ BlockData = NULL;
+ NewBlockData = NULL;
+ 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
- //\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
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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
+ 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
- // OneOf value doesn't belong to one of option value. \r
- //\r
- if ((VarBlockData.Scope == 0) && (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
+ // 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
+ 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
- // Go to the next opcode\r
+ // Insert new block data as the previous one of this link.\r
//\r
- IfrOffset += IfrOpHdr->Length;\r
+ InsertTailList (Link, &NewBlockData->Entry);\r
+ break;\r
}\r
- //\r
- // Only one form is in a package list.\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
//\r
- // Go to next package.\r
+ // Go to next ConfigBlock \r
//\r
- PackageOffset += PacakgeHeader.Length; \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
RemoveEntryList (&BlockData->Entry);\r
FreePool (BlockData);\r
}\r
- FreePool (CurrentBlockArray); \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
// 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
+ Status = EFI_SUCCESS;\r
goto NextConfigAltResp;\r
}\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 (StrStr (ConfigResp, L"&OFFSET=") == NULL) {\r
+ if (!GetElementsFromRequest (ConfigResp)) {\r
goto NextConfigAltResp;\r
}\r
\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
+ Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);\r
}\r
\r
if (EFI_ERROR (Status)) {\r
HiiPackageList = NULL;\r
}\r
\r
- if (ConfigResp != NULL) {\r
- FreePool (ConfigResp);\r
- ConfigResp = NULL;\r
- }\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ ConfigResp = NULL;\r
+ }\r
\r
//\r
// Free the allocated buffer.\r
return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
}\r
\r
+/**\r
+ Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.\r
+\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 OpCodeHandle is NULL, then ASSERT().\r
+ If any reserved bits are set in QuestionFlags, then ASSERT().\r
+\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
+ @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
+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_IFR_REF4 OpCode;\r
+ UINTN OpCodeSize;\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.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
+ // Cacluate OpCodeSize based on the input Ref value.\r
+ // Try to use the small OpCode to save size.\r
+ //\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
+ return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);\r
+}\r
+\r
/**\r
Create EFI_IFR_CHECKBOX_OP opcode.\r
\r