+ // No matched block data is ignored.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the DefaultId\r
+ //\r
+ IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;\r
+ VarDefaultId = IfrDefault->DefaultId;\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.Type = DefaultValueFromOpcode;\r
+ DefaultData.DefaultId = VarDefaultId;\r
+ CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+\r
+ // If the value field is expression, set the cleaned flag.\r
+ if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
+ DefaultData.Cleaned = TRUE;\r
+ }\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+\r
+ //\r
+ // After insert the default value, reset the cleaned value for next \r
+ // time used. If not set here, need to set the value before everytime \r
+ // use it.\r
+ //\r
+ DefaultData.Cleaned = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_END_OP:\r
+ //\r
+ // End Opcode is for Var question.\r
+ //\r
+ if (BlockData != NULL) {\r
+ if (BlockData->Scope > 0) {\r
+ BlockData->Scope--;\r
+ }\r
+ if (BlockData->Scope == 0) {\r
+ BlockData = NULL;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ if (BlockData != NULL) {\r
+ if (BlockData->Scope > 0) {\r
+ BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);\r
+ }\r
+\r
+ if (BlockData->Scope == 0) {\r
+ BlockData = NULL;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ IfrOffset += IfrOpHdr->Length;\r
+ PackageOffset += IfrOpHdr->Length;\r
+ }\r
+\r
+Done:\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; ) {\r
+ DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ LinkDefault = LinkDefault->ForwardLink;\r
+ if (DefaultDataPtr->Cleaned == TRUE) {\r
+ RemoveEntryList (&DefaultDataPtr->Entry);\r
+ FreePool (DefaultDataPtr);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ parse the configrequest string, get the elements.\r
+\r
+ @param ConfigRequest The input configrequest string.\r
+ @param Progress Return the progress data.\r
+\r
+ @retval Block data pointer.\r
+**/\r
+IFR_BLOCK_DATA *\r
+GetBlockElement (\r
+ IN EFI_STRING ConfigRequest,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ EFI_STATUS Status;\r
+ UINT8 *TmpBuffer;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *NextBlockData;\r
+ UINTN Length;\r
+\r
+ TmpBuffer = NULL;\r
+\r
+ //\r
+ // Init RequestBlockArray\r
+ //\r
+ RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (RequestBlockArray == NULL) {\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
+ StringPtr = ConfigRequest;\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
+ 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
+ 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
+ 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
+ goto Done;\r
+ }\r
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\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
+ return RequestBlockArray;\r
+\r
+Done:\r
+ if (RequestBlockArray != NULL) {\r
+ //\r
+ // Free Link Array RequestBlockArray\r
+ //\r
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ FreePool (RequestBlockArray);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ parse the configrequest string, get the elements.\r
+\r
+ @param ConfigRequest The input config request string.\r
+ @param Progress Return the progress data.\r
+\r
+ @retval return data block array.\r
+**/\r
+IFR_BLOCK_DATA *\r
+GetNameElement (\r
+ IN EFI_STRING ConfigRequest,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING NextTag;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ BOOLEAN HasValue;\r
+\r
+ StringPtr = ConfigRequest;\r
+\r
+ //\r
+ // Init RequestBlockArray\r
+ //\r
+ RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (RequestBlockArray == NULL) {\r
+ goto Done;\r
+ }\r
+ InitializeListHead (&RequestBlockArray->Entry);\r
+\r
+ //\r
+ // Get the request Block array from the request string\r
+ //\r
+\r
+ //\r
+ // Parse each <RequestElement> if exists\r
+ // Only <BlockName> format is supported by this help function.\r
+ // <BlockName> ::= &'Name***=***\r
+ //\r
+ while (StringPtr != NULL && *StringPtr == L'&') {\r
+\r
+ *Progress = StringPtr;\r
+ //\r
+ // Skip the L"&" string\r
+ //\r
+ StringPtr += 1;\r
+\r
+ HasValue = FALSE;\r
+ if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
+ *NextTag = L'\0';\r
+ HasValue = TRUE;\r
+ } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
+ *NextTag = L'\0';\r
+ }\r
+\r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get Name\r
+ //\r
+ BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);\r
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
+\r
+ if (HasValue) {\r
+ //\r
+ // If has value, skip the value.\r
+ // \r
+ StringPtr = NextTag + 1;\r
+ *NextTag = L'=';\r
+ StringPtr = StrStr (StringPtr, L"&");\r
+ } else if (NextTag != NULL) {\r
+ //\r
+ // restore the '&' text.\r
+ //\r
+ StringPtr = NextTag;\r
+ *NextTag = L'&';\r
+ }\r
+ }\r
+\r
+ return RequestBlockArray;\r
+\r
+Done:\r
+ if (RequestBlockArray != NULL) {\r
+ //\r
+ // Free Link Array RequestBlockArray\r
+ //\r
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ FreePool (RequestBlockArray);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Generate ConfigRequest string base on the varstore info.\r
+\r
+ @param ConfigHdr The config header for this varstore.\r
+ @param VarStorageData The varstore info.\r
+ @param Status Return Status.\r
+ @param ConfigRequest The ConfigRequest info may be return.\r
+\r
+ @retval TRUE Need to continue\r
+ @retval Others NO need to continue or error occur.\r
+**/\r
+BOOLEAN\r
+GenerateConfigRequest (\r
+ IN CHAR16 *ConfigHdr,\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ OUT EFI_STATUS *Status,\r
+ IN OUT EFI_STRING *ConfigRequest\r
+ )\r
+{\r
+ BOOLEAN DataExist;\r
+ UINTN Length;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *FullConfigRequest;\r
+ CHAR16 *StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+\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
+ DataExist = TRUE;\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Add <BlockName> length for each Name\r
+ //\r
+ // <BlockName> ::= &Name1&Name2&... \r
+ // |1| StrLen(Name1)\r
+ //\r
+ Length = Length + (1 + StrLen (BlockData->Name));\r
+ } else {\r
+ //\r
+ // Add <BlockName> length for each Offset/Width pair\r
+ //\r
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
+ // | 8 | 4 | 7 | 4 |\r
+ //\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
+ return FALSE;\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
+ return FALSE;\r
+ }\r
+ StringPtr = FullConfigRequest;\r
+\r
+ //\r
+ // Start with <ConfigHdr>\r
+ //\r
+ StrCpyS (StringPtr, Length, 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
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Append &Name1\0\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
+ L"&%s",\r
+ BlockData->Name\r
+ );\r
+ } else {\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
+ }\r
+ StringPtr += StrLen (StringPtr);\r
+ }\r
+ //\r
+ // Set to the got full request string.\r
+ //\r
+ HiiToLower (FullConfigRequest);\r
+\r
+ if (*ConfigRequest != NULL) {\r
+ FreePool (*ConfigRequest);\r
+ }\r
+ *ConfigRequest = FullConfigRequest;\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Generate ConfigRequest Header base on the varstore info.\r
+\r
+ @param VarStorageData The varstore info.\r
+ @param DevicePath Device path for this varstore.\r
+ @param ConfigHdr The config header for this varstore.\r
+\r
+ @retval EFI_SUCCESS Generate the header success.\r
+ @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
+**/\r
+EFI_STATUS\r
+GenerateHdr (\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT EFI_STRING *ConfigHdr\r
+ )\r
+{\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING PathStr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ NameStr = NULL;\r
+ GuidStr = NULL;\r
+ PathStr = NULL;\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
+ if (VarStorageData->Name != NULL) {\r
+ GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);\r
+ } else {\r
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
+ }\r
+ GenerateSubStr (\r
+ L"PATH=",\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
+ (VOID *) DevicePath,\r
+ 1,\r
+ &PathStr\r
+ );\r
+ Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
+ if (VarStorageData->Name == NULL) {\r
+ Length += 1;\r
+ }\r
+\r
+ *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (*ConfigHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ StrCpyS (*ConfigHdr, Length, GuidStr);\r
+ StrCatS (*ConfigHdr, Length, NameStr);\r
+ if (VarStorageData->Name == NULL) {\r
+ StrCatS (*ConfigHdr, Length, L"&");\r
+ }\r
+ StrCatS (*ConfigHdr, Length, PathStr);\r
+\r
+ //\r
+ // Remove the last character L'&'\r
+ //\r
+ *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
+\r
+Done:\r
+ if (GuidStr != NULL) {\r
+ FreePool (GuidStr);\r
+ }\r
+\r
+ if (NameStr != NULL) {\r
+ FreePool (NameStr);\r
+ }\r
+\r
+ if (PathStr != NULL) {\r
+ FreePool (PathStr);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get Data buffer size based on data type.\r
+\r
+ @param ValueType The input data type.\r
+\r
+ @retval The data buffer size for the input type.\r
+**/\r
+UINT16\r
+GetStorageWidth (\r
+ IN UINT8 ValueType\r
+ )\r
+{\r
+ UINT16 StorageWidth;\r
+\r
+ switch (ValueType) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ StorageWidth = (UINT16) sizeof (UINT8);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ StorageWidth = (UINT16) sizeof (UINT16);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ StorageWidth = (UINT16) sizeof (UINT32);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ StorageWidth = (UINT16) sizeof (UINT64);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);\r
+ break;\r
+\r
+ default:\r
+ StorageWidth = 0;\r
+ break;\r
+ }\r
+\r
+ return StorageWidth;\r
+}\r
+\r
+/**\r
+ Generate ConfigAltResp string base on the varstore info.\r
+\r
+ @param HiiHandle Hii Handle for this hii package.\r
+ @param ConfigHdr The config header for this varstore.\r
+ @param VarStorageData The varstore info.\r
+ @param DefaultIdArray The Default id array.\r
+ @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
+\r
+ @retval TRUE Need to continue\r
+ @retval Others NO need to continue or error occur.\r
+**/\r
+EFI_STATUS\r
+GenerateAltConfigResp (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN CHAR16 *ConfigHdr,\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ IN IFR_DEFAULT_DATA *DefaultIdArray,\r
+ IN OUT EFI_STRING *DefaultAltCfgResp\r
+ )\r
+{\r
+ BOOLEAN DataExist;\r
+ UINTN Length;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *LinkData;\r
+ LIST_ENTRY *LinkDefault;\r
+ LIST_ENTRY *ListEntry;\r
+ CHAR16 *StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_DEFAULT_DATA *DefaultId;\r
+ IFR_DEFAULT_DATA *DefaultValueData;\r
+ UINTN Width;\r
+ UINT8 *TmpBuffer;\r
+ CHAR16 *DefaultString;\r
+\r
+ BlockData = NULL;\r
+ DataExist = FALSE;\r
+ DefaultString = NULL;\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
+ ListEntry = &BlockData->DefaultValueEntry;\r
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
+ continue;\r
+ }\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Add length for "&Name1=zzzzzzzzzzzz"\r
+ // |1|Name|1|Value|\r
+ //\r
+ Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
+ } else {\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
+ }\r
+ DataExist = TRUE;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // No default value is found. The default string doesn't exist.\r
+ //\r
+ if (!DataExist) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the entire <DefaultAltCfgResp>\r
+ //\r
+ *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (*DefaultAltCfgResp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StringPtr = *DefaultAltCfgResp;\r
+\r
+ //\r
+ // Start with <ConfigHdr>\r
+ //\r
+ StrCpyS (StringPtr, Length, ConfigHdr);\r
+ StringPtr += StrLen (StringPtr);\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 <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 |\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr, \r
+ (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), \r
+ L"&%s&ALTCFG=%04X", \r
+ ConfigHdr, \r
+ DefaultId->DefaultId\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+\r
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
+ ListEntry = &BlockData->DefaultValueEntry;\r
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
+ continue;\r
+ }\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ UnicodeSPrint (\r
+ StringPtr, \r
+ (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16), \r
+ L"&%s=", \r
+ BlockData->Name\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+ } else {\r
+ //\r
+ // Add <BlockConfig>\r
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr, \r
+ (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
+ L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
+ BlockData->Offset, \r
+ BlockData->Width\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r