+ @param StringPtr String in <BlockConfig> format and points to the\r
+ first character of <Number>.\r
+ @param Number The output value. Caller takes the responsibility\r
+ to free memory.\r
+ @param Len 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
+GetValueOfNumber (\r
+ IN EFI_STRING StringPtr,\r
+ OUT UINT8 **Number,\r
+ OUT UINTN *Len\r
+ )\r
+{\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STRING Str;\r
+ UINT8 *Buf;\r
+ EFI_STATUS Status;\r
+ UINT8 DigitUint8;\r
+ UINTN Index;\r
+ CHAR16 TemStr[2];\r
+\r
+ if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Buf = NULL;\r
+\r
+ TmpPtr = StringPtr;\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+ *Len = StringPtr - TmpPtr;\r
+ Length = *Len + 1;\r
+\r
+ Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (Str == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
+ *(Str + *Len) = L'\0';\r
+\r
+ Length = (Length + 1) / 2;\r
+ Buf = (UINT8 *) AllocateZeroPool (Length);\r
+ if (Buf == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ Length = *Len;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index ++) {\r
+ TemStr[0] = Str[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
+ *Number = Buf;\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ if (Str != NULL) {\r
+ FreePool (Str);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function merges DefaultAltCfgResp string into AltCfgResp string for\r
+ the missing AltCfgId in AltCfgResq.\r
+\r
+ @param AltCfgResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format. The default value string \r
+ will be merged into it. \r
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
+ <MultiConfigAltResp> format. The default value \r
+ string may contain more than one ConfigAltResp\r
+ string for the different varstore buffer.\r
+\r
+ @retval EFI_SUCCESS The merged string returns.\r
+ @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MergeDefaultString (\r
+ IN OUT EFI_STRING *AltCfgResp,\r
+ IN EFI_STRING DefaultAltCfgResp\r
+ )\r
+{\r
+ EFI_STRING StringPtrDefault;\r
+ EFI_STRING StringPtrEnd;\r
+ CHAR16 TempChar;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING AltConfigHdr;\r
+ UINTN HeaderLength;\r
+ UINTN SizeAltCfgResp;\r
+ \r
+ if (*AltCfgResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Get the requestr ConfigHdr\r
+ //\r
+ SizeAltCfgResp = 0;\r
+ StringPtr = *AltCfgResp;\r
+ \r
+ //\r
+ // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == L'\0') {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ StringPtr += StrLen (L"&PATH=");\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr ++;\r
+ }\r
+ HeaderLength = StringPtr - *AltCfgResp;\r
+\r
+ //\r
+ // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
+ //\r
+ AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16));\r
+ if (AltConfigHdr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StrCpy (AltConfigHdr, L"&");\r
+ StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength);\r
+ StrCat (AltConfigHdr, L"&ALTCFG=");\r
+ HeaderLength = StrLen (AltConfigHdr);\r
+ \r
+ StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+ while (StringPtrDefault != NULL) {\r
+ //\r
+ // Get AltCfg Name\r
+ //\r
+ StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4);\r
+ StringPtr = StrStr (*AltCfgResp, AltConfigHdr); \r
+ \r
+ //\r
+ // Append the found default value string to the input AltCfgResp\r
+ // \r
+ if (StringPtr == NULL) {\r
+ StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
+ SizeAltCfgResp = StrSize (*AltCfgResp);\r
+ if (StringPtrEnd == NULL) {\r
+ //\r
+ // No more default string is found.\r
+ //\r
+ *AltCfgResp = (EFI_STRING) ReallocatePool (\r
+ SizeAltCfgResp,\r
+ SizeAltCfgResp + StrSize (StringPtrDefault),\r
+ (VOID *) (*AltCfgResp)\r
+ );\r
+ if (*AltCfgResp == NULL) {\r
+ FreePool (AltConfigHdr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StrCat (*AltCfgResp, StringPtrDefault);\r
+ break;\r
+ } else {\r
+ TempChar = *StringPtrEnd;\r
+ *StringPtrEnd = L'\0';\r
+ *AltCfgResp = (EFI_STRING) ReallocatePool (\r
+ SizeAltCfgResp,\r
+ SizeAltCfgResp + StrSize (StringPtrDefault),\r
+ (VOID *) (*AltCfgResp)\r
+ );\r
+ if (*AltCfgResp == NULL) {\r
+ FreePool (AltConfigHdr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StrCat (*AltCfgResp, StringPtrDefault);\r
+ *StringPtrEnd = TempChar;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Find next AltCfg String\r
+ //\r
+ *(AltConfigHdr + HeaderLength) = L'\0';\r
+ StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr); \r
+ }\r
+ \r
+ FreePool (AltConfigHdr);\r
+ return EFI_SUCCESS; \r
+}\r
+\r
+/**\r
+ This function finds the matched DefaultName for the input DefaultId\r
+\r
+ @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.\r
+ @param VarDefaultId Default Id\r
+ @param VarDefaultName Default Name string ID for the input default ID.\r
+ \r
+ @retval EFI_SUCCESS The mapped default name string ID is found.\r
+ @retval EFI_NOT_FOUND The mapped default name string ID is not found.\r
+**/\r
+EFI_STATUS\r
+FindDefaultName (\r
+ IN IFR_DEFAULT_DATA *DefaultIdArray, \r
+ IN UINT16 VarDefaultId, \r
+ OUT EFI_STRING_ID *VarDefaultName\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_DEFAULT_DATA *DefaultData;\r
+\r
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
+ DefaultData = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultData->DefaultId == VarDefaultId) {\r
+ *VarDefaultName = DefaultData->DefaultName;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
+\r
+ @param BlockData The BlockData is updated to add new default value.\r
+ @param DefaultValueData The DefaultValue is added.\r
+\r
+**/\r
+VOID\r
+InsertDefaultValue (\r
+ IN IFR_BLOCK_DATA *BlockData,\r
+ IN IFR_DEFAULT_DATA *DefaultValueData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_DEFAULT_DATA *DefaultValueArray;\r
+\r
+ for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {\r
+ DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
+ if (DefaultValueData->OpCode == EFI_IFR_DEFAULT_OP) {\r
+ //\r
+ // Update the default value array in BlockData.\r
+ //\r
+ DefaultValueArray->Value = DefaultValueData->Value;\r
+ } else if (DefaultValueArray->OpCode != EFI_IFR_DEFAULT_OP) {\r
+ //\r
+ // Update the default value array in BlockData.\r
+ //\r
+ DefaultValueArray->Value = DefaultValueData->Value;\r
+ }\r
+ FreePool (DefaultValueData);\r
+ return;\r
+ } else if (DefaultValueArray->DefaultId > DefaultValueData->DefaultId) {\r
+ //\r
+ // Insert new default value data in the front of this default value array.\r
+ //\r
+ InsertTailList (Link, &DefaultValueData->Entry);\r
+ return;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Insert new default value data in tail.\r
+ //\r
+ InsertTailList (Link, &DefaultValueData->Entry);\r
+ return;\r
+}\r
+\r
+/**\r
+ This function inserts new BlockData into the block link\r
+\r
+ @param BlockLink The list entry points to block array.\r
+ @param BlockData The point to BlockData is added.\r
+ \r
+**/\r
+VOID\r
+InsertBlockData (\r
+ IN LIST_ENTRY *BlockLink,\r
+ IN IFR_BLOCK_DATA **BlockData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *BlockArray;\r
+ IFR_BLOCK_DATA *BlockSingleData;\r
+\r
+ BlockSingleData = *BlockData;\r
+ \r
+ //\r
+ // Insert block data in its Offset and Width order.\r
+ //\r
+ for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
+ BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (BlockArray->Offset == BlockSingleData->Offset) {\r
+ if (BlockArray->Width > BlockSingleData->Width) {\r
+ //\r
+ // Insert this block data in the front of block array\r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+ return;\r
+ }\r
+\r
+ if (BlockArray->Width == BlockSingleData->Width) {\r
+ //\r
+ // The same block array has been added.\r
+ //\r
+ FreePool (BlockSingleData);\r
+ *BlockData = BlockArray;\r
+ return;\r
+ }\r
+ } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
+ //\r
+ // Insert new block data in the front of block array \r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+ return;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Add new block data into the tail.\r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+ return; \r
+}\r
+\r
+/**\r
+ This function checks VarOffset and VarWidth is in the block range.\r
+\r
+ @param RequestBlockArray 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 *RequestBlockArray,\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 (RequestBlockArray == NULL) {\r
+ return TRUE;\r
+ }\r
+ \r
+ //\r
+ // Check the input var is in the request block range.\r
+ //\r
+ for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->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
+ This function parses Form Package to get the block array and the default\r
+ value array according to the request ConfigHdr.\r
+\r
+ @param Package Pointer to the form package data.\r
+ @param PackageLength Length of the pacakge.\r
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
+ the first found varstore will be as ConfigHdr.\r
+ @param RequestBlockArray The block array is retrieved from the request string.\r
+ @param VarStorageData VarStorage structure contains the got block and default value.\r
+ @param PIfrDefaultIdArray Point to the got default id and default name array.\r
+\r
+ @retval EFI_SUCCESS The block array and the default value array are got.\r
+ @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges\r
+ are conflicted. \r
+ @retval EFI_OUT_OF_RESOURCES No enough memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ParseIfrData (\r
+ IN UINT8 *Package,\r
+ IN UINT32 PackageLength,\r
+ IN EFI_STRING ConfigHdr,\r
+ IN IFR_BLOCK_DATA *RequestBlockArray,\r
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
+ OUT IFR_DEFAULT_DATA *DefaultIdArray\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN IfrOffset;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_IFR_ONE_OF *IfrOneOf;\r
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
+ EFI_IFR_DEFAULT *IfrDefault;\r
+ EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
+ EFI_IFR_CHECKBOX *IfrCheckBox;\r
+ EFI_IFR_PASSWORD *IfrPassword;\r
+ EFI_IFR_STRING *IfrString;\r
+ IFR_DEFAULT_DATA *DefaultData;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ CHAR16 *VarStoreName;\r
+ UINT16 VarOffset;\r
+ UINT16 VarWidth;\r
+ EFI_STRING_ID VarDefaultName;\r
+ UINT16 VarDefaultId;\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING TempStr;\r
+ UINTN LengthString;\r
+ BOOLEAN FirstOneOfOption;\r
+\r
+ LengthString = 0;\r
+ Status = EFI_SUCCESS;\r
+ GuidStr = NULL;\r
+ NameStr = NULL;\r
+ TempStr = NULL;\r
+ BlockData = NULL;\r
+ DefaultData = NULL;\r
+ VarDefaultName = 0;\r
+ FirstOneOfOption = FALSE;\r
+\r
+ //\r
+ // Go through the form package to parse OpCode one by one.\r
+ //\r
+ IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (IfrOffset < PackageLength) {\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);\r
+\r
+ switch (IfrOpHdr->OpCode) {\r
+ case EFI_IFR_VARSTORE_OP:\r
+ //\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStorageData->Size != 0) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the requied varstore information\r
+ // Add varstore by Guid and Name in ConfigHdr\r
+ // Make sure Offset is in varstore size and varstoreid\r
+ //\r
+ IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
+ VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);\r
+\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);\r
+ GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);\r
+ LengthString = StrLen (GuidStr);\r
+ LengthString = LengthString + StrLen (NameStr) + 1;\r
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
+ if (TempStr == NULL) {\r
+ FreePool (GuidStr);\r
+ FreePool (NameStr);\r
+ FreePool (VarStoreName);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StrCpy (TempStr, GuidStr);\r
+ StrCat (TempStr, NameStr);\r
+ if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {\r
+ //\r
+ // Find the matched VarStore\r
+ //\r
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);\r
+ VarStorageData->VarStoreId = IfrVarStore->VarStoreId;\r
+ VarStorageData->Size = IfrVarStore->Size;\r
+ VarStorageData->Name = VarStoreName;\r
+ } else {\r
+ //\r
+ // No found, free the allocated memory \r
+ //\r
+ FreePool (VarStoreName);\r
+ }\r
+ //\r
+ // Free alllocated temp string.\r
+ //\r
+ FreePool (GuidStr);\r
+ FreePool (NameStr);\r
+ FreePool (TempStr);\r
+ break;\r
+\r
+ case EFI_IFR_DEFAULTSTORE_OP:\r
+ //\r
+ // Add new the map between default id and default name.\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;\r
+ DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
+ InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry);\r
+ DefaultData = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+ //\r
+ // No matched varstore is found and directly return.\r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Numeric and OneOf has the same opcode structure.\r
+ //\r
+\r
+ //\r
+ // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. \r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\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 != VarStorageData->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+ VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage \r
+ //\r
+ if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = VarOffset;\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrOneOf->Question.QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ BlockData->Scope = IfrOpHdr->Scope;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ \r
+ if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
+ //\r
+ // Set this flag to TRUE for the first oneof option.\r
+ //\r
+ FirstOneOfOption = TRUE;\r
+ } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
+ //\r
+ // Numeric minimum value will be used as default value when no default is specified. \r
+ //\r
+\r
+ //\r
+ // Set standard ID and Get DefaultName String ID\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+\r
+ switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ DefaultData->Value = (UINT64) IfrOneOf->data.u8.MinValue;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ CopyMem (&DefaultData->Value, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ CopyMem (&DefaultData->Value, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ CopyMem (&DefaultData->Value, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
+ break;\r
+ }\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData); \r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // offset by question header\r
+ // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
+ // no default value and default id, how to define its default value?\r
+ //\r
+\r
+ //\r
+ // OrderedList question is not in IFR Form. This IFR form is not valid. \r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;\r
+ if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) {\r
+ BlockData = NULL;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;\r
+ VarWidth = IfrOrderedList->MaxContainers;\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = VarOffset;\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrOrderedList->Question.QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ BlockData->Scope = IfrOpHdr->Scope;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ //\r
+ // EFI_IFR_DEFAULT_OP\r
+ // offset by question header\r
+ // width is 1 sizeof (BOOLEAN)\r
+ // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
+ // value by DefaultOption\r
+ // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
+ // \r
+\r
+ //\r
+ // CheckBox question is not in IFR Form. This IFR form is not valid. \r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
+ if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+ VarWidth = (UINT16) sizeof (BOOLEAN);\r
+\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage \r
+ //\r
+ if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = VarOffset;\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrCheckBox->Question.QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ BlockData->Scope = IfrOpHdr->Scope;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ \r
+ //\r
+ // Add default value by CheckBox Flags \r
+ //\r
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
+ //\r
+ // Set standard ID to Manufacture ID and Get DefaultName String ID\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+ DefaultData->Value = 1;\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData);\r
+ }\r
+\r
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
+ //\r
+ // Set standard ID to Manufacture ID and Get DefaultName String ID\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+ DefaultData->Value = 1;\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // String question is not in IFR Form. This IFR form is not valid. \r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
+ if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ VarOffset = IfrString->Question.VarStoreInfo.VarOffset;\r
+ VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
+\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage \r
+ //\r
+ if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = VarOffset;\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrString->Question.QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ \r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ \r
+ //\r
+ // No default value for string.\r
+ //\r
+ BlockData = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_PASSWORD_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // Password question is not in IFR Form. This IFR form is not valid. \r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;\r
+ if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Get Offset/Width by Question header and OneOf Flags\r
+ //\r
+ VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;\r
+ VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));\r
+\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage \r
+ //\r
+ if ((VarOffset + VarWidth) > VarStorageData->Size) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = VarOffset;\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrPassword->Question.QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ \r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ \r
+ //\r
+ // No default value for string.\r
+ //\r
+ BlockData = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ //\r
+ // No matched block data is ignored.\r
+ //\r
+ if (BlockData == NULL || BlockData->Scope == 0) {\r
+ break;\r
+ }\r
+ \r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
+ if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
+ //\r
+ // Get ordered list option data type.\r
+ //\r
+ if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {\r
+ VarWidth = 1;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
+ VarWidth = 2;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
+ VarWidth = 4;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ VarWidth = 8;\r
+ } else {\r
+ //\r
+ // Invalid ordered list option data type.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ FreePool (BlockData);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Calculate Ordered list QuestionId width.\r
+ //\r
+ BlockData->Width = (UINT16) (BlockData->Width * VarWidth);\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ FreePool (BlockData);\r
+ BlockData = NULL;\r
+ break;\r
+ }\r
+ //\r
+ // Check this var question is in the var storage \r
+ //\r
+ if ((BlockData->Offset + BlockData->Width) > VarStorageData->Size) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ FreePool (BlockData);\r
+ goto Done;\r
+ }\r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ //\r
+ // No default data for OrderedList.\r
+ //\r
+ BlockData = NULL;\r
+ break;\r
+ }\r
+\r
+ if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
+ (BlockData->OpCode == EFI_IFR_ONE_OF_OP && FirstOneOfOption)) {\r
+ //\r
+ // This flag is used to specify whether this option is the first. Set it to FALSE for the following options. \r
+ // The first oneof option value will be used as default value when no default value is specified. \r
+ //\r
+ FirstOneOfOption = FALSE;\r
+ //\r
+ // Set standard ID to Manufacture ID and Get DefaultName String ID\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+ DefaultData->Value = IfrOneOfOption->Value.u64;\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData);\r
+ }\r
+\r
+ if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
+ //\r
+ // Set default ID to Manufacture ID and Get DefaultName String ID\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+ DefaultData->Value = IfrOneOfOption->Value.u64;\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_DEFAULT_OP:\r
+ //\r
+ // Update Current BlockData to the default value.\r
+ //\r
+ if (BlockData == NULL || BlockData->Scope == 0) {\r
+ //\r
+ // No matched block data is ignored. \r
+ //\r
+ break;\r
+ }\r
+\r
+ if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
+ //\r
+ // OrderedList Opcode is no default value.\r
+ //\r
+ break;\r
+ }\r
+ //\r
+ // Get the DefaultId and DefaultName String ID\r
+ //\r
+ IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
+ VarDefaultId = IfrDefault->DefaultId;\r
+ Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ DefaultData->OpCode = IfrOpHdr->OpCode;\r
+ DefaultData->DefaultId = VarDefaultId;\r
+ DefaultData->DefaultName = VarDefaultName;\r
+ DefaultData->Value = IfrDefault->Value.u64;\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, DefaultData);\r
+ break;\r
+ case EFI_IFR_END_OP:\r
+ //\r
+ // End Opcode is for Var question.\r
+ //\r
+ if (BlockData != NULL && BlockData->Scope > 0) {\r
+ BlockData->Scope--;\r
+ }\r
+ break;\r
+ default:\r
+ if (BlockData != NULL && BlockData->Scope > 0) {\r
+ BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
+ }\r
+ break;\r
+ }\r
+\r
+ IfrOffset += IfrOpHdr->Length;\r
+ }\r
+\r
+Done:\r
+ return Status; \r
+}\r
+\r
+/**\r
+ This function gets the full request string and full default value string by \r
+ parsing IFR data in HII form packages. \r
+ \r
+ When Request points to NULL string, the request string and default value string \r
+ for each varstore in form package will return. \r
+\r
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
+ @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
+ @param Request Pointer to a null-terminated Unicode string in\r
+ <ConfigRequest> format. When it doesn't contain\r
+ any RequestElement, it will be updated to return \r
+ the full RequestElement retrieved from IFR data.\r
+ If it points to NULL, the request string for the first\r
+ varstore in form package will be merged into a\r
+ <MultiConfigRequest> format string and return. \r
+ @param AltCfgResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format. When the pointer is to NULL,\r
+ the full default value string retrieved from IFR data\r
+ will return. When the pinter is to a string, the\r
+ full default value string retrieved from IFR data\r
+ will be merged into the input string and return.\r
+ When Request points to NULL, the default value string \r
+ for each varstore in form package will be merged into \r
+ a <MultiConfigAltResp> format string and return.\r
+ @param PointerProgress Optional parameter, it can be be NULL. \r
+ When it is not NULL, if Request is NULL, it returns NULL. \r
+ On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ & before the first failing name / value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name / value pair) if the request was\r
+ not successful.\r
+ @retval EFI_SUCCESS The Results string is set to the full request string.\r
+ And AltCfgResp contains all default value string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
+ @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string \r
+ can't be found in Form package.\r
+ @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
+ @retval EFI_INVALID_PARAMETER Request points to NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetFullStringFromHiiFormPackages (\r
+ IN HII_DATABASE_RECORD *DataBaseRecord,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN OUT EFI_STRING *Request,\r
+ IN OUT EFI_STRING *AltCfgResp,\r
+ OUT EFI_STRING *PointerProgress OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *HiiFormPackage;\r
+ UINTN PackageSize;\r
+ UINTN ResultSize;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *NextBlockData;\r
+ IFR_DEFAULT_DATA *DefaultValueData;\r
+ IFR_DEFAULT_DATA *DefaultId;\r
+ IFR_DEFAULT_DATA *DefaultIdArray;\r
+ IFR_VARSTORAGE_DATA *VarStorageData;\r
+ EFI_STRING DefaultAltCfgResp;\r
+ EFI_STRING FullConfigRequest;\r
+ EFI_STRING ConfigHdr;\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING PathStr;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING Progress;\r
+ UINTN Length;\r
+ UINT8 *TmpBuffer;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *LinkData;\r
+ LIST_ENTRY *LinkDefault;\r
+ BOOLEAN DataExist;\r
+\r
+ if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the local variables.\r
+ //\r
+ RequestBlockArray = NULL;\r
+ DefaultIdArray = NULL;\r
+ VarStorageData = NULL;\r
+ DefaultAltCfgResp = NULL;\r
+ FullConfigRequest = NULL;\r
+ ConfigHdr = NULL;\r
+ GuidStr = NULL;\r
+ NameStr = NULL;\r
+ PathStr = NULL;\r
+ HiiFormPackage = NULL;\r
+ ResultSize = 0;\r
+ PackageSize = 0;\r
+ DataExist = FALSE;\r
+ Progress = *Request;\r
+ \r
+ //\r
+ // 0. Get Hii Form Package by HiiHandle\r
+ //\r
+ Status = ExportFormPackages (\r
+ &mPrivate, \r
+ DataBaseRecord->Handle, \r
+ DataBaseRecord->PackageList, \r
+ 0, \r
+ PackageSize, \r
+ HiiFormPackage,\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ HiiFormPackage = AllocatePool (ResultSize);\r
+ if (HiiFormPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get HiiFormPackage by HiiHandle\r
+ //\r
+ PackageSize = ResultSize;\r
+ ResultSize = 0;\r
+ Status = ExportFormPackages (\r
+ &mPrivate, \r
+ DataBaseRecord->Handle, \r
+ DataBaseRecord->PackageList, \r
+ 0,\r
+ PackageSize, \r
+ HiiFormPackage,\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 1. Get the request block array by Request String when Request string containts the block array.\r
+ //\r
+ StringPtr = NULL;\r
+ if (*Request != NULL) {\r
+ StringPtr = *Request;\r
+ //\r
+ // Jump <ConfigHdr>\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
+ 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
+ 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
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr ++;\r
+ }\r
+ //\r
+ // Check the following string &OFFSET=\r
+ //\r
+ if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
+ Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ } else if (*StringPtr == L'\0') {\r
+ //\r
+ // No request block is found.\r
+ //\r
+ StringPtr = NULL;\r
+ }\r
+ }\r
+ if (StringPtr != NULL) {\r
+ //\r
+ // Init RequestBlockArray\r
+ //\r
+ RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (RequestBlockArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&RequestBlockArray->Entry);\r
+\r
+ //\r
+ // Get the request Block array from the request string\r
+ // Offset and Width\r
+ //\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
+ Progress = StringPtr;\r
+ StringPtr += StrLen (L"&OFFSET=");\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = GetValueOfNumber (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
+ \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 = GetValueOfNumber (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
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ BlockData->Offset = Offset;\r
+ BlockData->Width = Width;\r
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
+ \r
+ //\r
+ // Skip &VALUE string if &VALUE does exists.\r
+ //\r
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
+ StringPtr += StrLen (L"&VALUE=");\r
+\r
+ //\r
+ // Get Value\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_INVALID_PARAMETER;\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
+ // If '\0', parsing is finished. \r
+ //\r
+ if (*StringPtr == 0) {\r
+ break;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Merge the requested block data.\r
+ //\r
+ Link = RequestBlockArray->Entry.ForwardLink;\r
+ while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
+ if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
+ BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
+ }\r
+ RemoveEntryList (Link->ForwardLink);\r
+ FreePool (NextBlockData);\r
+ continue;\r
+ }\r
+ Link = Link->ForwardLink; \r
+ }\r
+ }\r
+ \r
+ //\r
+ // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
+ //\r
+\r
+ //\r
+ // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
+ //\r
+ DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultIdArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&DefaultIdArray->Entry);\r
+\r
+ //\r
+ // Initialize VarStorageData to store the var store Block and Default value information.\r
+ //\r
+ VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
+ if (VarStorageData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&VarStorageData->Entry);\r
+ InitializeListHead (&VarStorageData->BlockEntry);\r
+\r
+ //\r
+ // Parse the opcode in form pacakge to get the default setting.\r
+ //\r
+ Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ \r
+ //\r
+ // No requested varstore in IFR data and directly return\r
+ //\r
+ if (VarStorageData->Size == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
+ //\r
+\r
+ //\r
+ // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
+ //\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);\r
+ GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
+ GenerateSubStr (\r
+ L"PATH=",\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
+ (VOID *) DevicePath,\r
+ 1,\r
+ &PathStr\r
+ );\r
+ Length = StrLen (GuidStr);\r
+ Length = Length + StrLen (NameStr);\r
+ Length = Length + StrLen (PathStr) + 1;\r
+ ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (ConfigHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done; \r
+ }\r
+ StrCpy (ConfigHdr, GuidStr);\r
+ StrCat (ConfigHdr, NameStr);\r
+ StrCat (ConfigHdr, PathStr);\r
+\r
+ //\r
+ // Remove the last character L'&'\r
+ //\r
+ *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';\r
+\r
+ if (RequestBlockArray == NULL) {\r
+ //\r
+ // Append VarStorageData BlockEntry into *Request string\r
+ // Now support only one varstore in a form package.\r
+ //\r
+\r
+ //\r
+ // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
+ // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
+ //\r
+\r
+ //\r
+ // Compute the length of the entire request starting with <ConfigHdr> and a \r
+ // Null-terminator\r
+ //\r
+ DataExist = FALSE;\r
+ Length = StrLen (ConfigHdr) + 1;\r
+\r
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
+ //\r
+ // Add <BlockName> length for each Offset/Width pair\r
+ //\r
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
+ // | 8 | 4 | 7 | 4 |\r
+ //\r
+ DataExist = TRUE;\r
+ Length = Length + (8 + 4 + 7 + 4);\r
+ }\r
+ \r
+ //\r
+ // No any request block data is found. The request string can't be constructed.\r
+ //\r
+ if (!DataExist) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the entire <ConfigRequest>\r
+ //\r
+ FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (FullConfigRequest == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StringPtr = FullConfigRequest;\r
+ \r
+ //\r
+ // Start with <ConfigHdr>\r
+ //\r
+ StrCpy (StringPtr, ConfigHdr);\r
+ StringPtr += StrLen (StringPtr);\r
+\r
+ //\r
+ // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
+ //\r
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ //\r
+ // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr, \r
+ (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
+ L"&OFFSET=%04X&WIDTH=%04X", \r
+ BlockData->Offset, \r
+ BlockData->Width\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+ }\r
+ //\r
+ // Set to the got full request string.\r
+ //\r
+ HiiToLower (FullConfigRequest);\r
+ if (*Request != NULL) {\r
+ FreePool (*Request);\r
+ }\r
+ *Request = FullConfigRequest;\r
+ }\r
+ \r
+ //\r
+ // 4. Construct Default Value string in AltResp according to request element.\r
+ // Go through all VarStorageData Entry and get the DefaultId array for each one\r
+ // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
+ //\r
+ DataExist = FALSE;\r
+ //\r
+ // Add length for <ConfigHdr> + '\0'\r
+ //\r
+ Length = StrLen (ConfigHdr) + 1;\r
+ \r
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ //\r
+ // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 |\r
+ //\r
+ Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
+ \r
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
+ for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueData->DefaultId == DefaultId->DefaultId) {\r
+ //\r
+ // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
+ // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
+ //\r
+ Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
+ DataExist = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // No default value is found. The default string doesn't exist.\r
+ //\r
+ if (!DataExist) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the entire <DefaultAltCfgResp>\r
+ //\r
+ DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (DefaultAltCfgResp == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StringPtr = DefaultAltCfgResp;\r