summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Library
diff options
context:
space:
mode:
authorEric Dong <eric.dong@intel.com>2013-07-02 07:53:35 +0000
committerydong10 <ydong10@6f19259b-4bc3-4df7-8a09-765794883524>2013-07-02 07:53:35 +0000
commit82e8c1380fe8d9d94b7585242f1e159bdbbeb778 (patch)
treea870a96103ef2fb7647b6180d905233b1f3072c5 /MdeModulePkg/Library
parent3aee9940c98cff4814c1ec9bddbcfd8528211c58 (diff)
downloadedk2-platforms-82e8c1380fe8d9d94b7585242f1e159bdbbeb778.tar.xz
Update HiiDataBase and UefiHiiLib to support Name/Value varstore.
Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14451 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Library')
-rw-r--r--MdeModulePkg/Library/UefiHiiLib/HiiLib.c1094
1 files changed, 720 insertions, 374 deletions
diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
index 9590f8f14a..87aeb947ae 100644
--- a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
+++ b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
@@ -31,6 +31,11 @@ typedef struct {
UINT8 Scope;
} IFR_BLOCK_DATA;
+typedef struct {
+ EFI_VARSTORE_ID VarStoreId;
+ UINT16 Size;
+} IFR_VARSTORAGE_DATA;
+
//
// <ConfigHdr> Template
//
@@ -914,42 +919,93 @@ InternalHiiGetValueOfNumber (
}
/**
+ Get value from config request resp string.
+
+ @param ConfigElement ConfigResp string contains the current setting.
+ @param VarName The variable name which need to get value.
+ @param VarValue The return value.
+
+ @retval EFI_SUCCESS Get the value for the VarName
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+**/
+EFI_STATUS
+GetValueFromRequest (
+ IN CHAR16 *ConfigElement,
+ IN CHAR16 *VarName,
+ OUT UINT64 *VarValue
+ )
+{
+ UINT8 *TmpBuffer;
+ CHAR16 *StringPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ //
+ // Find VarName related string.
+ //
+ StringPtr = StrStr (ConfigElement, VarName);
+ ASSERT (StringPtr != NULL);
+
+ //
+ // Skip the "VarName=" string
+ //
+ StringPtr += StrLen (VarName) + 1;
+
+ //
+ // Get Offset
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *VarValue = 0;
+ CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));
+
+ FreePool (TmpBuffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
This internal function parses IFR data to validate current setting.
- @param ConfigResp ConfigResp string contains the current setting.
+ Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
+ else the VarBuffer and CurrentBlockArray is valid.
+
@param HiiPackageList Point to Hii package list.
@param PackageListLength The length of the pacakge.
@param VarGuid Guid of the buffer storage.
@param VarName Name of the buffer storage.
+ @param VarBuffer The data buffer for the storage.
+ @param CurrentBlockArray The block array from the config Requst string.
+ @param RequestElement The config string for this storage.
+ @param HiiHandle The HiiHandle for this formset.
+ @param NameValueType Whether current storage is name/value varstore or not.
@retval EFI_SUCCESS The current setting is valid.
@retval EFI_OUT_OF_RESOURCES The memory is not enough.
@retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
**/
EFI_STATUS
-EFIAPI
-InternalHiiValidateCurrentSetting (
- IN EFI_STRING ConfigResp,
+ValidateQuestionFromVfr (
IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
IN UINTN PackageListLength,
IN EFI_GUID *VarGuid,
- IN CHAR16 *VarName
+ IN CHAR16 *VarName,
+ IN UINT8 *VarBuffer,
+ IN IFR_BLOCK_DATA *CurrentBlockArray,
+ IN CHAR16 *RequestElement,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BOOLEAN NameValueType
)
-{
- IFR_BLOCK_DATA *CurrentBlockArray;
- IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *NewBlockData;
+{
IFR_BLOCK_DATA VarBlockData;
- EFI_STRING StringPtr;
- UINTN Length;
UINT8 *TmpBuffer;
UINT16 Offset;
UINT16 Width;
UINT64 VarValue;
EFI_IFR_TYPE_VALUE TmpValue;
- LIST_ENTRY *Link;
- UINT8 *VarBuffer;
- UINTN MaxBufferSize;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER PacakgeHeader;
UINT32 PackageOffset;
@@ -957,6 +1013,9 @@ InternalHiiValidateCurrentSetting (
UINTN IfrOffset;
EFI_IFR_OP_HEADER *IfrOpHdr;
EFI_IFR_VARSTORE *IfrVarStore;
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueStore;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ IFR_VARSTORAGE_DATA VarStoreData;
EFI_IFR_ONE_OF *IfrOneOf;
EFI_IFR_NUMERIC *IfrNumeric;
EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
@@ -964,230 +1023,30 @@ InternalHiiValidateCurrentSetting (
EFI_IFR_STRING *IfrString;
CHAR8 *VarStoreName;
UINTN Index;
-
- //
- // 1. Get the current setting to current block data array and Convert them into VarBuffer
- //
+ CHAR16 *QuestionName;
+ CHAR16 *StringPtr;
//
- // Skip ConfigHdr string
- //
- StringPtr = ConfigResp;
- StringPtr = StrStr (ConfigResp, L"&OFFSET");
- if (StringPtr == NULL) {
- //
- // No ConfigBlock value is required to be validated.
- // EFI_SUCCESS directly return.
- //
- return EFI_SUCCESS;
- }
-
- //
// Initialize the local variables.
//
- Index = 0;
- VarStoreName = NULL;
- Status = EFI_SUCCESS;
- BlockData = NULL;
- NewBlockData = NULL;
- TmpBuffer = NULL;
- MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
- VarBuffer = AllocateZeroPool (MaxBufferSize);
- if (VarBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Init CurrentBlockArray
- //
- CurrentBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (CurrentBlockArray == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- InitializeListHead (&CurrentBlockArray->Entry);
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
- //
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
- //
- // Skip the &OFFSET= string
- //
- StringPtr += StrLen (L"&OFFSET=");
-
- //
- // Get Offset
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- StringPtr += StrLen (L"&VALUE=");
-
- //
- // Get Value
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether VarBuffer is enough
- //
- if ((UINTN) (Offset + Width) > MaxBufferSize) {
- VarBuffer = ReallocatePool (
- MaxBufferSize,
- Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
- VarBuffer
- );
- if (VarBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
- }
-
- //
- // Update the Block with configuration info
- //
- CopyMem (VarBuffer + Offset, TmpBuffer, Width);
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- //
- // Set new Block Data
- //
- NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (NewBlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- NewBlockData->Offset = Offset;
- NewBlockData->Width = Width;
-
- //
- // Insert the new block data into the block data array.
- //
- for (Link = CurrentBlockArray->Entry.ForwardLink; Link != &CurrentBlockArray->Entry; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (NewBlockData->Offset == BlockData->Offset) {
- if (NewBlockData->Width > BlockData->Width) {
- BlockData->Width = NewBlockData->Width;
- }
- FreePool (NewBlockData);
- break;
- } else if (NewBlockData->Offset < BlockData->Offset) {
- //
- // Insert new block data as the previous one of this link.
- //
- InsertTailList (Link, &NewBlockData->Entry);
- break;
- }
- }
-
- //
- // Insert new block data into the array tail.
- //
- if (Link == &CurrentBlockArray->Entry) {
- InsertTailList (Link, &NewBlockData->Entry);
- }
-
- //
- // If '\0', parsing is finished.
- //
- if (*StringPtr == 0) {
- break;
- }
- //
- // Go to next ConfigBlock
- //
- }
-
- //
- // Merge the aligned block data into the single block data.
- //
- Link = CurrentBlockArray->Entry.ForwardLink;
- while ((Link != &CurrentBlockArray->Entry) && (Link->ForwardLink != &CurrentBlockArray->Entry)) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
- if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
- if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
- BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
- }
- RemoveEntryList (Link->ForwardLink);
- FreePool (NewBlockData);
- continue;
- }
- Link = Link->ForwardLink;
- }
-
- if (IsListEmpty (&CurrentBlockArray->Entry)) {
- Status = EFI_SUCCESS;
- goto Done;
- }
+ Index = 0;
+ VarStoreName = NULL;
+ Status = EFI_SUCCESS;
+ TmpBuffer = NULL;
+ VarValue = 0;
+ IfrVarStore = NULL;
+ IfrNameValueStore = NULL;
+ IfrEfiVarStore = NULL;
+ ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));
+ ZeroMem (&VarBlockData, sizeof (VarBlockData));
//
- // 2. Check IFR value is in block data, then Validate Value
+ // Check IFR value is in block data, then Validate Value
//
- ZeroMem (&VarBlockData, sizeof (VarBlockData));
- VarValue = 0;
- IfrVarStore = NULL;
PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
while (PackageOffset < PackageListLength) {
CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
-
+
//
// Parse IFR opcode from the form package.
//
@@ -1200,11 +1059,11 @@ InternalHiiValidateCurrentSetting (
// Validate current setting to the value built in IFR opcode
//
switch (IfrOpHdr->OpCode) {
- case EFI_IFR_VARSTORE_OP:
+ case EFI_IFR_VARSTORE_OP:
//
// VarStoreId has been found. No further found.
//
- if (IfrVarStore != NULL) {
+ if (VarStoreData.VarStoreId != 0) {
break;
}
//
@@ -1227,15 +1086,82 @@ InternalHiiValidateCurrentSetting (
} else {
IfrVarStore = NULL;
}
+
+ if (IfrVarStore != NULL) {
+ VarStoreData.VarStoreId = IfrVarStore->VarStoreId;
+ VarStoreData.Size = IfrVarStore->Size;
+ }
+ break;
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ //
+ // VarStoreId has been found. No further found.
+ //
+ if (VarStoreData.VarStoreId != 0) {
+ break;
+ }
+ //
+ // Find the matched VarStoreId to the input VarGuid
+ //
+ IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
+ if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {
+ IfrNameValueStore = NULL;
+ }
+
+ if (IfrNameValueStore != NULL) {
+ VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;
+ }
+ break;
+ case EFI_IFR_VARSTORE_EFI_OP:
+ //
+ // VarStore is found. Don't need to search any more.
+ //
+ if (VarStoreData.VarStoreId != 0) {
+ break;
+ }
+
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
+
+ //
+ // If the length is small than the structure, this is from old efi
+ // varstore definition. Old efi varstore get config directly from
+ // GetVariable function.
+ //
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ break;
+ }
+
+ if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {
+ VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;
+ for (Index = 0; VarStoreName[Index] != 0; Index ++) {
+ if ((CHAR16) VarStoreName[Index] != VarName[Index]) {
+ break;
+ }
+ }
+ //
+ // The matched VarStore is found.
+ //
+ if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {
+ IfrEfiVarStore = NULL;
+ }
+ } else {
+ IfrEfiVarStore = NULL;
+ }
+
+ if (IfrEfiVarStore != NULL) {
+ //
+ // Find the matched VarStore
+ //
+ VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;
+ VarStoreData.Size = IfrEfiVarStore->Size;
+ }
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// Check the matched VarStoreId is found.
//
- if (IfrVarStore == NULL) {
- Status = EFI_SUCCESS;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_SUCCESS;
}
break;
case EFI_IFR_ONE_OF_OP:
@@ -1246,53 +1172,66 @@ InternalHiiValidateCurrentSetting (
//
// OneOf question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
- if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header and Width by DataType Flags
- //
- Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header and Width by DataType Flags
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
- //
- // Get the current value for oneof opcode
- //
- VarValue = 0;
- CopyMem (&VarValue, VarBuffer + Offset, Width);
+ //
+ // Get the current value for oneof opcode
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
+ }
//
// Set Block Data, to be checked in the following Oneof option opcode.
//
- VarBlockData.Offset = Offset;
- VarBlockData.Width = Width;
VarBlockData.OpCode = IfrOpHdr->OpCode;
VarBlockData.Scope = IfrOpHdr->Scope;
break;
@@ -1304,56 +1243,70 @@ InternalHiiValidateCurrentSetting (
//
// Numeric question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;
- if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header and Width by DataType Flags
- //
- Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header and Width by DataType Flags
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
- //
- // Check the current value is in the numeric range.
- //
- VarValue = 0;
- CopyMem (&VarValue, VarBuffer + Offset, Width);
+ //
+ // Check the current value is in the numeric range.
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
+ }
switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
case EFI_IFR_NUMERIC_SIZE_1:
if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_2:
@@ -1361,8 +1314,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_4:
@@ -1370,8 +1322,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_8:
@@ -1379,8 +1330,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
}
@@ -1394,52 +1344,69 @@ InternalHiiValidateCurrentSetting (
//
// CheckBox question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
- if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header
- //
- Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) sizeof (BOOLEAN);
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) sizeof (BOOLEAN);
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check the current value is in the numeric range.
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
}
-
//
// Boolean type, only 1 and 0 is valid.
//
- if (*(VarBuffer + Offset) > 1) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarValue > 1) {
+ return EFI_INVALID_PARAMETER;
}
-
break;
case EFI_IFR_STRING_OP:
//
@@ -1449,50 +1416,74 @@ InternalHiiValidateCurrentSetting (
//
// CheckBox question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrString = (EFI_IFR_STRING *) IfrOpHdr;
- if (IfrString->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
//
- // Get Offset/Width by Question header and OneOf Flags
+ // Get Width by OneOf Flags
//
- Offset = IfrString->Question.VarStoreInfo.VarOffset;
Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ StringPtr = StrStr (RequestElement, QuestionName);
+ if (StringPtr == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
//
- // This question is not in the current configuration string. Skip it.
+ // Skip the "=".
+ //
+ StringPtr += 1;
+
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ // Check current string length is less than maxsize
//
- // This question exceeds the var store size.
+ if (StrSize (StringPtr) > Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check current string length is less than maxsize
- //
- if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ // Get Offset/Width by Question header and OneOf Flags
+ //
+ Offset = IfrString->Question.VarStoreInfo.VarOffset;
+ //
+ // Check whether this question is in current block array.
+ //
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check current string length is less than maxsize
+ //
+ if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
+ return EFI_INVALID_PARAMETER;
+ }
}
break;
case EFI_IFR_ONE_OF_OPTION_OP:
@@ -1522,7 +1513,6 @@ InternalHiiValidateCurrentSetting (
VarBlockData.OpCode = 0;
}
}
-
break;
case EFI_IFR_END_OP:
//
@@ -1536,8 +1526,7 @@ InternalHiiValidateCurrentSetting (
// OneOf value doesn't belong to one of option value.
//
if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
default:
@@ -1559,14 +1548,343 @@ InternalHiiValidateCurrentSetting (
//
break;
}
-
+
//
// Go to next package.
//
- PackageOffset += PacakgeHeader.Length;
+ PackageOffset += PacakgeHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This internal function parses IFR data to validate current setting.
+
+ @param ConfigElement ConfigResp element string contains the current setting.
+ @param CurrentBlockArray Current block array.
+ @param VarBuffer Data buffer for this varstore.
+
+ @retval EFI_SUCCESS The current setting is valid.
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
+**/
+EFI_STATUS
+GetBlockDataInfo (
+ IN CHAR16 *ConfigElement,
+ OUT IFR_BLOCK_DATA **CurrentBlockArray,
+ OUT UINT8 **VarBuffer
+ )
+{
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *NewBlockData;
+ EFI_STRING StringPtr;
+ UINTN Length;
+ UINT8 *TmpBuffer;
+ UINT16 Offset;
+ UINT16 Width;
+ LIST_ENTRY *Link;
+ UINTN MaxBufferSize;
+ EFI_STATUS Status;
+ CHAR8 *VarStoreName;
+ UINTN Index;
+ IFR_BLOCK_DATA *BlockArray;
+ UINT8 *DataBuffer;
+
+ //
+ // Initialize the local variables.
+ //
+ Index = 0;
+ VarStoreName = NULL;
+ Status = EFI_SUCCESS;
+ BlockData = NULL;
+ NewBlockData = NULL;
+ TmpBuffer = NULL;
+ BlockArray = NULL;
+ MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
+ DataBuffer = AllocateZeroPool (MaxBufferSize);
+ if (DataBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Init BlockArray
+ //
+ BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ InitializeListHead (&BlockArray->Entry);
+
+ StringPtr = StrStr (ConfigElement, L"&OFFSET=");
+ ASSERT (StringPtr != NULL);
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ //
+ // Skip the &OFFSET= string
+ //
+ StringPtr += StrLen (L"&OFFSET=");
+
+ //
+ // Get Offset
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether VarBuffer is enough
+ //
+ if ((UINTN) (Offset + Width) > MaxBufferSize) {
+ DataBuffer = ReallocatePool (
+ MaxBufferSize,
+ Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
+ DataBuffer
+ );
+ if (DataBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+ CopyMem (DataBuffer + Offset, TmpBuffer, Width);
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ //
+ // Set new Block Data
+ //
+ NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (NewBlockData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ NewBlockData->Offset = Offset;
+ NewBlockData->Width = Width;
+
+ //
+ // Insert the new block data into the block data array.
+ //
+ for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (NewBlockData->Offset == BlockData->Offset) {
+ if (NewBlockData->Width > BlockData->Width) {
+ BlockData->Width = NewBlockData->Width;
+ }
+ FreePool (NewBlockData);
+ break;
+ } else if (NewBlockData->Offset < BlockData->Offset) {
+ //
+ // Insert new block data as the previous one of this link.
+ //
+ InsertTailList (Link, &NewBlockData->Entry);
+ break;
+ }
+ }
+
+ //
+ // Insert new block data into the array tail.
+ //
+ if (Link == &BlockArray->Entry) {
+ InsertTailList (Link, &NewBlockData->Entry);
+ }
+
+ //
+ // If '\0', parsing is finished.
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ //
+ // Go to next ConfigBlock
+ //
}
+ //
+ // Merge the aligned block data into the single block data.
+ //
+ Link = BlockArray->Entry.ForwardLink;
+ while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
+ if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
+ if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
+ BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
+ }
+ RemoveEntryList (Link->ForwardLink);
+ FreePool (NewBlockData);
+ continue;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ *VarBuffer = DataBuffer;
+ *CurrentBlockArray = BlockArray;
+ return EFI_SUCCESS;
+
Done:
+ if (DataBuffer != NULL) {
+ FreePool (DataBuffer);
+ }
+
+ if (BlockArray != NULL) {
+ //
+ // Free Link Array CurrentBlockArray
+ //
+ while (!IsListEmpty (&BlockArray->Entry)) {
+ BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ FreePool (BlockData);
+ }
+ FreePool (BlockArray);
+ }
+
+ return Status;
+}
+
+/**
+ This internal function parses IFR data to validate current setting.
+
+ @param ConfigResp ConfigResp string contains the current setting.
+ @param HiiPackageList Point to Hii package list.
+ @param PackageListLength The length of the pacakge.
+ @param VarGuid Guid of the buffer storage.
+ @param VarName Name of the buffer storage.
+ @param HiiHandle The HiiHandle for this package.
+
+ @retval EFI_SUCCESS The current setting is valid.
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
+**/
+EFI_STATUS
+EFIAPI
+InternalHiiValidateCurrentSetting (
+ IN EFI_STRING ConfigResp,
+ IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
+ IN UINTN PackageListLength,
+ IN EFI_GUID *VarGuid,
+ IN CHAR16 *VarName,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR16 *StringPtr;
+ EFI_STATUS Status;
+ IFR_BLOCK_DATA *CurrentBlockArray;
+ IFR_BLOCK_DATA *BlockData;
+ UINT8 *VarBuffer;
+ BOOLEAN NameValueType;
+
+ CurrentBlockArray = NULL;
+ VarBuffer = NULL;
+ StringPtr = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // If StringPtr != NULL, get the request elements.
+ //
+ if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {
+ Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ NameValueType = FALSE;
+ } else {
+ //
+ // Skip header part.
+ //
+ StringPtr = StrStr (ConfigResp, L"PATH=");
+ ASSERT (StringPtr != NULL);
+
+ if (StrStr (StringPtr, L"&") != NULL) {
+ NameValueType = TRUE;
+ } else {
+ //
+ // Not found Request element, return success.
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ValidateQuestionFromVfr(
+ HiiPackageList,
+ PackageListLength,
+ VarGuid,
+ VarName,
+ VarBuffer,
+ CurrentBlockArray,
+ ConfigResp,
+ HiiHandle,
+ NameValueType
+ );
+
if (VarBuffer != NULL) {
FreePool (VarBuffer);
}
@@ -1580,13 +1898,41 @@ Done:
RemoveEntryList (&BlockData->Entry);
FreePool (BlockData);
}
- FreePool (CurrentBlockArray);
+ FreePool (CurrentBlockArray);
}
return Status;
}
/**
+ Check whether the ConfigRequest string has the request elements.
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
+
+ @param ConfigRequest The input config request string.
+
+ @retval TRUE The input include config request elements.
+ @retval FALSE The input string not includes.
+
+**/
+BOOLEAN
+GetElementsFromRequest (
+ IN EFI_STRING ConfigRequest
+ )
+{
+ EFI_STRING TmpRequest;
+
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");
+ ASSERT (TmpRequest != NULL);
+
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
This function parses the input ConfigRequest string and its matched IFR code
string for setting default value and validating current setting.
@@ -1765,7 +2111,7 @@ InternalHiiIfrValueAction (
// Its default value and validating can't execute by parsing IFR data.
// Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
//
- Status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
goto NextConfigAltResp;
}
@@ -1822,7 +2168,7 @@ InternalHiiIfrValueAction (
//
// Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
//
- if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {
+ if (!GetElementsFromRequest (ConfigResp)) {
goto NextConfigAltResp;
}
@@ -1839,7 +2185,7 @@ InternalHiiIfrValueAction (
//
// Current Setting is in ConfigResp, will be set into buffer, then check it again.
//
- Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);
+ Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);
}
if (EFI_ERROR (Status)) {
@@ -1855,10 +2201,10 @@ NextConfigAltResp:
HiiPackageList = NULL;
}
- if (ConfigResp != NULL) {
- FreePool (ConfigResp);
- ConfigResp = NULL;
- }
+ if (ConfigResp != NULL) {
+ FreePool (ConfigResp);
+ ConfigResp = NULL;
+ }
//
// Free the allocated buffer.