X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FHiiDatabaseDxe%2FConfigRouting.c;h=d5ef60b7f5ed3eb223d96c60123df4b3bb319351;hp=3f35ed9005e27405399beb58e09ae6da29bdc13e;hb=f324bf4dbeda4d64b769bd005331e8f9404b692d;hpb=36fe40c2ea61a81b7f004886682e55fb2d5358be diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c index 3f35ed9005..d5ef60b7f5 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,224 +10,30 @@ 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 - -STATIC -CHAR16 -NibbleToHexCharPrivate ( - IN UINT8 Nibble - ) -/*++ - - Routine Description: - Converts the low nibble of a byte to hex unicode character. - - Arguments: - Nibble - lower nibble of a byte. - - Returns: - Hex unicode character between L'0' to L'f'. - ---*/ -{ - Nibble &= 0x0F; - - if (Nibble <= 0x9) { - return (CHAR16)(Nibble + L'0'); - } - - return (CHAR16)(Nibble - 0xA + L'a'); -} - - -/** - Converts Unicode string to binary buffer. - The conversion may be partial. - The first character in the string that is not hex digit stops the conversion. - At a minimum, any blob of data could be represented as a hex string. - - @param Buf Pointer to buffer that receives the data. - @param Len Length in bytes of the buffer to hold converted - data. If routine return with EFI_SUCCESS, - containing length of converted data. If routine - return with EFI_BUFFER_TOO_SMALL, containg length - of buffer desired. - @param Str String to be converted from. - @param ConvertedStrLen Length of the Hex String consumed. - - @retval EFI_SUCCESS Routine Success. - @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data. - -**/ -STATIC -EFI_STATUS -HexStringToBufPrivate ( - IN OUT UINT8 *Buf, - IN OUT UINTN *Len, - IN CHAR16 *Str, - OUT UINTN *ConvertedStrLen OPTIONAL - ) -{ - UINTN HexCnt; - UINTN Idx; - UINTN BufferLength; - UINT8 Digit; - UINT8 Byte; - - // - // Find out how many hex characters the string has. - // - for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++); - - if (HexCnt == 0) { - *Len = 0; - return EFI_SUCCESS; - } - // - // Two Unicode characters make up 1 buffer byte. Round up. - // - BufferLength = (HexCnt + 1) / 2; - - // - // Test if buffer is passed enough. - // - if (BufferLength > (*Len)) { - *Len = BufferLength; - return EFI_BUFFER_TOO_SMALL; - } - - *Len = BufferLength; - - for (Idx = 0; Idx < HexCnt; Idx++) { - - IsHexDigit (&Digit, Str[Idx]); - - // - // For odd charaters, write the lower nibble for each buffer byte, - // and for even characters, the upper nibble. - // - if ((Idx & 1) == 0) { - Byte = (UINT8) (Digit << 4); - } else { - Byte = Buf[Idx / 2]; - Byte &= 0xF0; - Byte = (UINT8) (Byte | Digit); - } - - Buf[Idx / 2] = Byte; - } - - if (ConvertedStrLen != NULL) { - *ConvertedStrLen = HexCnt; - } - - return EFI_SUCCESS; -} - - -/** - Converts binary buffer to Unicode string. - At a minimum, any blob of data could be represented as a hex string. - - @param Str Pointer to the string. - @param HexStringBufferLength Length in bytes of buffer to hold the hex string. - Includes tailing '\0' character. If routine return - with EFI_SUCCESS, containing length of hex string - buffer. If routine return with - EFI_BUFFER_TOO_SMALL, containg length of hex - string buffer desired. - @param Buf Buffer to be converted from. - @param Len Length in bytes of the buffer to be converted. - @param Flag If TRUE, encode the data in the same order as the - it resides in the Buf. Else encode it in the - reverse direction. - - @retval EFI_SUCCESS Routine success. - @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small. - -**/ -STATIC -EFI_STATUS -BufToHexStringPrivate ( - IN OUT CHAR16 *Str, - IN OUT UINTN *HexStringBufferLength, - IN UINT8 *Buf, - IN UINTN Len, - IN BOOLEAN Flag - ) -{ - UINTN Idx; - UINT8 Byte; - UINTN StrLen; - - // - // Make sure string is either passed or allocate enough. - // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer. - // Plus the Unicode termination character. - // - StrLen = Len * 2; - if ((*HexStringBufferLength) < (StrLen + 1) * sizeof (CHAR16)) { - *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16); - return EFI_BUFFER_TOO_SMALL; - } - - *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16); - - // - // Ends the string. - // - Str[StrLen] = 0; - - for (Idx = 0; Idx < Len; Idx++) { - - Byte = Buf[Idx]; - if (Flag) { - Str[Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4)); - Str[Idx * 2 + 1] = NibbleToHexCharPrivate (Byte); - } else { - Str[StrLen - 1 - Idx * 2] = NibbleToHexCharPrivate (Byte); - Str[StrLen - 2 - Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4)); - } - } - - return EFI_SUCCESS; -} - - +extern HII_DATABASE_PRIVATE_DATA mPrivate; /** Calculate the number of Unicode characters of the incoming Configuration string, not including NULL terminator. + This is a internal function. + @param String String in or format. @return The number of Unicode characters. **/ -STATIC UINTN CalculateConfigStringLen ( IN EFI_STRING String ) { - UINTN Length; + EFI_STRING TmpPtr; // // "GUID=" should be the first element of incoming string. @@ -234,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); } @@ -254,27 +58,34 @@ CalculateConfigStringLen ( Convert the hex UNICODE %02x encoding of a UEFI device path to binary from of . + This is a internal function. + @param String UEFI configuration string - @param DevicePath binary of a UEFI device path. + @param DevicePathData Binary of a UEFI device path. + @retval EFI_NOT_FOUND The device path is not invalid. @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid. @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures. @retval EFI_SUCCESS The device path is retrieved and translated to binary format. **/ -STATIC EFI_STATUS GetDevicePath ( IN EFI_STRING String, - OUT UINT8 **DevicePath + OUT UINT8 **DevicePathData ) { - UINTN Length; - EFI_STRING PathHdr; - EFI_STRING DevicePathString; + UINTN Length; + EFI_STRING PathHdr; + UINT8 *DevicePathBuffer; + CHAR16 TemStr[2]; + UINTN Index; + UINT8 DigitUint8; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + - if (String == NULL || DevicePath == NULL) { + if (String == NULL || DevicePathData == NULL) { return EFI_INVALID_PARAMETER; } @@ -285,8 +96,13 @@ GetDevicePath ( if (*String == 0) { return EFI_INVALID_PARAMETER; } - + // + // Check whether path data does exist. + // String += StrLen (L"PATH="); + if (*String == 0) { + return EFI_INVALID_PARAMETER; + } PathHdr = String; // @@ -295,238 +111,131 @@ GetDevicePath ( // of UEFI device path. // for (Length = 0; *String != 0 && *String != L'&'; String++, Length++); - DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16)); - if (DevicePathString == NULL) { - return EFI_OUT_OF_RESOURCES; + // + // Check DevicePath Length + // + if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return EFI_NOT_FOUND; } - StrnCpy (DevicePathString, PathHdr, Length); - *(DevicePathString + Length) = 0; - + // // The data in is encoded as hex UNICODE %02x bytes in the same order // as the device path resides in RAM memory. // Translate the data into binary. - // Two Unicode characters make up 1 buffer byte. // - Length /= 2; - *DevicePath = (UINT8 *) AllocateZeroPool (Length); - if (*DevicePath == NULL) { - SafeFreePool (DevicePathString); + DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2); + if (DevicePathBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } + + // + // Convert DevicePath + // + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < Length; Index ++) { + TemStr[0] = PathHdr[Index]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + DevicePathBuffer [Index/2] = DigitUint8; + } else { + DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8); + } + } + + // + // Validate DevicePath + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer; + while (!IsDevicePathEnd (DevicePath)) { + if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) { + // + // Invalid device path + // + FreePool (DevicePathBuffer); + return EFI_NOT_FOUND; + } + DevicePath = NextDevicePathNode (DevicePath); + } - HexStringToBufPrivate (*DevicePath, &Length, DevicePathString, NULL); - - SafeFreePool (DevicePathString); - + // + // return the device path + // + *DevicePathData = 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 **/ -STATIC -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; - } + EFI_STRING String; + BOOLEAN Lower; - HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); - for (Index = 0; Index < HandleCount; Index++) { - HiiHandle = HandleBuffer[Index]; + ASSERT (ConfigString != NULL); - 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; - - if (Operand == EFI_IFR_VARSTORE_OP) { - Storage->Type = EFI_HII_VARSTORE_BUFFER; - - 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. + This is a internal function. + @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 hex - string and to be the content of the generated - string. - @param Flag If TRUE, convert the buffer data in the same order - as the it resides in the Buffer. Else convert it - in the reverse direction. + + @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. + @param SubStr Points to the output string. It's caller's responsibility to free this buffer. **/ -STATIC VOID GenerateSubStr ( IN CONST EFI_STRING String, IN UINTN BufferLen, - IN UINT8 *Buffer, - IN BOOLEAN Flag, + IN VOID *Buffer, + IN UINT8 Flag, OUT EFI_STRING *SubStr ) { UINTN Length; EFI_STRING Str; - EFI_STATUS Status; + EFI_STRING StringHeader; + CHAR16 *TemString; + CHAR16 *TemName; + UINT8 *TemBuffer; + UINTN Index; ASSERT (String != NULL && SubStr != NULL); @@ -535,24 +244,61 @@ GenerateSubStr ( ASSERT (*SubStr != NULL); return ; } - - Length = BufferLen * 2 + 1 + StrLen (String) + 1; - Str = AllocateZeroPool (Length * sizeof (CHAR16)); + + // + // Header + Data + '&' + '\0' + // + Length = StrLen (String) + BufferLen * 2 + 1 + 1; + Str = AllocateZeroPool (Length * sizeof (CHAR16)); ASSERT (Str != NULL); StrCpy (Str, String); Length = (BufferLen * 2 + 1) * sizeof (CHAR16); - Status = BufToHexStringPrivate ( - Str + StrLen (String), - &Length, - Buffer, - BufferLen, - Flag - ); + StringHeader = Str + StrLen (String); + TemString = (CHAR16 *) StringHeader; + + switch (Flag) { + case 1: + // + // 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: + // + // 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: + // + // Convert Buffer to Hex String + // + 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; } @@ -561,6 +307,8 @@ GenerateSubStr ( /** Retrieve the from String then output it. + This is a internal function. + @param String A sub string of a configuration string in format. @param ConfigBody Points to the output string. It's caller's @@ -571,7 +319,6 @@ GenerateSubStr ( @retval EFI_SUCCESS All existing storage is exported. **/ -STATIC EFI_STATUS OutputConfigBody ( IN EFI_STRING String, @@ -585,6 +332,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) { @@ -609,55 +363,13 @@ OutputConfigBody ( *(Result + Length - 1) = 0; *ConfigBody = Result; return EFI_SUCCESS; - -} - - -#endif - -VOID * -ReallocatePool ( - IN VOID *OldPool, - IN UINTN OldSize, - IN UINTN NewSize - ) -/*++ - -Routine Description: - Adjusts the size of a previously allocated buffer. - -Arguments: - OldPool - A pointer to the buffer whose size is being adjusted. - OldSize - The size of the current buffer. - NewSize - The size of the new buffer. - -Returns: - Points to the new buffer - ---*/ -{ - VOID *NewPool; - - NewPool = NULL; - if (NewSize) { - NewPool = AllocateZeroPool (NewSize); - } - - if (OldPool) { - if (NewPool) { - CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); - } - - gBS->FreePool (OldPool); - } - - return NewPool; } - /** Append a string to a multi-string format. + This is a internal function. + @param MultiString String in , , or . On input, the buffer length of this string is @@ -669,7 +381,6 @@ Returns: @retval EFI_SUCCESS AppendString is append to the end of MultiString **/ -STATIC EFI_STATUS AppendToMultiString ( IN OUT EFI_STRING *MultiString, @@ -692,12 +403,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 // @@ -712,6 +423,8 @@ AppendToMultiString ( or WIDTH or VALUE. ::= 'OFFSET='&'WIDTH='&'VALUE'= + This is a internal function. + @param StringPtr String in format and points to the first character of . @param Number The output value. Caller takes the responsibility @@ -724,7 +437,6 @@ AppendToMultiString ( successfully. **/ -STATIC EFI_STATUS GetValueOfNumber ( IN EFI_STRING StringPtr, @@ -737,48 +449,1744 @@ 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; + *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++; + } + 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) + ); + if (*AltCfgResp == NULL) { + FreePool (AltConfigHdr); + return EFI_OUT_OF_RESOURCES; + } + 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) { + if (DefaultValueData->OpCode == EFI_IFR_DEFAULT_OP) { + // + // Update the default value array in BlockData. + // + DefaultValueArray->Value = DefaultValueData->Value; + } else if (DefaultValueArray->OpCode != EFI_IFR_DEFAULT_OP) { + // + // 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->OpCode = IfrOpHdr->OpCode; + 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->OpCode = IfrOpHdr->OpCode; + 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->OpCode = IfrOpHdr->OpCode; + 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->OpCode = IfrOpHdr->OpCode; + 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->OpCode = IfrOpHdr->OpCode; + 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. + @param PointerProgress Optional parameter, it can be be NULL. + When it is not NULL, if Request is NULL, it returns NULL. + On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + & before the first failing name / value pair (or + the beginning of the string if the failure is in + the first name / value pair) if the request was + not successful. + @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, + OUT EFI_STRING *PointerProgress OPTIONAL + ) +{ + 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; + EFI_STRING Progress; + UINTN Length; + UINT8 *TmpBuffer; + UINT16 Offset; + UINT16 Width; + LIST_ENTRY *Link; + LIST_ENTRY *LinkData; + LIST_ENTRY *LinkDefault; + BOOLEAN DataExist; + + if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // 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; + DataExist = FALSE; + Progress = *Request; + + // + // 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 = *Request; + // + // Jump + // + if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + StringPtr += StrLen (L"GUID="); + while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) { + StringPtr++; + } + if (*StringPtr == L'\0') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + StringPtr += StrLen (L"&NAME="); + while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) { + StringPtr++; + } + if (*StringPtr == L'\0') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + StringPtr += StrLen (L"&PATH="); + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr ++; + } + // + // Check the following string &OFFSET= + // + if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) { + Progress = StringPtr; + Status = EFI_INVALID_PARAMETER; + goto Done; + } else if (*StringPtr == L'\0') { + // + // No request block is found. + // + StringPtr = NULL; + } + } + 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 + // + Progress = StringPtr; + 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); + + // + // Skip &VALUE string if &VALUE does exists. + // + if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) { + StringPtr += StrLen (L"&VALUE="); + + // + // Get Value + // + Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + StringPtr += Length; + if (*StringPtr != 0 && *StringPtr != L'&') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } + // + // 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) { + Status = EFI_SUCCESS; + 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 + // + DataExist = FALSE; + 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 | + // + DataExist = TRUE; + Length = Length + (8 + 4 + 7 + 4); + } + + // + // No any request block data is found. The request string can't be constructed. + // + if (!DataExist) { + Status = EFI_SUCCESS; + goto Done; + } + + // + // Allocate buffer for the entire + // + FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16)); + if (FullConfigRequest == NULL) { + Status = EFI_OUT_OF_RESOURCES; + 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 + // + DataExist = FALSE; + // + // 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); + DataExist = TRUE; + } + } + } + } + + // + // No default value is found. The default string doesn't exist. + // + if (!DataExist) { + Status = EFI_SUCCESS; + goto Done; + } + + // + // Allocate buffer for the entire + // + DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16)); + if (DefaultAltCfgResp == NULL) { + Status = EFI_OUT_OF_RESOURCES; + 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); + + // + // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL. + // + if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) { + Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp); + FreePool (DefaultAltCfgResp); + } else if (*AltCfgResp == NULL) { + *AltCfgResp = DefaultAltCfgResp; + } + +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); + } - Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING)); - if (Str == NULL) { - Status = EFI_OUT_OF_RESOURCES; - 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); } - 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; + + // + // Free the allocated string + // + if (GuidStr != NULL) { + FreePool (GuidStr); + } + if (NameStr != NULL) { + FreePool (NameStr); + } + if (PathStr != NULL) { + FreePool (PathStr); + } + if (ConfigHdr != NULL) { + FreePool (ConfigHdr); } - Status = HexStringToBuf (Buf, &Length, Str, NULL); - if (EFI_ERROR (Status)) { - goto Exit; + // + // Free Pacakge data + // + if (HiiFormPackage != NULL) { + FreePool (HiiFormPackage); } - *Number = Buf; - Status = EFI_SUCCESS; + if (PointerProgress != NULL) { + if (*Request == NULL) { + *PointerProgress = NULL; + } else if (EFI_ERROR (Status)) { + *PointerProgress = Progress; + } else { + *PointerProgress = *Request + StrLen (*Request); + } + } -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. @@ -827,23 +2235,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; + BOOLEAN IfrDataParsedFlag; if (This == NULL || Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; @@ -857,6 +2267,12 @@ 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; + IfrDataParsedFlag = FALSE; // // The first element of should be @@ -866,6 +2282,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. @@ -892,7 +2310,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; @@ -901,42 +2320,80 @@ 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; 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 ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) { + CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); if (CompareMem ( DevicePath, CurrentDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath) ) == 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 + // + IfrDataParsedFlag = FALSE; + 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; + IfrDataParsedFlag = TRUE; + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress); + if (EFI_ERROR (Status)) { + // + // AccessProgress indicates the parsing progress on . + // Map it to the progress on then return it. + // + *Progress = StrStr (StringPtr, AccessProgress); + goto Done; + } + // + // Not any request block is found. + // + if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) { + AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest); + goto NextConfigString; + } } // @@ -960,23 +2417,48 @@ 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 (!IfrDataParsedFlag && HiiHandle != NULL) { + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL); + ASSERT_EFI_ERROR (Status); + } + + FreePool (DevicePath); + DevicePath = NULL; + + if (DefaultResults != NULL) { + Status = MergeDefaultString (&AccessResults, DefaultResults); + ASSERT_EFI_ERROR (Status); + 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; // @@ -989,14 +2471,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; } @@ -1029,24 +2528,25 @@ 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 StringPtr; + 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; + BOOLEAN IfrDataParsedFlag; if (This == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; @@ -1054,13 +2554,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. @@ -1070,156 +2563,138 @@ 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; - } - // - // 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; + continue; } - Status = BufToHexStringPrivate (PathHdr, &PathHdrSize, (UINT8 *) DevicePath, Length, TRUE); - 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 + sizeof (EFI_GUID) * 2 + StrLen (Storage->Name)) - * 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 + // + IfrDataParsedFlag = FALSE; + Progress = NULL; + HiiHandle = NULL; + DefaultResults = NULL; + Database = NULL; + ConfigRequest = NULL; + DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]); + 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 (CompareMem ( + DevicePath, + CurrentDevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath) + ) == 0) { + HiiHandle = Database->Handle; + break; + } + } + } } - // - // Add - // ::= 'GUID=' - // - StringPtr = ConfigRequest; - StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID=")); - StringPtr += StrLen (L"GUID="); - - Status = BufToHexStringPrivate ( - StringPtr, - &RequestSize, - (UINT8 *) (&Storage->Guid), - sizeof (EFI_GUID), - FALSE - ); - ASSERT_EFI_ERROR (Status); - StringPtr += RequestSize / 2 - 1; - ASSERT (*StringPtr == 0); - *StringPtr = L'&'; - StringPtr++; - - // - // Add - // ::= 'NAME=' - // - StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME=")); - StringPtr += StrLen (L"NAME="); - StrnCpy (StringPtr, Storage->Name, StrLen (Storage->Name)); - StringPtr += StrLen (Storage->Name); - *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. - // - // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig() - // will be updated as soon as the decision is made. - - // - // Route the request to corresponding ConfigAccess protocol to extract settings. - // - Status = gBS->HandleProtocol ( - Storage->DriverHandle, - &gEfiHiiConfigAccessProtocolGuid, - (VOID **) &ConfigAccess - ); - ASSERT_EFI_ERROR (Status); - Status = ConfigAccess->ExtractConfig ( ConfigAccess, - ConfigRequest, - &AccessProgress, + NULL, + &Progress, &AccessResults ); if (EFI_ERROR (Status)) { - SafeFreePool (ConfigRequest); - SafeFreePool (AccessResults); - return EFI_INVALID_PARAMETER; + // + // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle + // + if (HiiHandle != NULL && DevicePath != NULL) { + IfrDataParsedFlag = TRUE; + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL); + // + // Get the full request string to get the Current setting again. + // + if (!EFI_ERROR (Status) && ConfigRequest != NULL) { + Status = ConfigAccess->ExtractConfig ( + ConfigAccess, + ConfigRequest, + &Progress, + &AccessResults + ); + FreePool (ConfigRequest); + } else { + Status = EFI_NOT_FOUND; + } + } } - // - // 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); + if (!EFI_ERROR (Status)) { + // + // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle + // + if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) { + StringPtr = StrStr (AccessResults, L"&GUID="); + if (StringPtr != NULL) { + *StringPtr = 0; + } + if (StrStr (AccessResults, L"&OFFSET=") != NULL) { + Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL); + ASSERT_EFI_ERROR (Status); + } + if (StringPtr != NULL) { + *StringPtr = L'&'; + } + } + // + // 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; + } } + FreePool (ConfigAccessHandles); - return EFI_SUCCESS; -#else - return EFI_UNSUPPORTED; -#endif + return EFI_SUCCESS; } @@ -1250,28 +2725,26 @@ HiiConfigRoutingExportConfig ( **/ EFI_STATUS EFIAPI -HiiConfigRoutingRoutConfig ( +HiiConfigRoutingRouteConfig ( IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN CONST EFI_STRING Configuration, 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; if (This == NULL || Progress == NULL) { return EFI_INVALID_PARAMETER; @@ -1323,21 +2796,22 @@ HiiConfigRoutingRoutConfig ( // 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; 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 ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) { + CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER); if (CompareMem ( DevicePath, CurrentDevicePath, @@ -1349,18 +2823,30 @@ HiiConfigRoutingRoutConfig ( } } - 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 // @@ -1382,15 +2868,13 @@ HiiConfigRoutingRoutConfig ( // 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; // @@ -1407,9 +2891,6 @@ HiiConfigRoutingRoutConfig ( } return EFI_SUCCESS; -#else - return EFI_UNSUPPORTED; -#endif } @@ -1426,7 +2907,7 @@ HiiConfigRoutingRoutConfig ( @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 @@ -1470,6 +2951,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; @@ -1510,11 +2994,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 @@ -1548,7 +3044,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) { @@ -1572,7 +3068,7 @@ HiiBlockToConfig ( TmpBuffer, (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN) ); - SafeFreePool (TmpBuffer); + FreePool (TmpBuffer); StringPtr += Length; if (*StringPtr != 0 && *StringPtr != L'&') { @@ -1606,10 +3102,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); - SafeFreePool (Value); + FreePool (Value); Value = NULL; // @@ -1631,8 +3131,8 @@ HiiBlockToConfig ( AppendToMultiString (Config, ConfigElement); - SafeFreePool (ConfigElement); - SafeFreePool (ValueStr); + FreePool (ConfigElement); + FreePool (ValueStr); ConfigElement = NULL; ValueStr = NULL; @@ -1652,16 +3152,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; @@ -1675,7 +3184,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 @@ -1761,7 +3270,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 @@ -1774,7 +3295,7 @@ HiiConfigToBlock ( // Get Offset // Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length); - if (Status == EFI_OUT_OF_RESOURCES) { + if (EFI_ERROR (Status)) { *Progress = ConfigResp; goto Exit; } @@ -1784,7 +3305,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) { @@ -1808,7 +3329,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) { @@ -1822,7 +3343,7 @@ HiiConfigToBlock ( // Get Value // Status = GetValueOfNumber (StringPtr, &Value, &Length); - if (Status == EFI_OUT_OF_RESOURCES) { + if (EFI_ERROR (Status)) { *Progress = ConfigResp; goto Exit; } @@ -1845,7 +3366,7 @@ HiiConfigToBlock ( CopyMem (Block + Offset, Value, Width); *BlockSize = Offset + Width - 1; - SafeFreePool (Value); + FreePool (Value); Value = NULL; // @@ -1857,19 +3378,24 @@ 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; } - *Progress = StringPtr; + *Progress = StringPtr + StrLen (StringPtr); return EFI_SUCCESS; Exit: - SafeFreePool (Value); + if (Value != NULL) { + FreePool (Value); + } return Status; } @@ -1881,7 +3407,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, @@ -1903,7 +3429,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 @@ -1926,22 +3452,31 @@ HiiGetAltCfg ( OUT EFI_STRING *AltCfgResp ) { -#ifndef DISABLE_UNUSED_HII_PROTOCOLS - EFI_STATUS Status; EFI_STRING StringPtr; - EFI_STRING HdrStart = NULL; - EFI_STRING HdrEnd = NULL; + EFI_STRING HdrStart; + EFI_STRING HdrEnd; EFI_STRING TmpPtr; UINTN Length; - EFI_STRING GuidStr = NULL; - EFI_STRING NameStr = NULL; - EFI_STRING PathStr = NULL; - EFI_STRING AltIdStr = NULL; - EFI_STRING Result = NULL; - BOOLEAN GuidFlag = FALSE; - BOOLEAN NameFlag = FALSE; - BOOLEAN PathFlag = FALSE; + EFI_STRING GuidStr; + EFI_STRING NameStr; + EFI_STRING PathStr; + EFI_STRING AltIdStr; + EFI_STRING Result; + BOOLEAN GuidFlag; + BOOLEAN NameFlag; + BOOLEAN PathFlag; + + HdrStart = NULL; + HdrEnd = NULL; + GuidStr = NULL; + NameStr = NULL; + PathStr = NULL; + AltIdStr = NULL; + Result = NULL; + GuidFlag = FALSE; + NameFlag = FALSE; + PathFlag = FALSE; if (This == NULL || Configuration == NULL || AltCfgResp == NULL) { return EFI_INVALID_PARAMETER; @@ -1955,30 +3490,21 @@ HiiGetAltCfg ( // // Generate the sub string for later matching. // - GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (UINT8 *) Guid, FALSE, &GuidStr); + GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr); GenerateSubStr ( L"PATH=", GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath), - (UINT8 *) DevicePath, - TRUE, + (VOID *) DevicePath, + 1, &PathStr ); if (AltCfgId != NULL) { - GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (UINT8 *) AltCfgId, FALSE, &AltIdStr); + GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); } if (Name != NULL) { - Length = StrLen (Name); - Length += StrLen (L"NAME=&") + 1; - NameStr = AllocateZeroPool (Length * sizeof (CHAR16)); - if (NameStr == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - StrCpy (NameStr, L"NAME="); - StrCat (NameStr, Name); - StrCat (NameStr, L"&"); + GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); } else { - GenerateSubStr (L"NAME=", 0, NULL, FALSE, &NameStr); + GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr); } while (*StringPtr != 0) { @@ -2050,9 +3576,10 @@ HiiGetAltCfg ( Status = EFI_NOT_FOUND; goto Exit; } + StringPtr ++; } PathFlag = TRUE; - HdrEnd = ++StringPtr; + HdrEnd = StringPtr; } } @@ -2075,7 +3602,11 @@ HiiGetAltCfg ( NameFlag = FALSE; PathFlag = FALSE; } else { - Status = OutputConfigBody (StringPtr, &Result); + // + // Skip AltIdStr and & + // + StringPtr = StringPtr + StrLen (AltIdStr); + Status = OutputConfigBody (StringPtr, &Result); goto Exit; } } @@ -2084,12 +3615,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; @@ -2100,18 +3631,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 - }