From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Universal/HiiDatabaseDxe/ConfigRouting.c | 6231 ++++++++++++++++++++ 1 file changed, 6231 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c (limited to 'roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c') diff --git a/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c new file mode 100644 index 000000000..2cad6d29f --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c @@ -0,0 +1,6231 @@ +/** @file +Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "HiiDatabase.h" +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. + +**/ +UINTN +CalculateConfigStringLen ( + IN EFI_STRING String + ) +{ + EFI_STRING TmpPtr; + + // + // "GUID=" should be the first element of incoming string. + // + ASSERT (String != NULL); + ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0); + + // + // The beginning of next / should be "&GUID=". + // Will meet '\0' if there is only one /. + // + TmpPtr = StrStr (String, L"&GUID="); + if (TmpPtr == NULL) { + return StrLen (String); + } + + return (TmpPtr - String); +} + + +/** + 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 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 necessary structures. + @retval EFI_SUCCESS The device path is retrieved and translated to + binary format. + +**/ +EFI_STATUS +GetDevicePath ( + IN EFI_STRING String, + OUT UINT8 **DevicePathData + ) +{ + UINTN Length; + EFI_STRING PathHdr; + UINT8 *DevicePathBuffer; + CHAR16 TemStr[2]; + UINTN Index; + UINT8 DigitUint8; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + + if (String == NULL || DevicePathData == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the 'PATH=' of and skip it. + // + for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++); + 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; + + // + // The content between 'PATH=' of and '&' of next element + // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding + // of UEFI device path. + // + for (Length = 0; *String != 0 && *String != L'&'; String++, Length++); + // + // Check DevicePath Length + // + if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return EFI_NOT_FOUND; + } + + // + // 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. + // + 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); + } + + // + // return the device path + // + *DevicePathData = DevicePathBuffer; + return EFI_SUCCESS; +} + +/** + Converts the unicode character of the string from uppercase to lowercase. + This is a internal function. + + @param ConfigString String to be converted + +**/ +VOID +EFIAPI +HiiToLower ( + IN EFI_STRING ConfigString + ) +{ + EFI_STRING String; + BOOLEAN Lower; + + ASSERT (ConfigString != NULL); + + // + // 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'); + } + } + + 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 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. + + +**/ +VOID +GenerateSubStr ( + IN CONST EFI_STRING String, + IN UINTN BufferLen, + IN VOID *Buffer, + IN UINT8 Flag, + OUT EFI_STRING *SubStr + ) +{ + UINTN Length; + EFI_STRING Str; + EFI_STRING StringHeader; + CHAR16 *TemString; + CHAR16 *TemName; + UINT8 *TemBuffer; + UINTN Index; + + ASSERT (String != NULL && SubStr != NULL); + + if (Buffer == NULL) { + *SubStr = AllocateCopyPool (StrSize (String), String); + ASSERT (*SubStr != NULL); + return; + } + + // + // Header + Data + '&' + '\0' + // + Length = StrLen (String) + BufferLen * 2 + 1 + 1; + Str = AllocateZeroPool (Length * sizeof (CHAR16)); + ASSERT (Str != NULL); + + StrCpyS (Str, Length, String); + + 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 ++) { + UnicodeValueToStringS ( + TemString, + sizeof (CHAR16) * (Length - StrnLenS (Str, Length)), + PREFIX_ZERO | RADIX_HEX, + *TemBuffer, + 2 + ); + TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length)); + } + 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++) { + UnicodeValueToStringS ( + TemString, + sizeof (CHAR16) * (Length - StrnLenS (Str, Length)), + PREFIX_ZERO | RADIX_HEX, + *TemName, + 4 + ); + TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length)); + } + break; + case 3: + // + // Convert Buffer to Hex String + // + TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1; + for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) { + UnicodeValueToStringS ( + TemString, + sizeof (CHAR16) * (Length - StrnLenS (Str, Length)), + PREFIX_ZERO | RADIX_HEX, + *TemBuffer, + 2 + ); + TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length)); + } + break; + default: + break; + } + + // + // Convert the uppercase to lowercase since is defined in lowercase format. + // + StrCatS (Str, Length, L"&"); + HiiToLower (Str); + + *SubStr = Str; +} + + +/** + 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 + responsibility to free this buffer. + + @retval EFI_INVALID_PARAMETER There is no form package in current hii database. + @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation. + @retval EFI_SUCCESS All existing storage is exported. + +**/ +EFI_STATUS +OutputConfigBody ( + IN EFI_STRING String, + OUT EFI_STRING *ConfigBody + ) +{ + EFI_STRING TmpPtr; + EFI_STRING Result; + UINTN Length; + + 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) { + // + // It is the last of the incoming configuration string. + // + Result = AllocateCopyPool (StrSize (String), String); + if (Result == NULL) { + return EFI_OUT_OF_RESOURCES; + } else { + *ConfigBody = Result; + return EFI_SUCCESS; + } + } + + Length = TmpPtr - String; + if (Length == 0) { + return EFI_NOT_FOUND; + } + Result = AllocateCopyPool (Length * sizeof (CHAR16), String); + if (Result == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *(Result + Length - 1) = 0; + *ConfigBody = Result; + return EFI_SUCCESS; +} + +/** + 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 + MAX_STRING_LENGTH. On output, the buffer length + might be updated. + @param AppendString NULL-terminated Unicode string. + + @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid. + @retval EFI_SUCCESS AppendString is append to the end of MultiString + +**/ +EFI_STATUS +AppendToMultiString ( + IN OUT EFI_STRING *MultiString, + IN EFI_STRING AppendString + ) +{ + UINTN AppendStringSize; + UINTN MultiStringSize; + UINTN MaxLen; + + if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) { + return EFI_INVALID_PARAMETER; + } + + AppendStringSize = StrSize (AppendString); + MultiStringSize = StrSize (*MultiString); + MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16); + + // + // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH. + // + if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH || + MultiStringSize > MAX_STRING_LENGTH) { + *MultiString = (EFI_STRING) ReallocatePool ( + MultiStringSize, + MultiStringSize + AppendStringSize, + (VOID *) (*MultiString) + ); + MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16); + ASSERT (*MultiString != NULL); + } + // + // Append the incoming string + // + StrCatS (*MultiString, MaxLen, AppendString); + + return EFI_SUCCESS; +} + + +/** + Get the value of in format, i.e. the value of OFFSET + 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 + to free memory. + @param Len Length of the , in characters. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary + structures. + @retval EFI_SUCCESS Value of is outputted in Number + successfully. + +**/ +EFI_STATUS +GetValueOfNumber ( + IN EFI_STRING StringPtr, + OUT UINT8 **Number, + OUT UINTN *Len + ) +{ + EFI_STRING TmpPtr; + UINTN Length; + EFI_STRING Str; + UINT8 *Buf; + EFI_STATUS Status; + UINT8 DigitUint8; + UINTN Index; + CHAR16 TemStr[2]; + + if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) { + return EFI_INVALID_PARAMETER; + } + + Buf = NULL; + + TmpPtr = StringPtr; + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr++; + } + *Len = StringPtr - TmpPtr; + Length = *Len + 1; + + Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16)); + if (Str == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16)); + *(Str + *Len) = L'\0'; + + Length = (Length + 1) / 2; + Buf = (UINT8 *) AllocateZeroPool (Length); + if (Buf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + Length = *Len; + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < Length; Index ++) { + TemStr[0] = Str[Length - Index - 1]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + Buf [Index/2] = DigitUint8; + } else { + Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]); + } + } + + *Number = Buf; + Status = EFI_SUCCESS; + +Exit: + if (Str != NULL) { + FreePool (Str); + } + + return Status; +} + +/** + To find the BlockName in the string with same value. + + @param String Pointer to a Null-terminated Unicode string. + @param BlockName Pointer to a Null-terminated Unicode string to search for. + @param Buffer Pointer to the value correspond to the BlockName. + @param Found The Block whether has been found. + @param BufferLen The length of the buffer. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +FindSameBlockElement( + IN EFI_STRING String, + IN EFI_STRING BlockName, + IN UINT8 *Buffer, + OUT BOOLEAN *Found, + IN UINTN BufferLen + ) +{ + EFI_STRING BlockPtr; + UINTN Length; + UINT8 *TempBuffer; + EFI_STATUS Status; + + TempBuffer = NULL; + *Found = FALSE; + BlockPtr = StrStr (String, BlockName); + + while (BlockPtr != NULL) { + BlockPtr += StrLen (BlockName); + Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (TempBuffer != NULL); + if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) { + *Found = TRUE; + FreePool (TempBuffer); + TempBuffer = NULL; + return EFI_SUCCESS; + } else { + FreePool (TempBuffer); + TempBuffer = NULL; + BlockPtr = StrStr (BlockPtr + 1, BlockName); + } + } + return EFI_SUCCESS; +} + +/** + Compare the in ConfigAltResp and DefaultAltCfgResp, if the + in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp. + + @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. + @param ConfigAltResp Pointer to a null-terminated Unicode string in + format. + @param AltConfigHdr Pointer to a Unicode string in format. + @param ConfigAltRespChanged Whether the ConfigAltResp has been changed. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +CompareBlockElementDefault ( + IN EFI_STRING DefaultAltCfgResp, + IN OUT EFI_STRING *ConfigAltResp, + IN EFI_STRING AltConfigHdr, + IN OUT BOOLEAN *ConfigAltRespChanged +) +{ + EFI_STATUS Status; + EFI_STRING BlockPtr; + EFI_STRING BlockPtrStart; + EFI_STRING StringPtr; + EFI_STRING AppendString; + EFI_STRING AltConfigHdrPtr; + UINT8 *TempBuffer; + UINTN OffsetLength; + UINTN AppendSize; + UINTN TotalSize; + BOOLEAN FoundOffset; + + AppendString = NULL; + TempBuffer = NULL; + // + // Make BlockPtr point to the first with AltConfigHdr in DefaultAltCfgResp. + // + AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr); + ASSERT (AltConfigHdrPtr != NULL); + BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET="); + // + // Make StringPtr point to the AltConfigHdr in ConfigAltResp. + // + StringPtr = StrStr (*ConfigAltResp, AltConfigHdr); + ASSERT (StringPtr != NULL); + + while (BlockPtr != NULL) { + // + // Find the "&OFFSET=" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp. + // + BlockPtrStart = BlockPtr; + BlockPtr += StrLen (L"&OFFSET="); + Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + // + // To find the same "&OFFSET=" block in ConfigAltResp. + // + Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength); + if (TempBuffer != NULL) { + FreePool (TempBuffer); + TempBuffer = NULL; + } + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + if (!FoundOffset) { + // + // Don't find the same "&OFFSET=" block in ConfigAltResp. + // Calculate the size of . + // ::='OFFSET=''&WIDTH=''&VALUE='. + // + BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET="); + if (BlockPtr != NULL) { + AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16); + } else { + AppendSize = StrSize (BlockPtrStart); + } + // + // Copy the to AppendString. + // + if (AppendString == NULL) { + AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16)); + StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16)); + } else { + TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16); + AppendString = (EFI_STRING) ReallocatePool ( + StrSize (AppendString), + TotalSize, + AppendString + ); + if (AppendString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16)); + } + } else { + // + // To find next "&OFFSET=" block with AltConfigHdr in DefaultAltCfgResp. + // + BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET="); + } + } + + if (AppendString != NULL) { + // + // Reallocate ConfigAltResp to copy the AppendString. + // + TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16); + *ConfigAltResp = (EFI_STRING) ReallocatePool ( + StrSize (*ConfigAltResp), + TotalSize, + *ConfigAltResp + ); + if (*ConfigAltResp == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString); + *ConfigAltRespChanged = TRUE; + } + + Status = EFI_SUCCESS; + +Exit: + if (AppendString != NULL) { + FreePool (AppendString); + } + + return Status; +} + +/** + Compare the in ConfigAltResp and DefaultAltCfgResp, if the + in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp. + + @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. + @param ConfigAltResp Pointer to a null-terminated Unicode string in + format. + @param AltConfigHdr Pointer to a Unicode string in format. + @param ConfigAltRespChanged Whether the ConfigAltResp has been changed. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +CompareNameElementDefault ( + IN EFI_STRING DefaultAltCfgResp, + IN OUT EFI_STRING *ConfigAltResp, + IN EFI_STRING AltConfigHdr, + IN OUT BOOLEAN *ConfigAltRespChanged +) +{ + EFI_STATUS Status; + EFI_STRING NvConfigPtr; + EFI_STRING NvConfigStart; + EFI_STRING NvConfigValuePtr; + EFI_STRING StringPtr; + EFI_STRING NvConfigExist; + EFI_STRING AppendString; + CHAR16 TempChar; + UINTN AppendSize; + UINTN TotalSize; + + AppendString = NULL; + NvConfigExist = NULL; + // + // Make NvConfigPtr point to the first with AltConfigHdr in DefaultAltCfgResp. + // + NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr); + ASSERT (NvConfigPtr != NULL); + NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&"); + // + // Make StringPtr point to the first with AltConfigHdr in ConfigAltResp. + // + StringPtr = StrStr (*ConfigAltResp, AltConfigHdr); + ASSERT (StringPtr != NULL); + StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&"); + ASSERT (StringPtr != NULL); + + while (NvConfigPtr != NULL) { + // + // ::=