X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FHiiDatabaseDxe%2FConfigRouting.c;h=665b951869d1a15e110c63a56da67df5a0fd8aba;hb=8567300ae4047da0891d62eedf50d407a23c5203;hp=d7ae31057370135f9676dce8bcf1cad8dff5fc9b;hpb=e90b081afa4bc51135aacdb1c4c581d01960a83b;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c index d7ae310573..665b951869 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c @@ -1,4 +1,5 @@ /** @file +Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL. Copyright (c) 2007 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials @@ -9,23 +10,11 @@ http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -Module Name: - - ConfigRouting.c - -Abstract: - - Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL. - -Revision History - - **/ #include "HiiDatabase.h" - -#ifndef _DISABLE_UNUSED_HII_PROTOCOLS_ +extern HII_DATABASE_PRIVATE_DATA mPrivate; /** Calculate the number of Unicode characters of the incoming Configuration string, @@ -44,7 +33,7 @@ CalculateConfigStringLen ( IN EFI_STRING String ) { - UINTN Length; + EFI_STRING TmpPtr; // // "GUID=" should be the first element of incoming string. @@ -52,19 +41,16 @@ CalculateConfigStringLen ( ASSERT (String != NULL); ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0); - Length = StrLen (L"GUID="); - String += Length; - // // The beginning of next / should be "&GUID=". // Will meet '\0' if there is only one /. - // - while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) { - Length++; - String++; + // + TmpPtr = StrStr (String, L"&GUID="); + if (TmpPtr == NULL) { + return StrLen (String); } - return Length; + return (TmpPtr - String); } @@ -92,6 +78,10 @@ GetDevicePath ( UINTN Length; EFI_STRING PathHdr; EFI_STRING DevicePathString; + UINT8 *DevicePathBuffer; + CHAR16 TemStr[2]; + UINTN Index; + UINT8 DigitUint8; if (String == NULL || DevicePath == NULL) { return EFI_INVALID_PARAMETER; @@ -126,196 +116,65 @@ GetDevicePath ( // as the device path resides in RAM memory. // Translate the data into binary. // - Length /= 2; - *DevicePath = (UINT8 *) AllocateZeroPool (Length); - if (*DevicePath == NULL) { - SafeFreePool (DevicePathString); + DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2); + if (DevicePathBuffer == NULL) { + FreePool (DevicePathString); return EFI_OUT_OF_RESOURCES; } - HexStringToBuffer (*DevicePath, &Length, DevicePathString); + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; DevicePathString[Index] != L'\0'; Index ++) { + TemStr[0] = DevicePathString[Index]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + DevicePathBuffer [Index/2] = DigitUint8; + } else { + DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8); + } + } - SafeFreePool (DevicePathString); + FreePool (DevicePathString); + + *DevicePath = DevicePathBuffer; return EFI_SUCCESS; } - /** - Extract Storage from all Form Packages in current hii database. - + Converts the unicode character of the string from uppercase to lowercase. This is a internal function. - @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance. - @param StorageListHead Storage link List head. - - @retval EFI_NOT_FOUND There is no form package in current hii database. - @retval EFI_INVALID_PARAMETER Any parameter is invalid. - @retval EFI_SUCCESS All existing storage is exported. + @param Str String to be converted **/ -EFI_STATUS -ExportAllStorage ( - IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase, - IN OUT LIST_ENTRY *StorageListHead -) +VOID +EFIAPI +HiiToLower ( + IN EFI_STRING ConfigString + ) { - EFI_STATUS Status; - UINTN BufferSize; - UINTN HandleCount; - EFI_HII_HANDLE *HandleBuffer; - UINTN Index; - UINTN Index2; - EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; - EFI_HII_PACKAGE_HEADER *Package; - UINT8 *OpCodeData; - UINT8 Operand; - UINT32 Offset; - HII_FORMSET_STORAGE *Storage; - EFI_HII_HANDLE HiiHandle; - EFI_HANDLE DriverHandle; - CHAR8 *AsciiString; - UINT32 PackageListLength; - EFI_HII_PACKAGE_HEADER PackageHeader; - - // - // Find the package list which contains Form package. - // - BufferSize = 0; - HandleBuffer = NULL; - Status = HiiListPackageLists ( - HiiDatabase, - EFI_HII_PACKAGE_FORM, - NULL, - &BufferSize, - HandleBuffer - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - HandleBuffer = AllocateZeroPool (BufferSize); - ASSERT (HandleBuffer != NULL); - - Status = HiiListPackageLists ( - HiiDatabase, - EFI_HII_PACKAGE_FORM, - NULL, - &BufferSize, - HandleBuffer - ); - } - if (EFI_ERROR (Status)) { - SafeFreePool (HandleBuffer); - return Status; - } - - HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); - for (Index = 0; Index < HandleCount; Index++) { - HiiHandle = HandleBuffer[Index]; - - BufferSize = 0; - HiiPackageList = NULL; - Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList); - if (Status == EFI_BUFFER_TOO_SMALL) { - HiiPackageList = AllocateZeroPool (BufferSize); - ASSERT (HiiPackageList != NULL); - Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList); - } - if (EFI_ERROR (Status)) { - SafeFreePool (HandleBuffer); - SafeFreePool (HiiPackageList); - return Status; - } - - // - // Get Form package from this HII package List - // - Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); - CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); - Package = NULL; - ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER)); - - while (Offset < PackageListLength) { - Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset); - CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); - if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) { - break; - } - Offset += PackageHeader.Length; - } - if (Offset >= PackageListLength) { - // - // Error here: No Form package found in this Package List - // - ASSERT (FALSE); - } - - // - // Search Storage definition in this Form package - // - Offset = sizeof (EFI_HII_PACKAGE_HEADER); - while (Offset < PackageHeader.Length) { - OpCodeData = ((UINT8 *) Package) + Offset; - Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - - Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; - - if ((Operand == EFI_IFR_VARSTORE_OP) || - (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) || - (Operand == EFI_IFR_VARSTORE_EFI_OP)) { - - Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE)); - ASSERT (Storage != NULL); - InsertTailList (StorageListHead, &Storage->Entry); - - Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE; - Storage->HiiHandle = HiiHandle; - - Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle); - if (EFI_ERROR (Status)) { - SafeFreePool (HandleBuffer); - SafeFreePool (HiiPackageList); - SafeFreePool (Storage); - return Status; - } - Storage->DriverHandle = DriverHandle; + EFI_STRING String; + BOOLEAN Lower; - if (Operand == EFI_IFR_VARSTORE_OP) { - Storage->Type = EFI_HII_VARSTORE_BUFFER; + ASSERT (ConfigString != NULL); - CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID)); - CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16)); - - AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name; - Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2); - ASSERT (Storage->Name != NULL); - for (Index2 = 0; AsciiString[Index2] != 0; Index2++) { - Storage->Name[Index2] = (CHAR16) AsciiString[Index2]; - } - // - // Append '\0' to the end of the unicode string. - // - Storage->Name[Index2] = 0; - } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) { - Storage->Type = EFI_HII_VARSTORE_NAME_VALUE; - - CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID)); - } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) { - Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE; - - CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID)); - } - } + // + // Convert all hex digits in range [A-F] in the configuration header to [a-f] + // + for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) { + if (*String == L'=') { + Lower = TRUE; + } else if (*String == L'&') { + Lower = FALSE; + } else if (Lower && *String >= L'A' && *String <= L'F') { + *String = (CHAR16) (*String - L'A' + L'a'); } - - SafeFreePool (HiiPackageList); } - SafeFreePool (HandleBuffer); - - return EFI_SUCCESS; + return; } - /** Generate a sub string then output it. @@ -323,12 +182,16 @@ ExportAllStorage ( @param String A constant string which is the prefix of the to be generated string, e.g. GUID= + @param BufferLen The length of the Buffer in bytes. + @param Buffer Points to a buffer which will be converted to be the - content of the generated string. - @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in - UINT8 *; if 2, the buffer contains unicode string for the value of NAME; - if 3, the buffer contains other data. + content of the generated string. + + @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in + UINT8 *; if 2, the buffer contains unicode string for the value of NAME; + if 3, the buffer contains other data. + @param SubStr Points to the output string. It's caller's responsibility to free this buffer. @@ -345,8 +208,11 @@ GenerateSubStr ( { UINTN Length; EFI_STRING Str; - EFI_STATUS Status; EFI_STRING StringHeader; + CHAR16 *TemString; + CHAR16 *TemName; + UINT8 *TemBuffer; + UINTN Index; ASSERT (String != NULL && SubStr != NULL); @@ -355,37 +221,61 @@ GenerateSubStr ( ASSERT (*SubStr != NULL); return ; } - + + // + // Header + Data + '&' + '\0' + // Length = StrLen (String) + BufferLen * 2 + 1 + 1; - Str = AllocateZeroPool (Length * sizeof (CHAR16)); + Str = AllocateZeroPool (Length * sizeof (CHAR16)); ASSERT (Str != NULL); StrCpy (Str, String); Length = (BufferLen * 2 + 1) * sizeof (CHAR16); - Status = EFI_SUCCESS; StringHeader = Str + StrLen (String); + TemString = (CHAR16 *) StringHeader; switch (Flag) { case 1: - Status = BufferToHexString (StringHeader, (UINT8 *) Buffer, BufferLen); + // + // Convert Buffer to Hex String in reverse order + // + TemBuffer = ((UINT8 *) Buffer); + for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2); + } break; case 2: - Status = UnicodeToConfigString (StringHeader, &Length, (CHAR16 *) Buffer); + // + // Check buffer is enough + // + TemName = (CHAR16 *) Buffer; + ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1)); + // + // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044" + // + for (; *TemName != L'\0'; TemName++) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4); + } break; case 3: - Status = BufToHexString (StringHeader, &Length, (UINT8 *) Buffer, BufferLen); // - // Convert the uppercase to lowercase since is defined in lowercase format. + // Convert Buffer to Hex String // - ToLower (StringHeader); + TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1; + for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2); + } break; default: break; } - ASSERT_EFI_ERROR (Status); - StrCat (Str, L"&"); + // + // Convert the uppercase to lowercase since is defined in lowercase format. + // + StrCat (Str, L"&"); + HiiToLower (Str); *SubStr = Str; } @@ -419,6 +309,13 @@ OutputConfigBody ( if (String == NULL || ConfigBody == NULL) { return EFI_INVALID_PARAMETER; } + + // + // The setting information should start OFFSET, not ALTCFG. + // + if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) { + return EFI_INVALID_PARAMETER; + } TmpPtr = StrStr (String, L"GUID="); if (TmpPtr == NULL) { @@ -443,49 +340,8 @@ OutputConfigBody ( *(Result + Length - 1) = 0; *ConfigBody = Result; return EFI_SUCCESS; - -} - - -#endif - -/** - Adjusts the size of a previously allocated buffer. - - - @param OldPool A pointer to the buffer whose size is being adjusted. - @param OldSize The size of the current buffer. - @param NewSize The size of the new buffer. - - @return The new buffer allocated. - -**/ -VOID * -ReallocatePool ( - IN VOID *OldPool, - IN UINTN OldSize, - IN UINTN NewSize - ) -{ - VOID *NewPool; - - NewPool = NULL; - if (NewSize != 0) { - NewPool = AllocateZeroPool (NewSize); - } - - if (OldPool != NULL) { - if (NewPool != NULL) { - CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); - } - - gBS->FreePool (OldPool); - } - - return NewPool; } - /** Append a string to a multi-string format. @@ -524,12 +380,12 @@ AppendToMultiString ( if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH || MultiStringSize > MAX_STRING_LENGTH) { *MultiString = (EFI_STRING) ReallocatePool ( - (VOID *) (*MultiString), MultiStringSize, - MultiStringSize + AppendStringSize + MultiStringSize + AppendStringSize, + (VOID *) (*MultiString) ); + ASSERT (*MultiString != NULL); } - // // Append the incoming string // @@ -570,48 +426,1616 @@ GetValueOfNumber ( EFI_STRING Str; UINT8 *Buf; EFI_STATUS Status; + UINT8 DigitUint8; + UINTN Index; + CHAR16 TemStr[2]; ASSERT (StringPtr != NULL && Number != NULL && Len != NULL); - ASSERT (*StringPtr != 0); + ASSERT (*StringPtr != L'\0'); Buf = NULL; TmpPtr = StringPtr; - while (*StringPtr != 0 && *StringPtr != L'&') { + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr++; + } + *Len = StringPtr - TmpPtr; + Length = *Len + 1; + + Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16)); + if (Str == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16)); + *(Str + *Len) = L'\0'; + + Length = (Length + 1) / 2; + Buf = (UINT8 *) AllocateZeroPool (Length); + if (Buf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + Length = *Len; + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < Length; Index ++) { + TemStr[0] = Str[Length - Index - 1]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + Buf [Index/2] = DigitUint8; + } else { + Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]); + } + } + + *Number = Buf; + Status = EFI_SUCCESS; + +Exit: + if (Str != NULL) { + FreePool (Str); + } + + return Status; +} + +/** + This function merges DefaultAltCfgResp string into AltCfgResp string for + the missing AltCfgId in AltCfgResq. + + @param AltCfgResp Pointer to a null-terminated Unicode string in + format. The default value string + will be merged into it. + @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in + format. The default value + string may contain more than one ConfigAltResp + string for the different varstore buffer. + + @retval EFI_SUCCESS The merged string returns. + @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL. +**/ +EFI_STATUS +EFIAPI +MergeDefaultString ( + IN OUT EFI_STRING *AltCfgResp, + IN EFI_STRING DefaultAltCfgResp + ) +{ + EFI_STRING StringPtrDefault; + EFI_STRING StringPtrEnd; + CHAR16 TempChar; + EFI_STRING StringPtr; + EFI_STRING AltConfigHdr; + UINTN HeaderLength; + UINTN SizeAltCfgResp; + + if (*AltCfgResp == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Get the requestr ConfigHdr + // + SizeAltCfgResp = 0; + StringPtr = *AltCfgResp; + + // + // Find GUID=...&NAME=...&PATH=... + // + if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) { + return EFI_INVALID_PARAMETER; + } + while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) { + StringPtr++; + } + while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) { StringPtr++; } - *Len = StringPtr - TmpPtr; - Length = *Len + 1; + if (*StringPtr == L'\0') { + return EFI_INVALID_PARAMETER; + } + StringPtr += StrLen (L"&PATH="); + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr ++; + } + HeaderLength = StringPtr - *AltCfgResp; + + // + // Construct AltConfigHdr string "&&ALTCFG=XXXX\0" + // |1| StrLen (ConfigHdr) | 8 | 4 | 1 | + // + AltConfigHdr = AllocateZeroPool ((1 + HeaderLength + 8 + 4 + 1) * sizeof (CHAR16)); + if (AltConfigHdr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + StrCpy (AltConfigHdr, L"&"); + StrnCat (AltConfigHdr, *AltCfgResp, HeaderLength); + StrCat (AltConfigHdr, L"&ALTCFG="); + HeaderLength = StrLen (AltConfigHdr); + + StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr); + while (StringPtrDefault != NULL) { + // + // Get AltCfg Name + // + StrnCat (AltConfigHdr, StringPtrDefault + HeaderLength, 4); + StringPtr = StrStr (*AltCfgResp, AltConfigHdr); + + // + // Append the found default value string to the input AltCfgResp + // + if (StringPtr == NULL) { + StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID"); + SizeAltCfgResp = StrSize (*AltCfgResp); + if (StringPtrEnd == NULL) { + // + // No more default string is found. + // + *AltCfgResp = (EFI_STRING) ReallocatePool ( + SizeAltCfgResp, + SizeAltCfgResp + StrSize (StringPtrDefault), + (VOID *) (*AltCfgResp) + ); + if (*AltCfgResp == NULL) { + FreePool (AltConfigHdr); + return EFI_OUT_OF_RESOURCES; + } + StrCat (*AltCfgResp, StringPtrDefault); + break; + } else { + TempChar = *StringPtrEnd; + *StringPtrEnd = L'\0'; + *AltCfgResp = (EFI_STRING) ReallocatePool ( + SizeAltCfgResp, + SizeAltCfgResp + StrSize (StringPtrDefault), + (VOID *) (*AltCfgResp) + ); + StrCat (*AltCfgResp, StringPtrDefault); + *StringPtrEnd = TempChar; + } + } + + // + // Find next AltCfg String + // + *(AltConfigHdr + HeaderLength) = L'\0'; + StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr); + } + + FreePool (AltConfigHdr); + return EFI_SUCCESS; +} + +/** + This function finds the matched DefaultName for the input DefaultId + + @param DefaultIdArray Array stores the map table between DefaultId and DefaultName. + @param VarDefaultId Default Id + @param VarDefaultName Default Name string ID for the input default ID. + + @retval EFI_SUCCESS The mapped default name string ID is found. + @retval EFI_NOT_FOUND The mapped default name string ID is not found. +**/ +EFI_STATUS +FindDefaultName ( + IN IFR_DEFAULT_DATA *DefaultIdArray, + IN UINT16 VarDefaultId, + OUT EFI_STRING_ID *VarDefaultName + ) +{ + LIST_ENTRY *Link; + IFR_DEFAULT_DATA *DefaultData; + + for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) { + DefaultData = BASE_CR (Link, IFR_DEFAULT_DATA, Entry); + if (DefaultData->DefaultId == VarDefaultId) { + *VarDefaultName = DefaultData->DefaultName; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + This function inserts new DefaultValueData into the BlockData DefaultValue array. + + @param BlockData The BlockData is updated to add new default value. + @param DefaultValueData The DefaultValue is added. + +**/ +VOID +InsertDefaultValue ( + IN IFR_BLOCK_DATA *BlockData, + IN IFR_DEFAULT_DATA *DefaultValueData + ) +{ + LIST_ENTRY *Link; + IFR_DEFAULT_DATA *DefaultValueArray; + + for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) { + DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry); + if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) { + // + // Update the default value array in BlockData. + // + DefaultValueArray->Value = DefaultValueData->Value; + FreePool (DefaultValueData); + return; + } else if (DefaultValueArray->DefaultId > DefaultValueData->DefaultId) { + // + // Insert new default value data in the front of this default value array. + // + InsertTailList (Link, &DefaultValueData->Entry); + return; + } + } + + // + // Insert new default value data in tail. + // + InsertTailList (Link, &DefaultValueData->Entry); + return; +} + +/** + This function inserts new BlockData into the block link + + @param BlockLink The list entry points to block array. + @param BlockData The point to BlockData is added. + +**/ +VOID +InsertBlockData ( + IN LIST_ENTRY *BlockLink, + IN IFR_BLOCK_DATA **BlockData + ) +{ + LIST_ENTRY *Link; + IFR_BLOCK_DATA *BlockArray; + IFR_BLOCK_DATA *BlockSingleData; + + BlockSingleData = *BlockData; + + // + // Insert block data in its Offset and Width order. + // + for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) { + BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry); + if (BlockArray->Offset == BlockSingleData->Offset) { + if (BlockArray->Width > BlockSingleData->Width) { + // + // Insert this block data in the front of block array + // + InsertTailList (Link, &BlockSingleData->Entry); + return; + } + + if (BlockArray->Width == BlockSingleData->Width) { + // + // The same block array has been added. + // + FreePool (BlockSingleData); + *BlockData = BlockArray; + return; + } + } else if (BlockArray->Offset > BlockSingleData->Offset) { + // + // Insert new block data in the front of block array + // + InsertTailList (Link, &BlockSingleData->Entry); + return; + } + } + + // + // Add new block data into the tail. + // + InsertTailList (Link, &BlockSingleData->Entry); + return; +} + +/** + This function checks VarOffset and VarWidth is in the block range. + + @param BlockArray The block array is to be checked. + @param VarOffset Offset of var to the structure + @param VarWidth Width of var. + + @retval TRUE This Var is in the block range. + @retval FALSE This Var is not in the block range. +**/ +BOOLEAN +BlockArrayCheck ( + IN IFR_BLOCK_DATA *RequestBlockArray, + IN UINT16 VarOffset, + IN UINT16 VarWidth + ) +{ + LIST_ENTRY *Link; + IFR_BLOCK_DATA *BlockData; + + // + // No Request Block array, all vars are got. + // + if (RequestBlockArray == NULL) { + return TRUE; + } + + // + // Check the input var is in the request block range. + // + for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) { + BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); + if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) { + return TRUE; + } + } + + return FALSE; +} + +/** + This function parses Form Package to get the block array and the default + value array according to the request ConfigHdr. + + @param Package Pointer to the form package data. + @param PackageLength Length of the pacakge. + @param ConfigHdr Request string ConfigHdr. If it is NULL, + the first found varstore will be as ConfigHdr. + @param RequestBlockArray The block array is retrieved from the request string. + @param VarStorageData VarStorage structure contains the got block and default value. + @param PIfrDefaultIdArray Point to the got default id and default name array. + + @retval EFI_SUCCESS The block array and the default value array are got. + @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges + are conflicted. + @retval EFI_OUT_OF_RESOURCES No enough memory. +**/ +EFI_STATUS +EFIAPI +ParseIfrData ( + IN UINT8 *Package, + IN UINT32 PackageLenth, + IN EFI_STRING ConfigHdr, + IN IFR_BLOCK_DATA *RequestBlockArray, + IN OUT IFR_VARSTORAGE_DATA *VarStorageData, + OUT IFR_DEFAULT_DATA *DefaultIdArray + ) +{ + EFI_STATUS Status; + UINTN IfrOffset; + EFI_IFR_VARSTORE *IfrVarStore; + EFI_IFR_OP_HEADER *IfrOpHdr; + EFI_IFR_ONE_OF *IfrOneOf; + EFI_IFR_ONE_OF_OPTION *IfrOneOfOption; + EFI_IFR_DEFAULT *IfrDefault; + EFI_IFR_ORDERED_LIST *IfrOrderedList; + EFI_IFR_CHECKBOX *IfrCheckBox; + EFI_IFR_PASSWORD *IfrPassword; + EFI_IFR_STRING *IfrString; + IFR_DEFAULT_DATA *DefaultData; + IFR_BLOCK_DATA *BlockData; + CHAR16 *VarStoreName; + UINT16 VarOffset; + UINT16 VarWidth; + EFI_STRING_ID VarDefaultName; + UINT16 VarDefaultId; + EFI_STRING GuidStr; + EFI_STRING NameStr; + EFI_STRING TempStr; + UINTN LengthString; + + LengthString = 0; + Status = EFI_SUCCESS; + GuidStr = NULL; + NameStr = NULL; + TempStr = NULL; + BlockData = NULL; + DefaultData = NULL; + + // + // Go through the form package to parse OpCode one by one. + // + IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER); + while (IfrOffset < PackageLenth) { + IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset); + + switch (IfrOpHdr->OpCode) { + case EFI_IFR_VARSTORE_OP: + // + // VarStore is found. Don't need to search any more. + // + if (VarStorageData->Size != 0) { + break; + } + + // + // Get the requied varstore information + // Add varstore by Guid and Name in ConfigHdr + // Make sure Offset is in varstore size and varstoreid + // + IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr; + VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16)); + if (VarStoreName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName); + + GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr); + GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr); + LengthString = StrLen (GuidStr); + LengthString = LengthString + StrLen (NameStr) + 1; + TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16)); + if (TempStr == NULL) { + FreePool (GuidStr); + FreePool (NameStr); + FreePool (VarStoreName); + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + StrCpy (TempStr, GuidStr); + StrCat (TempStr, NameStr); + if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) { + // + // Find the matched VarStore + // + CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid); + VarStorageData->VarStoreId = IfrVarStore->VarStoreId; + VarStorageData->Size = IfrVarStore->Size; + VarStorageData->Name = VarStoreName; + } else { + // + // No found, free the allocated memory + // + FreePool (VarStoreName); + } + // + // Free alllocated temp string. + // + FreePool (GuidStr); + FreePool (NameStr); + FreePool (TempStr); + break; + + case EFI_IFR_DEFAULTSTORE_OP: + // + // Add new the map between default id and default name. + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId; + DefaultData->DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName; + InsertTailList (&DefaultIdArray->Entry, &DefaultData->Entry); + DefaultData = NULL; + break; + + case EFI_IFR_FORM_OP: + // + // No matched varstore is found and directly return. + // + if (VarStorageData->Size == 0) { + Status = EFI_SUCCESS; + goto Done; + } + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + // + // Numeric and OneOf has the same opcode structure. + // + + // + // Numeric and OneOf question is not in IFR Form. This IFR form is not valid. + // + if (VarStorageData->Size == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Check whether this question is for the requested varstore. + // + IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr; + if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) { + break; + } + + // + // Get Offset/Width by Question header and OneOf Flags + // + VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset; + VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE)); + // + // Check whether this question is in requested block array. + // + if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) { + // + // This question is not in the requested string. Skip it. + // + break; + } + + // + // Check this var question is in the var storage + // + if ((VarOffset + VarWidth) > VarStorageData->Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = VarOffset; + BlockData->Width = VarWidth; + BlockData->QuestionId = IfrOneOf->Question.QuestionId; + BlockData->OpCode = IfrOpHdr->OpCode; + BlockData->Scope = IfrOpHdr->Scope; + InitializeListHead (&BlockData->DefaultValueEntry); + // + // Add Block Data into VarStorageData BlockEntry + // + InsertBlockData (&VarStorageData->BlockEntry, &BlockData); + break; + + case EFI_IFR_ORDERED_LIST_OP: + // + // offset by question header + // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type + // no default value and default id, how to define its default value? + // + + // + // OrderedList question is not in IFR Form. This IFR form is not valid. + // + if (VarStorageData->Size == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Check whether this question is for the requested varstore. + // + IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr; + if (IfrOrderedList->Question.VarStoreId != VarStorageData->VarStoreId) { + break; + } + + // + // Get Offset/Width by Question header and OneOf Flags + // + VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset; + VarWidth = IfrOrderedList->MaxContainers; + + // + // Check whether this question is in requested block array. + // + if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) { + // + // This question is not in the requested string. Skip it. + // + break; + } + + // + // Check this var question is in the var storage + // + if ((VarOffset + VarWidth) > VarStorageData->Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = VarOffset; + BlockData->Width = VarWidth; + BlockData->QuestionId = IfrOrderedList->Question.QuestionId; + BlockData->OpCode = IfrOpHdr->OpCode; + BlockData->Scope = IfrOpHdr->Scope; + InitializeListHead (&BlockData->DefaultValueEntry); + + // + // Add Block Data into VarStorageData BlockEntry + // + InsertBlockData (&VarStorageData->BlockEntry, &BlockData); + break; + + case EFI_IFR_CHECKBOX_OP: + // + // EFI_IFR_DEFAULT_OP + // offset by question header + // width is 1 sizeof (BOOLEAN) + // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set. + // value by DefaultOption + // default id by DeaultOption DefaultId can override CheckBox Flags and Default value. + // + + // + // CheckBox question is not in IFR Form. This IFR form is not valid. + // + if (VarStorageData->Size == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Check whether this question is for the requested varstore. + // + IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr; + if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) { + break; + } + + // + // Get Offset/Width by Question header and OneOf Flags + // + VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset; + VarWidth = sizeof (BOOLEAN); + + // + // Check whether this question is in requested block array. + // + if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) { + // + // This question is not in the requested string. Skip it. + // + break; + } + + // + // Check this var question is in the var storage + // + if ((VarOffset + VarWidth) > VarStorageData->Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = VarOffset; + BlockData->Width = VarWidth; + BlockData->QuestionId = IfrCheckBox->Question.QuestionId; + BlockData->OpCode = IfrOpHdr->OpCode; + BlockData->Scope = IfrOpHdr->Scope; + InitializeListHead (&BlockData->DefaultValueEntry); + // + // Add Block Data into VarStorageData BlockEntry + // + InsertBlockData (&VarStorageData->BlockEntry, &BlockData); + + // + // Add default value by CheckBox Flags + // + if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) { + // + // Set standard ID to Manufacture ID and Get DefaultName String ID + // + VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Prepare new DefaultValue + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = VarDefaultId; + DefaultData->DefaultName = VarDefaultName; + DefaultData->Value = 1; + // + // Add DefaultValue into current BlockData + // + InsertDefaultValue (BlockData, DefaultData); + } + + if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) { + // + // Set standard ID to Manufacture ID and Get DefaultName String ID + // + VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; + Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Prepare new DefaultValue + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = VarDefaultId; + DefaultData->DefaultName = VarDefaultName; + DefaultData->Value = 1; + // + // Add DefaultValue into current BlockData + // + InsertDefaultValue (BlockData, DefaultData); + } + break; + + case EFI_IFR_STRING_OP: + // + // offset by question header + // width MaxSize * sizeof (CHAR16) + // no default value, only block array + // + + // + // String question is not in IFR Form. This IFR form is not valid. + // + if (VarStorageData->Size == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Check whether this question is for the requested varstore. + // + IfrString = (EFI_IFR_STRING *) IfrOpHdr; + if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) { + break; + } + + // + // Get Offset/Width by Question header and OneOf Flags + // + VarOffset = IfrString->Question.VarStoreInfo.VarOffset; + VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16)); + + // + // Check whether this question is in requested block array. + // + if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) { + // + // This question is not in the requested string. Skip it. + // + break; + } + + // + // Check this var question is in the var storage + // + if ((VarOffset + VarWidth) > VarStorageData->Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = VarOffset; + BlockData->Width = VarWidth; + BlockData->QuestionId = IfrString->Question.QuestionId; + BlockData->OpCode = IfrOpHdr->OpCode; + InitializeListHead (&BlockData->DefaultValueEntry); + + // + // Add Block Data into VarStorageData BlockEntry + // + InsertBlockData (&VarStorageData->BlockEntry, &BlockData); + + // + // No default value for string. + // + BlockData = NULL; + break; + + case EFI_IFR_PASSWORD_OP: + // + // offset by question header + // width MaxSize * sizeof (CHAR16) + // no default value, only block array + // + + // + // Password question is not in IFR Form. This IFR form is not valid. + // + if (VarStorageData->Size == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Check whether this question is for the requested varstore. + // + IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr; + if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) { + break; + } + + // + // Get Offset/Width by Question header and OneOf Flags + // + VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset; + VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16)); + + // + // Check whether this question is in requested block array. + // + if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) { + // + // This question is not in the requested string. Skip it. + // + break; + } + + // + // Check this var question is in the var storage + // + if ((VarOffset + VarWidth) > VarStorageData->Size) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = VarOffset; + BlockData->Width = VarWidth; + BlockData->QuestionId = IfrPassword->Question.QuestionId; + BlockData->OpCode = IfrOpHdr->OpCode; + InitializeListHead (&BlockData->DefaultValueEntry); + + // + // Add Block Data into VarStorageData BlockEntry + // + InsertBlockData (&VarStorageData->BlockEntry, &BlockData); + + // + // No default value for string. + // + BlockData = NULL; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + // + // No matched block data is ignored. + // + if (BlockData == NULL || BlockData->Scope == 0) { + break; + } + + IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr; + if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) { + // + // Get ordered list option data type. + // + if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) { + VarWidth = 1; + } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) { + VarWidth = 2; + } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) { + VarWidth = 4; + } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) { + VarWidth = 8; + } else { + // + // Invalid ordered list option data type. + // + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // Calculate Ordered list QuestionId width. + // + BlockData->Width = (UINT16) (BlockData->Width * VarWidth); + BlockData = NULL; + break; + } + + if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) { + // + // Set standard ID to Manufacture ID and Get DefaultName String ID + // + VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Prepare new DefaultValue + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = VarDefaultId; + DefaultData->DefaultName = VarDefaultName; + DefaultData->Value = IfrOneOfOption->Value.u64; + // + // Add DefaultValue into current BlockData + // + InsertDefaultValue (BlockData, DefaultData); + } + + if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) { + // + // Set default ID to Manufacture ID and Get DefaultName String ID + // + VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; + Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Prepare new DefaultValue + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = VarDefaultId; + DefaultData->DefaultName = VarDefaultName; + DefaultData->Value = IfrOneOfOption->Value.u64; + // + // Add DefaultValue into current BlockData + // + InsertDefaultValue (BlockData, DefaultData); + } + break; + + case EFI_IFR_DEFAULT_OP: + // + // Update Current BlockData to the default value. + // + if (BlockData == NULL || BlockData->Scope == 0) { + // + // No matched block data is ignored. + // + break; + } + + if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) { + // + // OrderedList Opcode is no default value. + // + break; + } + // + // Get the DefaultId and DefaultName String ID + // + IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr; + VarDefaultId = IfrDefault->DefaultId; + Status = FindDefaultName (DefaultIdArray, VarDefaultId, &VarDefaultName); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Prepare new DefaultValue + // + DefaultData = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + DefaultData->DefaultId = VarDefaultId; + DefaultData->DefaultName = VarDefaultName; + DefaultData->Value = IfrDefault->Value.u64; + // + // Add DefaultValue into current BlockData + // + InsertDefaultValue (BlockData, DefaultData); + break; + case EFI_IFR_END_OP: + // + // End Opcode is for Var question. + // + if (BlockData != NULL && BlockData->Scope > 0) { + BlockData->Scope--; + } + break; + default: + if (BlockData != NULL && BlockData->Scope > 0) { + BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope); + } + break; + } + + IfrOffset += IfrOpHdr->Length; + } + +Done: + return Status; +} + +/** + This function gets the full request string and full default value string by + parsing IFR data in HII form packages. + + When Request points to NULL string, the request string and default value string + for each varstore in form package will return. + + @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package. + @param DevicePath Device Path which Hii Config Access Protocol is registered. + @param Request Pointer to a null-terminated Unicode string in + format. When it doesn't contain + any RequestElement, it will be updated to return + the full RequestElement retrieved from IFR data. + If it points to NULL, the request string for the first + varstore in form package will be merged into a + format string and return. + @param AltCfgResp Pointer to a null-terminated Unicode string in + format. When the pointer is to NULL, + the full default value string retrieved from IFR data + will return. When the pinter is to a string, the + full default value string retrieved from IFR data + will be merged into the input string and return. + When Request points to NULL, the default value string + for each varstore in form package will be merged into + a format string and return. + @retval EFI_SUCCESS The Results string is set to the full request string. + And AltCfgResp contains all default value string. + @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string. + @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string + can't be found in Form package. + @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle. + @retval EFI_INVALID_PARAMETER *Request points to NULL. + +**/ +EFI_STATUS +EFIAPI +GetFullStringFromHiiFormPackages ( + IN HII_DATABASE_RECORD *DataBaseRecord, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN OUT EFI_STRING *Request, + IN OUT EFI_STRING *AltCfgResp + ) +{ + EFI_STATUS Status; + UINT8 *HiiFormPackage; + UINTN PackageSize; + UINTN ResultSize; + IFR_BLOCK_DATA *RequestBlockArray; + IFR_BLOCK_DATA *BlockData; + IFR_BLOCK_DATA *NextBlockData; + IFR_DEFAULT_DATA *DefaultValueData; + IFR_DEFAULT_DATA *DefaultId; + IFR_DEFAULT_DATA *DefaultIdArray; + IFR_VARSTORAGE_DATA *VarStorageData; + EFI_STRING DefaultAltCfgResp; + EFI_STRING FullConfigRequest; + EFI_STRING ConfigHdr; + EFI_STRING GuidStr; + EFI_STRING NameStr; + EFI_STRING PathStr; + EFI_STRING StringPtr; + UINTN Length; + UINT8 *TmpBuffer; + UINT16 Offset; + UINT16 Width; + LIST_ENTRY *Link; + LIST_ENTRY *LinkData; + LIST_ENTRY *LinkDefault; + + // + // Initialize the local variables. + // + RequestBlockArray = NULL; + DefaultIdArray = NULL; + VarStorageData = NULL; + DefaultAltCfgResp = NULL; + FullConfigRequest = NULL; + ConfigHdr = NULL; + GuidStr = NULL; + NameStr = NULL; + PathStr = NULL; + HiiFormPackage = NULL; + ResultSize = 0; + PackageSize = 0; + + // + // 0. Get Hii Form Package by HiiHandle + // + Status = ExportFormPackages ( + &mPrivate, + DataBaseRecord->Handle, + DataBaseRecord->PackageList, + 0, + PackageSize, + HiiFormPackage, + &ResultSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + HiiFormPackage = AllocatePool (ResultSize); + if (HiiFormPackage == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Get HiiFormPackage by HiiHandle + // + PackageSize = ResultSize; + ResultSize = 0; + Status = ExportFormPackages ( + &mPrivate, + DataBaseRecord->Handle, + DataBaseRecord->PackageList, + 0, + PackageSize, + HiiFormPackage, + &ResultSize + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // 1. Get the request block array by Request String when Request string containts the block array. + // + StringPtr = NULL; + if (*Request != NULL) { + StringPtr = StrStr (*Request, L"&OFFSET="); + } + if (StringPtr != NULL) { + // + // Init RequestBlockArray + // + RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (RequestBlockArray == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + InitializeListHead (&RequestBlockArray->Entry); + + // + // Get the request Block array from the request string + // Offset and Width + // + + // + // Parse each if exists + // Only format is supported by this help function. + // ::= &'OFFSET='&'WIDTH=' + // + while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) { + // + // Skip the OFFSET string + // + StringPtr += StrLen (L"&OFFSET="); + // + // Get Offset + // + Status = GetValueOfNumber (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); + + StringPtr += Length; + if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + StringPtr += StrLen (L"&WIDTH="); + + // + // Get Width + // + Status = GetValueOfNumber (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); + + StringPtr += Length; + if (*StringPtr != 0 && *StringPtr != L'&') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Set Block Data + // + BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA)); + if (BlockData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + BlockData->Offset = Offset; + BlockData->Width = Width; + InsertBlockData (&RequestBlockArray->Entry, &BlockData); + + // + // If '\0', parsing is finished. + // + if (*StringPtr == 0) { + break; + } + } + + // + // Merge the requested block data. + // + Link = RequestBlockArray->Entry.ForwardLink; + while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) { + BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); + NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry); + if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) { + if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) { + BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset); + } + RemoveEntryList (Link->ForwardLink); + FreePool (NextBlockData); + continue; + } + Link = Link->ForwardLink; + } + } + + // + // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray. + // + + // + // Initialize DefaultIdArray to store the map between DeaultId and DefaultName + // + DefaultIdArray = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA)); + if (DefaultIdArray == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + InitializeListHead (&DefaultIdArray->Entry); + + // + // Initialize VarStorageData to store the var store Block and Default value information. + // + VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA)); + if (VarStorageData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + InitializeListHead (&VarStorageData->Entry); + InitializeListHead (&VarStorageData->BlockEntry); + + // + // Parse the opcode in form pacakge to get the default setting. + // + Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // No requested varstore in IFR data and directly return + // + if (VarStorageData->Size == 0) { + goto Done; + } + + // + // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case. + // + + // + // Construct : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle + // + GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr); + GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr); + GenerateSubStr ( + L"PATH=", + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath), + (VOID *) DevicePath, + 1, + &PathStr + ); + Length = StrLen (GuidStr); + Length = Length + StrLen (NameStr); + Length = Length + StrLen (PathStr) + 1; + ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16)); + if (ConfigHdr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + StrCpy (ConfigHdr, GuidStr); + StrCat (ConfigHdr, NameStr); + StrCat (ConfigHdr, PathStr); + + // + // Remove the last character L'&' + // + *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0'; + + if (RequestBlockArray == NULL) { + // + // Append VarStorageData BlockEntry into *Request string + // Now support only one varstore in a form package. + // + + // + // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package + // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig + // + + // + // Compute the length of the entire request starting with and a + // Null-terminator + // + Length = StrLen (ConfigHdr) + 1; + + for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) { + // + // Add length for each Offset/Width pair + // + // ::= &OFFSET=1234&WIDTH=1234 + // | 8 | 4 | 7 | 4 | + // + Length = Length + (8 + 4 + 7 + 4); + } + + // + // Allocate buffer for the entire + // + FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16)); + if (FullConfigRequest == NULL) { + goto Done; + } + StringPtr = FullConfigRequest; + + // + // Start with + // + StrCpy (StringPtr, ConfigHdr); + StringPtr += StrLen (StringPtr); + + // + // Loop through all the Offset/Width pairs and append them to ConfigRequest + // + for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) { + BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry); + // + // Append &OFFSET=XXXX&WIDTH=YYYY\0 + // + UnicodeSPrint ( + StringPtr, + (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16), + L"&OFFSET=%04X&WIDTH=%04X", + BlockData->Offset, + BlockData->Width + ); + StringPtr += StrLen (StringPtr); + } + // + // Set to the got full request string. + // + HiiToLower (FullConfigRequest); + if (*Request != NULL) { + FreePool (*Request); + } + *Request = FullConfigRequest; + } + + // + // 4. Construct Default Value string in AltResp according to request element. + // Go through all VarStorageData Entry and get the DefaultId array for each one + // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody + // + + // + // Add length for + '\0' + // + Length = StrLen (ConfigHdr) + 1; + + for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) { + DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry); + // + // Add length for "&&ALTCFG=XXXX" + // |1| StrLen (ConfigHdr) | 8 | 4 | + // + Length += (1 + StrLen (ConfigHdr) + 8 + 4); + + for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) { + BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry); + for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) { + DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry); + if (DefaultValueData->DefaultId == DefaultId->DefaultId) { + // + // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz" + // | 8 | 4 | 7 | 4 | 7 | Width * 2 | + // + Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2); + } + } + } + } + + // + // Allocate buffer for the entire + // + DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16)); + if (DefaultAltCfgResp == NULL) { + goto Done; + } + StringPtr = DefaultAltCfgResp; + + // + // Start with + // + StrCpy (StringPtr, ConfigHdr); + StringPtr += StrLen (StringPtr); + + for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) { + DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry); + // + // Add of the form "&&ALTCFG=XXXX\0" + // |1| StrLen (ConfigHdr) | 8 | 4 | + // + UnicodeSPrint ( + StringPtr, + (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16), + L"&%s&ALTCFG=%04X", + ConfigHdr, + DefaultId->DefaultName + ); + StringPtr += StrLen (StringPtr); + + for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) { + BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry); + for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) { + DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry); + if (DefaultValueData->DefaultId == DefaultId->DefaultId) { + // + // Add + // ::= 'OFFSET='&'WIDTH='&'VALUE'= + // + UnicodeSPrint ( + StringPtr, + (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16), + L"&OFFSET=%04X&WIDTH=%04X&VALUE=", + BlockData->Offset, + BlockData->Width + ); + StringPtr += StrLen (StringPtr); + + // + // Convert Value to a hex string in "%x" format + // NOTE: This is in the opposite byte that GUID and PATH use + // + Width = BlockData->Width; + TmpBuffer = (UINT8 *) &(DefaultValueData->Value); + for (; Width > 0; Width--) { + StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2); + } + } + } + } + } + HiiToLower (DefaultAltCfgResp); - Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING)); - if (Str == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; + // + // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL. + // + if (*AltCfgResp != NULL) { + Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp); + FreePool (DefaultAltCfgResp); + } else { + *AltCfgResp = DefaultAltCfgResp; } - CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16)); - *(Str + *Len) = 0; - Length = (Length + 1) / 2; - Buf = (UINT8 *) AllocateZeroPool (Length); - if (Buf == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; +Done: + if (RequestBlockArray != NULL) { + // + // Free Link Array RequestBlockArray + // + while (!IsListEmpty (&RequestBlockArray->Entry)) { + BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry); + RemoveEntryList (&BlockData->Entry); + FreePool (BlockData); + } + + FreePool (RequestBlockArray); + } + + if (VarStorageData != NULL) { + // + // Free link array VarStorageData + // + while (!IsListEmpty (&VarStorageData->BlockEntry)) { + BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry); + RemoveEntryList (&BlockData->Entry); + // + // Free default value link array + // + while (!IsListEmpty (&BlockData->DefaultValueEntry)) { + DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry); + RemoveEntryList (&DefaultValueData->Entry); + FreePool (DefaultValueData); + } + FreePool (BlockData); + } + FreePool (VarStorageData); } - Status = HexStringToBuf (Buf, &Length, Str, NULL); - if (EFI_ERROR (Status)) { - goto Exit; + if (DefaultIdArray != NULL) { + // + // Free DefaultId Array + // + while (!IsListEmpty (&DefaultIdArray->Entry)) { + DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry); + RemoveEntryList (&DefaultId->Entry); + FreePool (DefaultId); + } + FreePool (DefaultIdArray); + } + + // + // Free the allocated string + // + if (GuidStr != NULL) { + FreePool (GuidStr); + } + if (NameStr != NULL) { + FreePool (NameStr); + } + if (PathStr != NULL) { + FreePool (PathStr); + } + if (ConfigHdr != NULL) { + FreePool (ConfigHdr); } - *Number = Buf; - Status = EFI_SUCCESS; + // + // Free Pacakge data + // + if (HiiFormPackage != NULL) { + FreePool (HiiFormPackage); + } -Exit: - SafeFreePool (Str); return Status; } - /** This function allows a caller to extract the current configuration for one or more named elements from one or more drivers. @@ -660,23 +2084,25 @@ HiiConfigRoutingExtractConfig ( OUT EFI_STRING *Results ) { -#ifndef _DISABLE_UNUSED_HII_PROTOCOLS_ - HII_DATABASE_PRIVATE_DATA *Private; EFI_STRING StringPtr; EFI_STRING ConfigRequest; UINTN Length; EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_STATUS Status; LIST_ENTRY *Link; HII_DATABASE_RECORD *Database; + UINT8 *DevicePathPkg; UINT8 *CurrentDevicePath; EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; EFI_STRING AccessProgress; EFI_STRING AccessResults; - UINTN RemainSize; - EFI_STRING TmpPtr; + EFI_STRING DefaultResults; + BOOLEAN FirstElement; + UINTN DevicePathLength; if (This == NULL || Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; @@ -690,6 +2116,11 @@ HiiConfigRoutingExtractConfig ( Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This); StringPtr = Request; *Progress = StringPtr; + DefaultResults = NULL; + ConfigRequest = NULL; + Status = EFI_SUCCESS; + AccessResults = NULL; + DevicePath = NULL; // // The first element of should be @@ -699,6 +2130,8 @@ HiiConfigRoutingExtractConfig ( return EFI_INVALID_PARAMETER; } + FirstElement = TRUE; + // // Allocate a fix length of memory to store Results. Reallocate memory for // Results if this fix length is insufficient. @@ -725,7 +2158,8 @@ HiiConfigRoutingExtractConfig ( Length = CalculateConfigStringLen (StringPtr); ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr); if (ConfigRequest == NULL) { - return EFI_OUT_OF_RESOURCES; + Status = EFI_OUT_OF_RESOURCES; + goto Done; } *(ConfigRequest + Length) = 0; @@ -734,42 +2168,76 @@ HiiConfigRoutingExtractConfig ( // Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath); if (EFI_ERROR (Status)) { - SafeFreePool (ConfigRequest); - return Status; + goto Done; } // // Find driver which matches the routing data. // - DriverHandle = NULL; + DriverHandle = NULL; + HiiHandle = NULL; + Database = NULL; + DevicePathLength = GetDevicePathSize (DevicePath); for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink ) { Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); - CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); - if (CurrentDevicePath != NULL) { - if (CompareMem ( + + if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) { + CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); + if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) && + (CompareMem ( DevicePath, CurrentDevicePath, - GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath) - ) == 0) { + DevicePathLength + ) == 0)) { DriverHandle = Database->DriverHandle; + HiiHandle = Database->Handle; break; } } } - - SafeFreePool (DevicePath); - + + // + // Try to find driver handle by device path. + // if (DriverHandle == NULL) { + TempDevicePath = DevicePath; + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempDevicePath, + &DriverHandle + ); + if (EFI_ERROR (Status) || (DriverHandle == NULL)) { + // + // Routing data does not match any known driver. + // Set Progress to the 'G' in "GUID" of the routing header. + // + *Progress = StringPtr; + Status = EFI_NOT_FOUND; + goto Done; + } + } + + // + // Check whether ConfigRequest contains request string OFFSET/WIDTH + // + if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) { // - // Routing data does not match any known driver. - // Set Progress to the 'G' in "GUID" of the routing header. + // Get the full request string from IFR when HiiPackage is registered to HiiHandle // - *Progress = StringPtr; - SafeFreePool (ConfigRequest); - return EFI_NOT_FOUND; + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Not any request block is found. + // + if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) { + AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest); + goto NextConfigString; + } } // @@ -793,23 +2261,55 @@ HiiConfigRoutingExtractConfig ( // AccessProgress indicates the parsing progress on . // Map it to the progress on then return it. // - RemainSize = StrSize (AccessProgress); - for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++); - *Progress = TmpPtr; - - SafeFreePool (ConfigRequest); - return Status; + *Progress = StrStr (StringPtr, AccessProgress); + goto Done; } // - // Attach this to a + // Attach this to a . There is a '&' + // which seperates the first and the following ones. // ASSERT (*AccessProgress == 0); + + // + // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle + // + if (HiiHandle != NULL) { + if (DefaultResults == NULL) { + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &AccessResults); + } else { + Status = MergeDefaultString (&AccessResults, DefaultResults); + } + } + FreePool (DevicePath); + DevicePath = NULL; + + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Free the allocated memory. + // + if (DefaultResults != NULL) { + FreePool (DefaultResults); + DefaultResults = NULL; + } + +NextConfigString: + if (!FirstElement) { + Status = AppendToMultiString (Results, L"&"); + ASSERT_EFI_ERROR (Status); + } + Status = AppendToMultiString (Results, AccessResults); ASSERT_EFI_ERROR (Status); - SafeFreePool (AccessResults); + + FirstElement = FALSE; + + FreePool (AccessResults); AccessResults = NULL; - SafeFreePool (ConfigRequest); + FreePool (ConfigRequest); ConfigRequest = NULL; // @@ -822,14 +2322,31 @@ HiiConfigRoutingExtractConfig ( } StringPtr++; - } - return EFI_SUCCESS; -#else - return EFI_UNSUPPORTED; -#endif +Done: + if (EFI_ERROR (Status)) { + FreePool (*Results); + *Results = NULL; + } + + if (ConfigRequest != NULL) { + FreePool (ConfigRequest); + } + + if (AccessResults != NULL) { + FreePool (AccessResults); + } + + if (DefaultResults != NULL) { + FreePool (DefaultResults); + } + + if (DevicePath != NULL) { + FreePool (DevicePath); + } + return Status; } @@ -862,24 +2379,24 @@ HiiConfigRoutingExportConfig ( OUT EFI_STRING *Results ) { -#ifndef _DISABLE_UNUSED_HII_PROTOCOLS_ - EFI_STATUS Status; - HII_DATABASE_PRIVATE_DATA *Private; - LIST_ENTRY StorageListHdr; - HII_FORMSET_STORAGE *Storage; - LIST_ENTRY *Link; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINTN Length; - EFI_STRING PathHdr; - UINTN PathHdrSize; - EFI_STRING ConfigRequest; - UINTN RequestSize; - EFI_STRING StringPtr; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; - EFI_STRING AccessProgress; EFI_STRING AccessResults; - UINTN TmpSize; + EFI_STRING Progress; + EFI_STRING ConfigRequest; + UINTN Index; + EFI_HANDLE *ConfigAccessHandles; + UINTN NumberConfigAccessHandles; + BOOLEAN FirstElement; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HII_HANDLE HiiHandle; + EFI_STRING DefaultResults; + HII_DATABASE_PRIVATE_DATA *Private; + LIST_ENTRY *Link; + HII_DATABASE_RECORD *Database; + UINT8 *DevicePathPkg; + UINT8 *CurrentDevicePath; + UINTN DevicePathLength; if (This == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; @@ -887,13 +2404,6 @@ HiiConfigRoutingExportConfig ( Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This); - InitializeListHead (&StorageListHdr); - - Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr); - if (EFI_ERROR (Status)) { - return Status; - } - // // Allocate a fix length of memory to store Results. Reallocate memory for // Results if this fix length is insufficient. @@ -903,156 +2413,113 @@ HiiConfigRoutingExportConfig ( return EFI_OUT_OF_RESOURCES; } - // - // Parsing all formset storages. - // - for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) { - Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE); - // - // Find the corresponding device path instance - // + NumberConfigAccessHandles = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiHiiConfigAccessProtocolGuid, + NULL, + &NumberConfigAccessHandles, + &ConfigAccessHandles + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FirstElement = TRUE; + + for (Index = 0; Index < NumberConfigAccessHandles; Index++) { Status = gBS->HandleProtocol ( - Storage->DriverHandle, - &gEfiDevicePathProtocolGuid, - (VOID **) &DevicePath + ConfigAccessHandles[Index], + &gEfiHiiConfigAccessProtocolGuid, + (VOID **) &ConfigAccess ); if (EFI_ERROR (Status)) { - return Status; + continue; } - // - // Convert the device path binary to hex UNICODE %02x bytes in the same order - // as the device path resides in RAM memory. - // - Length = GetDevicePathSize (DevicePath); - PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16); - PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize); - if (PathHdr == NULL) { - return EFI_OUT_OF_RESOURCES; - } - Status = BufferToHexString (PathHdr, (UINT8 *) DevicePath, Length); - ASSERT_EFI_ERROR (Status); // - // Generate a with one and zero . - // It means extract all possible configurations from this specific driver. - // - TmpSize = StrLen (L"GUID=&NAME=&PATH="); - RequestSize = (TmpSize + 32 + StrLen (Storage->Name) * 4) - * sizeof (CHAR16) + PathHdrSize; - ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize); - if (ConfigRequest == NULL) { - SafeFreePool (PathHdr); - return EFI_OUT_OF_RESOURCES; + // Get DevicePath and HiiHandle for this ConfigAccess driver handle + // + Progress = NULL; + HiiHandle = NULL; + ConfigRequest = NULL; + DefaultResults = NULL; + Database = NULL; + DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]); + DevicePathLength = GetDevicePathSize (DevicePath); + if (DevicePath != NULL) { + for (Link = Private->DatabaseList.ForwardLink; + Link != &Private->DatabaseList; + Link = Link->ForwardLink + ) { + Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); + if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) { + CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); + if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) && + (CompareMem ( + DevicePath, + CurrentDevicePath, + DevicePathLength + ) == 0)) { + HiiHandle = Database->Handle; + break; + } + } + } } // - // Add - // ::= 'GUID=' - // Convert in the same order as it resides in RAM memory. - // - StringPtr = ConfigRequest; - StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID=")); - StringPtr += StrLen (L"GUID="); - - Status = BufferToHexString (StringPtr, (UINT8 *) (&Storage->Guid), sizeof (EFI_GUID)); - ASSERT_EFI_ERROR (Status); - - StringPtr += 32; - ASSERT (*StringPtr == 0); - *StringPtr = L'&'; - StringPtr++; - - // - // Add - // ::= 'NAME=' - // - StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME=")); - StringPtr += StrLen (L"NAME="); - - Length = (StrLen (Storage->Name) * 4 + 1) * sizeof (CHAR16); - Status = UnicodeToConfigString (StringPtr, &Length, Storage->Name); - ASSERT_EFI_ERROR (Status); - StringPtr += StrLen (Storage->Name) * 4; - - *StringPtr = L'&'; - StringPtr++; - - // - // Add - // ::= '' - // - StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH=")); - StringPtr += StrLen (L"PATH="); - StrCpy (StringPtr, PathHdr); - - SafeFreePool (PathHdr); - PathHdr = NULL; - - // - // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the - // code somewhat complex. Let's TBD here whether a or a - // is required to call ConfigAccess.ExtractConfig(). - // - // Here we use to call ConfigAccess instance. It requires ConfigAccess - // to handle such kind of "ConfigRequest". It is not supported till now. + // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle // - // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig() - // will be updated as soon as the decision is made. - + if (HiiHandle != NULL && DevicePath != NULL) { + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults); + } // - // Route the request to corresponding ConfigAccess protocol to extract settings. + // Can't parse IFR data to get the request string and default string. // - Status = gBS->HandleProtocol ( - Storage->DriverHandle, - &gEfiHiiConfigAccessProtocolGuid, - (VOID **) &ConfigAccess - ); - ASSERT_EFI_ERROR (Status); - + if (EFI_ERROR (Status)) { + ConfigRequest = NULL; + DefaultResults = NULL; + } + Status = ConfigAccess->ExtractConfig ( ConfigAccess, ConfigRequest, - &AccessProgress, + &Progress, &AccessResults ); - if (EFI_ERROR (Status)) { - SafeFreePool (ConfigRequest); - SafeFreePool (AccessResults); - return EFI_INVALID_PARAMETER; + if (!EFI_ERROR (Status)) { + // + // Merge the default sting from IFR code into the got setting from driver. + // + if (DefaultResults != NULL) { + Status = MergeDefaultString (&AccessResults, DefaultResults); + ASSERT_EFI_ERROR (Status); + FreePool (DefaultResults); + DefaultResults = NULL; + } + + // + // Attach this to a . There is a '&' + // which seperates the first and the following ones. + // + if (!FirstElement) { + Status = AppendToMultiString (Results, L"&"); + ASSERT_EFI_ERROR (Status); + } + + Status = AppendToMultiString (Results, AccessResults); + ASSERT_EFI_ERROR (Status); + + FirstElement = FALSE; + + FreePool (AccessResults); + AccessResults = NULL; } - - // - // Attach this to a - // - ASSERT (*AccessProgress == 0); - Status = AppendToMultiString (Results, AccessResults); - ASSERT_EFI_ERROR (Status); - SafeFreePool (AccessResults); - AccessResults = NULL; - SafeFreePool (ConfigRequest); - ConfigRequest = NULL; - - } - - // - // Free the exported storage resource - // - while (!IsListEmpty (&StorageListHdr)) { - Storage = CR ( - StorageListHdr.ForwardLink, - HII_FORMSET_STORAGE, - Entry, - HII_FORMSET_STORAGE_SIGNATURE - ); - RemoveEntryList (&Storage->Entry); - SafeFreePool (Storage->Name); - SafeFreePool (Storage); } + FreePool (ConfigAccessHandles); - return EFI_SUCCESS; -#else - return EFI_UNSUPPORTED; -#endif + return EFI_SUCCESS; } @@ -1089,22 +2556,21 @@ HiiConfigRoutingRouteConfig ( OUT EFI_STRING *Progress ) { -#ifndef _DISABLE_UNUSED_HII_PROTOCOLS_ - HII_DATABASE_PRIVATE_DATA *Private; EFI_STRING StringPtr; EFI_STRING ConfigResp; UINTN Length; EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; LIST_ENTRY *Link; HII_DATABASE_RECORD *Database; + UINT8 *DevicePathPkg; UINT8 *CurrentDevicePath; EFI_HANDLE DriverHandle; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; EFI_STRING AccessProgress; - UINTN RemainSize; - EFI_STRING TmpPtr; + UINTN DevicePathLength; if (This == NULL || Progress == NULL) { return EFI_INVALID_PARAMETER; @@ -1156,44 +2622,59 @@ HiiConfigRoutingRouteConfig ( // Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath); if (EFI_ERROR (Status)) { - SafeFreePool (ConfigResp); + FreePool (ConfigResp); return Status; } // // Find driver which matches the routing data. // - DriverHandle = NULL; + DriverHandle = NULL; + DevicePathLength = GetDevicePathSize (DevicePath); for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink ) { Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); - CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); - if (CurrentDevicePath != NULL) { - if (CompareMem ( + + if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) { + CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); + if ((DevicePathLength == GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)) && + (CompareMem ( DevicePath, CurrentDevicePath, - GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath) - ) == 0) { + DevicePathLength + ) == 0)) { DriverHandle = Database->DriverHandle; break; } } } - SafeFreePool (DevicePath); - + // + // Try to find driver handle by device path. + // if (DriverHandle == NULL) { - // - // Routing data does not match any known driver. - // Set Progress to the 'G' in "GUID" of the routing header. - // - *Progress = StringPtr; - SafeFreePool (ConfigResp); - return EFI_NOT_FOUND; + TempDevicePath = DevicePath; + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempDevicePath, + &DriverHandle + ); + if (EFI_ERROR (Status) || (DriverHandle == NULL)) { + // + // Routing data does not match any known driver. + // Set Progress to the 'G' in "GUID" of the routing header. + // + FreePool (DevicePath); + *Progress = StringPtr; + FreePool (ConfigResp); + return EFI_NOT_FOUND; + } } + FreePool (DevicePath); + // // Call corresponding ConfigAccess protocol to route settings // @@ -1215,15 +2696,13 @@ HiiConfigRoutingRouteConfig ( // AccessProgress indicates the parsing progress on . // Map it to the progress on then return it. // - RemainSize = StrSize (AccessProgress); - for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++); - *Progress = TmpPtr; + *Progress = StrStr (StringPtr, AccessProgress); - SafeFreePool (ConfigResp); + FreePool (ConfigResp); return Status; } - SafeFreePool (ConfigResp); + FreePool (ConfigResp); ConfigResp = NULL; // @@ -1240,9 +2719,6 @@ HiiConfigRoutingRouteConfig ( } return EFI_SUCCESS; -#else - return EFI_UNSUPPORTED; -#endif } @@ -1259,7 +2735,7 @@ HiiConfigRoutingRouteConfig ( @param BlockSize Length in bytes of Block. @param Config Filled-in configuration string. String allocated by the function. Returned only if call is - successful. + successful. It is string format. @param Progress A pointer to a string filled in with the offset of the most recent & before the first failing name/value pair (or the beginning of the string if @@ -1303,6 +2779,9 @@ HiiBlockToConfig ( UINT8 *Value; EFI_STRING ValueStr; EFI_STRING ConfigElement; + UINTN Index; + UINT8 *TemBuffer; + CHAR16 *TemString; if (This == NULL || Progress == NULL || Config == NULL) { return EFI_INVALID_PARAMETER; @@ -1343,11 +2822,23 @@ HiiBlockToConfig ( StringPtr++; } if (*StringPtr == 0) { - *Progress = StringPtr; + *Progress = StringPtr - 1; + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + while (*StringPtr != L'&' && *StringPtr != 0) { + StringPtr++; + } + if (*StringPtr == 0) { + *Progress = StringPtr - 1; Status = EFI_INVALID_PARAMETER; goto Exit; } - while (*StringPtr++ != L'&'); + // + // Skip '&' + // + StringPtr++; // // Copy and an additional '&' to @@ -1381,7 +2872,7 @@ HiiBlockToConfig ( TmpBuffer, (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN) ); - SafeFreePool (TmpBuffer); + FreePool (TmpBuffer); StringPtr += Length; if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) { @@ -1405,7 +2896,7 @@ HiiBlockToConfig ( TmpBuffer, (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN) ); - SafeFreePool (TmpBuffer); + FreePool (TmpBuffer); StringPtr += Length; if (*StringPtr != 0 && *StringPtr != L'&') { @@ -1439,12 +2930,14 @@ HiiBlockToConfig ( Status = EFI_OUT_OF_RESOURCES; goto Exit; } + + TemString = ValueStr; + TemBuffer = Value + Width - 1; + for (Index = 0; Index < Width; Index ++, TemBuffer --) { + TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2); + } - Status = BufToHexString (ValueStr, &Length, Value, Width); - ASSERT_EFI_ERROR (Status); - ToLower (ValueStr); - - SafeFreePool (Value); + FreePool (Value); Value = NULL; // @@ -1466,8 +2959,8 @@ HiiBlockToConfig ( AppendToMultiString (Config, ConfigElement); - SafeFreePool (ConfigElement); - SafeFreePool (ValueStr); + FreePool (ConfigElement); + FreePool (ValueStr); ConfigElement = NULL; ValueStr = NULL; @@ -1487,16 +2980,25 @@ HiiBlockToConfig ( Status = EFI_INVALID_PARAMETER; goto Exit; } - + + HiiToLower (*Config); *Progress = StringPtr; return EFI_SUCCESS; Exit: - - SafeFreePool (*Config); - SafeFreePool (ValueStr); - SafeFreePool (Value); - SafeFreePool (ConfigElement); + if (*Config != NULL) { + FreePool (*Config); + *Config = NULL; + } + if (ValueStr != NULL) { + FreePool (ValueStr); + } + if (Value != NULL) { + FreePool (Value); + } + if (ConfigElement != NULL) { + FreePool (ConfigElement); + } return Status; @@ -1510,7 +3012,7 @@ Exit: @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. @param ConfigResp A null-terminated Unicode string in - format. + format. It can be ConfigAltResp format string. @param Block A possibly null array of bytes representing the current block. Only bytes referenced in the ConfigResp string in the block are modified. If @@ -1596,7 +3098,19 @@ HiiConfigToBlock ( Status = EFI_INVALID_PARAMETER; goto Exit; } - while (*StringPtr++ != L'&'); + + while (*StringPtr != L'&' && *StringPtr != 0) { + StringPtr++; + } + if (*StringPtr == 0) { + *Progress = StringPtr; + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + // + // Skip '&' + // + StringPtr++; // // Parse each if exists @@ -1609,7 +3123,7 @@ HiiConfigToBlock ( // Get Offset // Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length); - if (Status == EFI_OUT_OF_RESOURCES) { + if (EFI_ERROR (Status)) { *Progress = ConfigResp; goto Exit; } @@ -1619,7 +3133,7 @@ HiiConfigToBlock ( TmpBuffer, (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN) ); - SafeFreePool (TmpBuffer); + FreePool (TmpBuffer); StringPtr += Length; if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) { @@ -1643,7 +3157,7 @@ HiiConfigToBlock ( TmpBuffer, (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN) ); - SafeFreePool (TmpBuffer); + FreePool (TmpBuffer); StringPtr += Length; if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) { @@ -1657,7 +3171,7 @@ HiiConfigToBlock ( // Get Value // Status = GetValueOfNumber (StringPtr, &Value, &Length); - if (Status == EFI_OUT_OF_RESOURCES) { + if (EFI_ERROR (Status)) { *Progress = ConfigResp; goto Exit; } @@ -1680,7 +3194,7 @@ HiiConfigToBlock ( CopyMem (Block + Offset, Value, Width); *BlockSize = Offset + Width - 1; - SafeFreePool (Value); + FreePool (Value); Value = NULL; // @@ -1692,8 +3206,11 @@ HiiConfigToBlock ( StringPtr++; } - - if (*StringPtr != 0) { + + // + // The input string is ConfigAltResp format. + // + if ((*StringPtr != 0) && (StrnCmp (StringPtr, L"&GUID=", StrLen (L"&GUID=")) != 0)) { *Progress = StringPtr - 1; Status = EFI_INVALID_PARAMETER; goto Exit; @@ -1704,7 +3221,9 @@ HiiConfigToBlock ( Exit: - SafeFreePool (Value); + if (Value != NULL) { + FreePool (Value); + } return Status; } @@ -1716,7 +3235,7 @@ Exit: @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. @param Configuration A null-terminated Unicode string in - format. + format. It is format. @param Guid A pointer to the GUID value to search for in the routing portion of the ConfigResp string when retrieving the requested data. If Guid is NULL, @@ -1738,7 +3257,7 @@ Exit: @param AltCfgResp A pointer to a buffer which will be allocated by the function which contains the retrieved string as requested. This buffer is only allocated if - the call was successful. + the call was successful. It is format. @retval EFI_SUCCESS The request succeeded. The requested data was extracted and placed in the newly allocated @@ -1761,8 +3280,6 @@ HiiGetAltCfg ( OUT EFI_STRING *AltCfgResp ) { -#ifndef _DISABLE_UNUSED_HII_PROTOCOLS_ - EFI_STATUS Status; EFI_STRING StringPtr; EFI_STRING HdrStart; @@ -1887,9 +3404,10 @@ HiiGetAltCfg ( Status = EFI_NOT_FOUND; goto Exit; } + StringPtr ++; } PathFlag = TRUE; - HdrEnd = ++StringPtr; + HdrEnd = StringPtr; } } @@ -1912,7 +3430,11 @@ HiiGetAltCfg ( NameFlag = FALSE; PathFlag = FALSE; } else { - Status = OutputConfigBody (StringPtr, &Result); + // + // Skip AltIdStr and & + // + StringPtr = StringPtr + StrLen (AltIdStr); + Status = OutputConfigBody (StringPtr, &Result); goto Exit; } } @@ -1921,12 +3443,12 @@ HiiGetAltCfg ( Status = EFI_NOT_FOUND; Exit: - - if (!EFI_ERROR (Status)) { + *AltCfgResp = NULL; + if (!EFI_ERROR (Status) && (Result != NULL)) { // // Copy the and // - Length = HdrEnd - HdrStart + StrLen (Result); + Length = HdrEnd - HdrStart + StrLen (Result) + 1; *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16)); if (*AltCfgResp == NULL) { Status = EFI_OUT_OF_RESOURCES; @@ -1937,18 +3459,24 @@ Exit: } } - SafeFreePool (GuidStr); - SafeFreePool (NameStr); - SafeFreePool (PathStr); - SafeFreePool (AltIdStr); - SafeFreePool (Result); + if (GuidStr != NULL) { + FreePool (GuidStr); + } + if (NameStr != NULL) { + FreePool (NameStr); + } + if (PathStr != NULL) { + FreePool (PathStr); + } + if (AltIdStr != NULL) { + FreePool (AltIdStr); + } + if (Result != NULL) { + FreePool (Result); + } return Status; -#else - return EFI_UNSUPPORTED; -#endif - }