/** @file\r
+Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
\r
-Copyright (c) 2007 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- ConfigRouting.c\r
-\r
-Abstract:\r
-\r
- Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
-\r
-Revision History\r
-\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include "HiiDatabase.h"\r
+extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
\r
/**\r
Calculate the number of Unicode characters of the incoming Configuration string,\r
**/\r
UINTN\r
CalculateConfigStringLen (\r
- IN EFI_STRING String\r
+ IN EFI_STRING String\r
)\r
{\r
- UINTN Length;\r
+ EFI_STRING TmpPtr;\r
\r
//\r
// "GUID=" should be the first element of incoming string.\r
ASSERT (String != NULL);\r
ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
\r
- Length = StrLen (L"GUID=");\r
- String += Length;\r
-\r
//\r
// The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
// Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
//\r
- while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {\r
- Length++;\r
- String++;\r
+ TmpPtr = StrStr (String, L"&GUID=");\r
+ if (TmpPtr == NULL) {\r
+ return StrLen (String);\r
}\r
\r
- return Length;\r
+ return (TmpPtr - String);\r
}\r
\r
-\r
/**\r
Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
from <PathHdr> of <ConfigHdr>.\r
This is a internal function.\r
\r
@param String UEFI configuration string\r
- @param DevicePath binary of a UEFI device path.\r
+ @param DevicePathData Binary of a UEFI device path.\r
\r
+ @retval EFI_NOT_FOUND The device path is not invalid.\r
@retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
- @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.\r
@retval EFI_SUCCESS The device path is retrieved and translated to\r
binary format.\r
\r
**/\r
EFI_STATUS\r
GetDevicePath (\r
- IN EFI_STRING String,\r
- OUT UINT8 **DevicePath\r
+ IN EFI_STRING String,\r
+ OUT UINT8 **DevicePathData\r
)\r
{\r
- UINTN Length;\r
- EFI_STRING PathHdr;\r
- EFI_STRING DevicePathString;\r
-\r
- if (String == NULL || DevicePath == NULL) {\r
+ UINTN Length;\r
+ EFI_STRING PathHdr;\r
+ UINT8 *DevicePathBuffer;\r
+ CHAR16 TemStr[2];\r
+ UINTN Index;\r
+ UINT8 DigitUint8;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ if ((String == NULL) || (DevicePathData == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Find the 'PATH=' of <PathHdr> and skip it.\r
//\r
- for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
+ for ( ; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++) {\r
+ }\r
+\r
if (*String == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // Check whether path data does exist.\r
+ //\r
String += StrLen (L"PATH=");\r
+ if (*String == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
PathHdr = String;\r
\r
//\r
// or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
// of UEFI device path.\r
//\r
- for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
- DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
- if (DevicePathString == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {\r
+ }\r
+\r
+ //\r
+ // Check DevicePath Length\r
+ //\r
+ if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+ return EFI_NOT_FOUND;\r
}\r
- StrnCpy (DevicePathString, PathHdr, Length);\r
- *(DevicePathString + Length) = 0;\r
\r
//\r
// The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
// as the device path resides in RAM memory.\r
// Translate the data into binary.\r
//\r
- Length /= 2;\r
- *DevicePath = (UINT8 *) AllocateZeroPool (Length);\r
- if (*DevicePath == NULL) {\r
- SafeFreePool (DevicePathString);\r
+ DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);\r
+ if (DevicePathBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- HexStringToBufInReverseOrder (*DevicePath, &Length, DevicePathString);\r
-\r
- SafeFreePool (DevicePathString);\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-/**\r
- Extract Storage from all Form Packages in current hii database.\r
-\r
- This is a internal function.\r
-\r
- @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.\r
- @param StorageListHead Storage link List head.\r
-\r
- @retval EFI_NOT_FOUND There is no form package in current hii database.\r
- @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
- @retval EFI_SUCCESS All existing storage is exported.\r
-\r
-**/\r
-EFI_STATUS\r
-ExportAllStorage (\r
- IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,\r
- IN OUT LIST_ENTRY *StorageListHead\r
-)\r
-{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- UINTN HandleCount;\r
- EFI_HII_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- UINTN Index2;\r
- EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
- EFI_HII_PACKAGE_HEADER *Package;\r
- UINT8 *OpCodeData;\r
- UINT8 Operand;\r
- UINT32 Offset;\r
- HII_FORMSET_STORAGE *Storage;\r
- EFI_HII_HANDLE HiiHandle;\r
- EFI_HANDLE DriverHandle;\r
- CHAR8 *AsciiString;\r
- UINT32 PackageListLength;\r
- EFI_HII_PACKAGE_HEADER PackageHeader;\r
-\r
- //\r
- // Find the package list which contains Form package.\r
//\r
- BufferSize = 0;\r
- HandleBuffer = NULL;\r
- Status = HiiListPackageLists (\r
- HiiDatabase,\r
- EFI_HII_PACKAGE_FORM,\r
- NULL,\r
- &BufferSize,\r
- HandleBuffer\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- HandleBuffer = AllocateZeroPool (BufferSize);\r
- ASSERT (HandleBuffer != NULL);\r
-\r
- Status = HiiListPackageLists (\r
- HiiDatabase,\r
- EFI_HII_PACKAGE_FORM,\r
- NULL,\r
- &BufferSize,\r
- HandleBuffer\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- SafeFreePool (HandleBuffer);\r
- return Status;\r
- }\r
-\r
- HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- HiiHandle = HandleBuffer[Index];\r
-\r
- BufferSize = 0;\r
- HiiPackageList = NULL;\r
- Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- HiiPackageList = AllocateZeroPool (BufferSize);\r
- ASSERT (HiiPackageList != NULL);\r
- Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- SafeFreePool (HandleBuffer);\r
- SafeFreePool (HiiPackageList);\r
- return Status;\r
+ // Convert DevicePath\r
+ //\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index++) {\r
+ TemStr[0] = PathHdr[Index];\r
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ DevicePathBuffer[Index/2] = DigitUint8;\r
+ } else {\r
+ DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);\r
}\r
+ }\r
\r
- //\r
- // Get Form package from this HII package List\r
- //\r
- Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
- CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
- Package = NULL;\r
- ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
-\r
- while (Offset < PackageListLength) {\r
- Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
- CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
- if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
- break;\r
- }\r
- Offset += PackageHeader.Length;\r
- }\r
- if (Offset >= PackageListLength) {\r
+ //\r
+ // Validate DevicePath\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;\r
+ while (!IsDevicePathEnd (DevicePath)) {\r
+ if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
//\r
- // Error here: No Form package found in this Package List\r
+ // Invalid device path\r
//\r
- ASSERT (FALSE);\r
+ FreePool (DevicePathBuffer);\r
+ return EFI_NOT_FOUND;\r
}\r
\r
- //\r
- // Search Storage definition in this Form package\r
- //\r
- Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
- while (Offset < PackageHeader.Length) {\r
- OpCodeData = ((UINT8 *) Package) + Offset;\r
- Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
-\r
- Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
-\r
- if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
- (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
- (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
-\r
- Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
- ASSERT (Storage != NULL);\r
- InsertTailList (StorageListHead, &Storage->Entry);\r
-\r
- Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;\r
- Storage->HiiHandle = HiiHandle;\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ }\r
\r
- Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);\r
- if (EFI_ERROR (Status)) {\r
- SafeFreePool (HandleBuffer);\r
- SafeFreePool (HiiPackageList);\r
- SafeFreePool (Storage);\r
- return Status;\r
- }\r
- Storage->DriverHandle = DriverHandle;\r
+ //\r
+ // return the device path\r
+ //\r
+ *DevicePathData = DevicePathBuffer;\r
+ return EFI_SUCCESS;\r
+}\r
\r
- if (Operand == EFI_IFR_VARSTORE_OP) {\r
- Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
+/**\r
+ Converts the unicode character of the string from uppercase to lowercase.\r
+ This is a internal function.\r
\r
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
- CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
+ @param ConfigString String to be converted\r
\r
- AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
- Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
- ASSERT (Storage->Name != NULL);\r
- for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {\r
- Storage->Name[Index2] = (CHAR16) AsciiString[Index2];\r
- }\r
- //\r
- // Append '\0' to the end of the unicode string.\r
- //\r
- Storage->Name[Index2] = 0;\r
- } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
- Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiToLower (\r
+ IN EFI_STRING ConfigString\r
+ )\r
+{\r
+ EFI_STRING String;\r
+ BOOLEAN Lower;\r
\r
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
- } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {\r
- Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
+ ASSERT (ConfigString != NULL);\r
\r
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
- }\r
- }\r
+ //\r
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+ //\r
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+ if (*String == L'=') {\r
+ Lower = TRUE;\r
+ } else if (*String == L'&') {\r
+ Lower = FALSE;\r
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {\r
+ *String = (CHAR16)(*String - L'A' + L'a');\r
}\r
-\r
- SafeFreePool (HiiPackageList);\r
}\r
\r
- SafeFreePool (HandleBuffer);\r
-\r
- return EFI_SUCCESS;\r
+ return;\r
}\r
\r
-\r
/**\r
Generate a sub string then output it.\r
\r
\r
@param String A constant string which is the prefix of the to be\r
generated string, e.g. GUID=\r
+\r
@param BufferLen The length of the Buffer in bytes.\r
- @param Buffer Points to a buffer which will be converted to be the \r
- content of the generated string.\r
- @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in \r
- UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
- if 3, the buffer contains other data.\r
+\r
+ @param Buffer Points to a buffer which will be converted to be the\r
+ content of the generated string.\r
+\r
+ @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in\r
+ UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
+ if 3, the buffer contains other data.\r
+\r
@param SubStr Points to the output string. It's caller's\r
responsibility to free this buffer.\r
\r
**/\r
VOID\r
GenerateSubStr (\r
- IN CONST EFI_STRING String,\r
- IN UINTN BufferLen,\r
- IN VOID *Buffer,\r
- IN UINT8 Flag,\r
- OUT EFI_STRING *SubStr\r
+ IN CONST EFI_STRING String,\r
+ IN UINTN BufferLen,\r
+ IN VOID *Buffer,\r
+ IN UINT8 Flag,\r
+ OUT EFI_STRING *SubStr\r
)\r
{\r
UINTN Length;\r
EFI_STRING Str;\r
- EFI_STATUS Status;\r
EFI_STRING StringHeader;\r
+ CHAR16 *TemString;\r
+ CHAR16 *TemName;\r
+ UINT8 *TemBuffer;\r
+ UINTN Index;\r
\r
ASSERT (String != NULL && SubStr != NULL);\r
\r
if (Buffer == NULL) {\r
*SubStr = AllocateCopyPool (StrSize (String), String);\r
ASSERT (*SubStr != NULL);\r
- return ;\r
+ return;\r
}\r
\r
+ //\r
+ // Header + Data + '&' + '\0'\r
+ //\r
Length = StrLen (String) + BufferLen * 2 + 1 + 1;\r
- Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
ASSERT (Str != NULL);\r
\r
- StrCpy (Str, String);\r
- Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
+ StrCpyS (Str, Length, String);\r
\r
- Status = EFI_SUCCESS;\r
StringHeader = Str + StrLen (String);\r
+ TemString = (CHAR16 *)StringHeader;\r
\r
switch (Flag) {\r
- case 1:\r
- Status = BufInReverseOrderToHexString (StringHeader, (UINT8 *) Buffer, BufferLen);\r
- break;\r
- case 2:\r
- Status = UnicodeToConfigString (StringHeader, &Length, (CHAR16 *) Buffer);\r
- break;\r
- case 3:\r
- Status = BufToHexString (StringHeader, &Length, (UINT8 *) Buffer, BufferLen);\r
- //\r
- // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
- //\r
- ToLower (StringHeader);\r
- break;\r
- default:\r
- break;\r
+ case 1:\r
+ //\r
+ // Convert Buffer to Hex String in reverse order\r
+ //\r
+ TemBuffer = ((UINT8 *)Buffer);\r
+ for (Index = 0; Index < BufferLen; Index++, TemBuffer++) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));\r
+ }\r
+\r
+ break;\r
+ case 2:\r
+ //\r
+ // Check buffer is enough\r
+ //\r
+ TemName = (CHAR16 *)Buffer;\r
+ ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));\r
+ //\r
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+ //\r
+ for ( ; *TemName != L'\0'; TemName++) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemName,\r
+ 4\r
+ );\r
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));\r
+ }\r
+\r
+ break;\r
+ case 3:\r
+ //\r
+ // Convert Buffer to Hex String\r
+ //\r
+ TemBuffer = ((UINT8 *)Buffer) + BufferLen - 1;\r
+ for (Index = 0; Index < BufferLen; Index++, TemBuffer--) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ sizeof (CHAR16) * (Length - StrnLenS (Str, Length)),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, Length - StrnLenS (Str, Length));\r
+ }\r
+\r
+ break;\r
+ default:\r
+ break;\r
}\r
\r
- ASSERT_EFI_ERROR (Status);\r
- StrCat (Str, L"&");\r
+ //\r
+ // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.\r
+ //\r
+ StrCatS (Str, Length, L"&");\r
+ HiiToLower (Str);\r
\r
*SubStr = Str;\r
}\r
\r
-\r
/**\r
Retrieve the <ConfigBody> from String then output it.\r
\r
**/\r
EFI_STATUS\r
OutputConfigBody (\r
- IN EFI_STRING String,\r
- OUT EFI_STRING *ConfigBody\r
+ IN EFI_STRING String,\r
+ OUT EFI_STRING *ConfigBody\r
)\r
{\r
EFI_STRING TmpPtr;\r
EFI_STRING Result;\r
UINTN Length;\r
\r
- if (String == NULL || ConfigBody == NULL) {\r
+ if ((String == NULL) || (ConfigBody == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The setting information should start OFFSET, not ALTCFG.\r
+ //\r
+ if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
}\r
\r
Length = TmpPtr - String;\r
+ if (Length == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
if (Result == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
*(Result + Length - 1) = 0;\r
- *ConfigBody = Result;\r
+ *ConfigBody = Result;\r
return EFI_SUCCESS;\r
-\r
-}\r
-\r
-\r
-/**\r
- Adjusts the size of a previously allocated buffer.\r
-\r
-\r
- @param OldPool A pointer to the buffer whose size is being adjusted.\r
- @param OldSize The size of the current buffer.\r
- @param NewSize The size of the new buffer.\r
-\r
- @return The new buffer allocated.\r
-\r
-**/\r
-VOID *\r
-ReallocatePool (\r
- IN VOID *OldPool,\r
- IN UINTN OldSize,\r
- IN UINTN NewSize\r
- )\r
-{\r
- VOID *NewPool;\r
-\r
- NewPool = NULL;\r
- if (NewSize != 0) {\r
- NewPool = AllocateZeroPool (NewSize);\r
- }\r
-\r
- if (OldPool != NULL) {\r
- if (NewPool != NULL) {\r
- CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
- }\r
-\r
- gBS->FreePool (OldPool);\r
- }\r
-\r
- return NewPool;\r
}\r
\r
-\r
/**\r
Append a string to a multi-string format.\r
\r
**/\r
EFI_STATUS\r
AppendToMultiString (\r
- IN OUT EFI_STRING *MultiString,\r
- IN EFI_STRING AppendString\r
+ IN OUT EFI_STRING *MultiString,\r
+ IN EFI_STRING AppendString\r
)\r
{\r
- UINTN AppendStringSize;\r
- UINTN MultiStringSize;\r
+ UINTN AppendStringSize;\r
+ UINTN MultiStringSize;\r
+ UINTN MaxLen;\r
\r
- if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
+ if ((MultiString == NULL) || (*MultiString == NULL) || (AppendString == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
AppendStringSize = StrSize (AppendString);\r
MultiStringSize = StrSize (*MultiString);\r
+ MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);\r
\r
//\r
// Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
//\r
- if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
- MultiStringSize > MAX_STRING_LENGTH) {\r
- *MultiString = (EFI_STRING) ReallocatePool (\r
- (VOID *) (*MultiString),\r
- MultiStringSize,\r
- MultiStringSize + AppendStringSize\r
- );\r
+ if ((MultiStringSize + AppendStringSize > MAX_STRING_LENGTH) ||\r
+ (MultiStringSize > MAX_STRING_LENGTH))\r
+ {\r
+ *MultiString = (EFI_STRING)ReallocatePool (\r
+ MultiStringSize,\r
+ MultiStringSize + AppendStringSize,\r
+ (VOID *)(*MultiString)\r
+ );\r
+ MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);\r
+ ASSERT (*MultiString != NULL);\r
}\r
\r
//\r
// Append the incoming string\r
//\r
- StrCat (*MultiString, AppendString);\r
+ StrCatS (*MultiString, MaxLen, AppendString);\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
or WIDTH or VALUE.\r
to free memory.\r
@param Len Length of the <Number>, in characters.\r
\r
- @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary\r
structures.\r
@retval EFI_SUCCESS Value of <Number> is outputted in Number\r
successfully.\r
**/\r
EFI_STATUS\r
GetValueOfNumber (\r
- IN EFI_STRING StringPtr,\r
- OUT UINT8 **Number,\r
- OUT UINTN *Len\r
+ IN EFI_STRING StringPtr,\r
+ OUT UINT8 **Number,\r
+ OUT UINTN *Len\r
)\r
{\r
- EFI_STRING TmpPtr;\r
- UINTN Length;\r
- EFI_STRING Str;\r
- UINT8 *Buf;\r
- EFI_STATUS Status;\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STRING Str;\r
+ UINT8 *Buf;\r
+ EFI_STATUS Status;\r
+ UINT8 DigitUint8;\r
+ UINTN Index;\r
+ CHAR16 TemStr[2];\r
\r
- ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
- ASSERT (*StringPtr != 0);\r
+ if ((StringPtr == NULL) || (*StringPtr == L'\0') || (Number == NULL) || (Len == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
Buf = NULL;\r
\r
TmpPtr = StringPtr;\r
- while (*StringPtr != 0 && *StringPtr != L'&') {\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
StringPtr++;\r
}\r
+\r
*Len = StringPtr - TmpPtr;\r
Length = *Len + 1;\r
\r
- Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));\r
+ Str = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));\r
if (Str == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
+\r
CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
- *(Str + *Len) = 0;\r
+ *(Str + *Len) = L'\0';\r
\r
Length = (Length + 1) / 2;\r
- Buf = (UINT8 *) AllocateZeroPool (Length);\r
+ Buf = (UINT8 *)AllocateZeroPool (Length);\r
if (Buf == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
\r
- Status = HexStringToBuf (Buf, &Length, Str, NULL);\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
+ Length = *Len;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < Length; Index++) {\r
+ TemStr[0] = Str[Length - Index - 1];\r
+ DigitUint8 = (UINT8)StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ Buf[Index/2] = DigitUint8;\r
+ } else {\r
+ Buf[Index/2] = (UINT8)((DigitUint8 << 4) + Buf[Index/2]);\r
+ }\r
}\r
\r
*Number = Buf;\r
Status = EFI_SUCCESS;\r
\r
Exit:\r
- SafeFreePool (Str);\r
+ if (Str != NULL) {\r
+ FreePool (Str);\r
+ }\r
+\r
return Status;\r
}\r
\r
-\r
/**\r
- This function allows a caller to extract the current configuration\r
- for one or more named elements from one or more drivers.\r
+ To find the BlockName in the string with same value.\r
\r
- @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
- instance.\r
- @param Request A null-terminated Unicode string in\r
- <MultiConfigRequest> format.\r
- @param Progress On return, points to a character in the Request\r
- string. Points to the string's null terminator if\r
- request was successful. Points to the most recent\r
- & before the first failing name / value pair (or\r
- the beginning of the string if the failure is in\r
- the first name / value pair) if the request was\r
- not successful.\r
- @param Results Null-terminated Unicode string in\r
- <MultiConfigAltResp> format which has all values\r
- filled in for the names in the Request string.\r
- String to be allocated by the called function.\r
+ @param String Pointer to a Null-terminated Unicode string.\r
+ @param BlockName Pointer to a Null-terminated Unicode string to search for.\r
+ @param Buffer Pointer to the value correspond to the BlockName.\r
+ @param Found The Block whether has been found.\r
+ @param BufferLen The length of the buffer.\r
\r
- @retval EFI_SUCCESS The Results string is filled with the values\r
- corresponding to all requested names.\r
- @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
- results that must be stored awaiting possible\r
- future protocols.\r
- @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
- Progress set to the "G" in "GUID" of the routing\r
- header that doesn't match. Note: There is no\r
- requirement that all routing data be validated\r
- before any configuration extraction.\r
- @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
- parameter would result in this type of error. The\r
- Progress parameter is set to NULL.\r
- @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
- before the error or the beginning of the string.\r
- @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
- name in question.\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.\r
+ @retval EFI_SUCCESS The function finishes successfully.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-HiiConfigRoutingExtractConfig (\r
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
- IN CONST EFI_STRING Request,\r
- OUT EFI_STRING *Progress,\r
- OUT EFI_STRING *Results\r
+FindSameBlockElement (\r
+ IN EFI_STRING String,\r
+ IN EFI_STRING BlockName,\r
+ IN UINT8 *Buffer,\r
+ OUT BOOLEAN *Found,\r
+ IN UINTN BufferLen\r
)\r
{\r
- HII_DATABASE_PRIVATE_DATA *Private;\r
- EFI_STRING StringPtr;\r
- EFI_STRING ConfigRequest;\r
- UINTN Length;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- HII_DATABASE_RECORD *Database;\r
- UINT8 *DevicePathPkg;\r
- UINT8 *CurrentDevicePath;\r
- EFI_HANDLE DriverHandle;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_STRING AccessProgress;\r
- EFI_STRING AccessResults;\r
- UINTN RemainSize;\r
- EFI_STRING TmpPtr;\r
-\r
- //\r
- // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
- // as FALSE. But this renders the system to not 100% compliant with\r
- // UEFI 2.1. Use this with caution.\r
- //\r
- if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (This == NULL || Progress == NULL || Results == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ EFI_STRING BlockPtr;\r
+ UINTN Length;\r
+ UINT8 *TempBuffer;\r
+ EFI_STATUS Status;\r
\r
- if (Request == NULL) {\r
- *Progress = NULL;\r
- return EFI_INVALID_PARAMETER;\r
+ TempBuffer = NULL;\r
+ *Found = FALSE;\r
+ BlockPtr = StrStr (String, BlockName);\r
+\r
+ while (BlockPtr != NULL) {\r
+ BlockPtr += StrLen (BlockName);\r
+ Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ASSERT (TempBuffer != NULL);\r
+ if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {\r
+ *Found = TRUE;\r
+ FreePool (TempBuffer);\r
+ TempBuffer = NULL;\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ FreePool (TempBuffer);\r
+ TempBuffer = NULL;\r
+ BlockPtr = StrStr (BlockPtr + 1, BlockName);\r
+ }\r
}\r
\r
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
- StringPtr = Request;\r
- *Progress = StringPtr;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>\r
+ in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.\r
+\r
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
+ <MultiConfigAltResp> format. The default value\r
+ string may contain more than one ConfigAltResp\r
+ string for the different varstore buffer.\r
+ @param ConfigAltResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format.\r
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.\r
+ @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.\r
\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.\r
+ @retval EFI_SUCCESS The function finishes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareBlockElementDefault (\r
+ IN EFI_STRING DefaultAltCfgResp,\r
+ IN OUT EFI_STRING *ConfigAltResp,\r
+ IN EFI_STRING AltConfigHdr,\r
+ IN OUT BOOLEAN *ConfigAltRespChanged\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING BlockPtr;\r
+ EFI_STRING BlockPtrStart;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING AppendString;\r
+ EFI_STRING AltConfigHdrPtr;\r
+ UINT8 *TempBuffer;\r
+ UINTN OffsetLength;\r
+ UINTN AppendSize;\r
+ UINTN TotalSize;\r
+ BOOLEAN FoundOffset;\r
+\r
+ AppendString = NULL;\r
+ TempBuffer = NULL;\r
//\r
- // The first element of <MultiConfigRequest> should be\r
- // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+ // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.\r
//\r
- if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
+ AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+ ASSERT (AltConfigHdrPtr != NULL);\r
+ BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");\r
//\r
- // Allocate a fix length of memory to store Results. Reallocate memory for\r
- // Results if this fix length is insufficient.\r
+ // Make StringPtr point to the AltConfigHdr in ConfigAltResp.\r
//\r
- *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
- if (*Results == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);\r
+ ASSERT (StringPtr != NULL);\r
\r
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+ while (BlockPtr != NULL) {\r
//\r
- // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
- // or most recent & before the error.\r
+ // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.\r
//\r
- if (StringPtr == Request) {\r
- *Progress = StringPtr;\r
- } else {\r
- *Progress = StringPtr - 1;\r
+ BlockPtrStart = BlockPtr;\r
+ BlockPtr += StrLen (L"&OFFSET=");\r
+ Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // To find the same "&OFFSET=<Number>" block in ConfigAltResp.\r
+ //\r
+ Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);\r
+ if (TempBuffer != NULL) {\r
+ FreePool (TempBuffer);\r
+ TempBuffer = NULL;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ if (!FoundOffset) {\r
+ //\r
+ // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.\r
+ // Calculate the size of <BlockConfig>.\r
+ // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.\r
+ //\r
+ BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");\r
+ if (BlockPtr != NULL) {\r
+ AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);\r
+ } else {\r
+ AppendSize = StrSize (BlockPtrStart);\r
+ }\r
+\r
+ //\r
+ // Copy the <BlockConfig> to AppendString.\r
+ //\r
+ if (AppendString == NULL) {\r
+ AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));\r
+ StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));\r
+ } else {\r
+ TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);\r
+ AppendString = (EFI_STRING)ReallocatePool (\r
+ StrSize (AppendString),\r
+ TotalSize,\r
+ AppendString\r
+ );\r
+ if (AppendString == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));\r
+ }\r
+ } else {\r
+ //\r
+ // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.\r
+ //\r
+ BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");\r
+ }\r
+ }\r
+\r
+ if (AppendString != NULL) {\r
+ //\r
+ // Reallocate ConfigAltResp to copy the AppendString.\r
+ //\r
+ TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);\r
+ *ConfigAltResp = (EFI_STRING)ReallocatePool (\r
+ StrSize (*ConfigAltResp),\r
+ TotalSize,\r
+ *ConfigAltResp\r
+ );\r
+ if (*ConfigAltResp == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);\r
+ *ConfigAltRespChanged = TRUE;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ if (AppendString != NULL) {\r
+ FreePool (AppendString);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>\r
+ in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.\r
+\r
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
+ <MultiConfigAltResp> format. The default value\r
+ string may contain more than one ConfigAltResp\r
+ string for the different varstore buffer.\r
+ @param ConfigAltResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format.\r
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.\r
+ @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.\r
+ @retval EFI_SUCCESS The function finishes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareNameElementDefault (\r
+ IN EFI_STRING DefaultAltCfgResp,\r
+ IN OUT EFI_STRING *ConfigAltResp,\r
+ IN EFI_STRING AltConfigHdr,\r
+ IN OUT BOOLEAN *ConfigAltRespChanged\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING NvConfigPtr;\r
+ EFI_STRING NvConfigStart;\r
+ EFI_STRING NvConfigValuePtr;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING NvConfigExist;\r
+ EFI_STRING AppendString;\r
+ CHAR16 TempChar;\r
+ UINTN AppendSize;\r
+ UINTN TotalSize;\r
+\r
+ AppendString = NULL;\r
+ NvConfigExist = NULL;\r
+ //\r
+ // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.\r
+ //\r
+ NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+ ASSERT (NvConfigPtr != NULL);\r
+ NvConfigPtr = StrStr (NvConfigPtr + StrLen (AltConfigHdr), L"&");\r
+ //\r
+ // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.\r
+ //\r
+ StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);\r
+ ASSERT (StringPtr != NULL);\r
+ StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ while (NvConfigPtr != NULL) {\r
+ //\r
+ // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.\r
+ // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.\r
+ //\r
+ NvConfigStart = NvConfigPtr;\r
+ NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");\r
+ ASSERT (NvConfigValuePtr != NULL);\r
+ TempChar = *NvConfigValuePtr;\r
+ *NvConfigValuePtr = L'\0';\r
+ //\r
+ // Get the <Label> with AltConfigHdr in ConfigAltResp.\r
+ //\r
+ NvConfigExist = StrStr (StringPtr, NvConfigPtr);\r
+ if (NvConfigExist == NULL) {\r
+ //\r
+ // Don't find same <Label> in ConfigAltResp.\r
+ // Calculate the size of <NvConfig>.\r
+ //\r
+ *NvConfigValuePtr = TempChar;\r
+ NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");\r
+ if (NvConfigPtr != NULL) {\r
+ AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);\r
+ } else {\r
+ AppendSize = StrSize (NvConfigStart);\r
+ }\r
+\r
+ //\r
+ // Copy the <NvConfig> to AppendString.\r
+ //\r
+ if (AppendString == NULL) {\r
+ AppendString = (EFI_STRING)AllocateZeroPool (AppendSize + sizeof (CHAR16));\r
+ StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));\r
+ } else {\r
+ TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);\r
+ AppendString = (EFI_STRING)ReallocatePool (\r
+ StrSize (AppendString),\r
+ TotalSize,\r
+ AppendString\r
+ );\r
+ if (AppendString == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));\r
+ }\r
+ } else {\r
+ //\r
+ // To find next <Label> in DefaultAltCfgResp.\r
+ //\r
+ *NvConfigValuePtr = TempChar;\r
+ NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");\r
+ }\r
+ }\r
+\r
+ if (AppendString != NULL) {\r
+ //\r
+ // Reallocate ConfigAltResp to copy the AppendString.\r
+ //\r
+ TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);\r
+ *ConfigAltResp = (EFI_STRING)ReallocatePool (\r
+ StrSize (*ConfigAltResp),\r
+ StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),\r
+ *ConfigAltResp\r
+ );\r
+ if (*ConfigAltResp == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);\r
+ *ConfigAltRespChanged = TRUE;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ if (AppendString != NULL) {\r
+ FreePool (AppendString);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>\r
+ in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.\r
+\r
+ @param AltCfgResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format.\r
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
+ <MultiConfigAltResp> format. The default value\r
+ string may contain more than one ConfigAltResp\r
+ string for the different varstore buffer.\r
+ @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary\r
+ structures.\r
+ @retval EFI_SUCCESS The function finishes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareAndMergeDefaultString (\r
+ IN OUT EFI_STRING *AltCfgResp,\r
+ IN EFI_STRING DefaultAltCfgResp,\r
+ IN EFI_STRING AltConfigHdr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING AltCfgRespBackup;\r
+ EFI_STRING AltConfigHdrPtr;\r
+ EFI_STRING AltConfigHdrPtrNext;\r
+ EFI_STRING ConfigAltResp;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING StringPtrNext;\r
+ EFI_STRING BlockPtr;\r
+ UINTN ReallocateSize;\r
+ CHAR16 TempChar;\r
+ CHAR16 TempCharA;\r
+ BOOLEAN ConfigAltRespChanged;\r
+\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ BlockPtr = NULL;\r
+ AltConfigHdrPtrNext = NULL;\r
+ StringPtrNext = NULL;\r
+ ConfigAltResp = NULL;\r
+ AltCfgRespBackup = NULL;\r
+ TempChar = L'\0';\r
+ TempCharA = L'\0';\r
+ ConfigAltRespChanged = FALSE;\r
+\r
+ //\r
+ // To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.\r
+ //\r
+ AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+ ASSERT (AltConfigHdrPtr != NULL);\r
+ AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");\r
+ if (AltConfigHdrPtrNext != NULL) {\r
+ TempChar = *AltConfigHdrPtrNext;\r
+ *AltConfigHdrPtrNext = L'\0';\r
+ }\r
+\r
+ //\r
+ // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.\r
+ //\r
+ StringPtr = StrStr (*AltCfgResp, AltConfigHdr);\r
+ ASSERT (StringPtr != NULL);\r
+ StringPtrNext = StrStr (StringPtr + 1, L"&GUID");\r
+ if (StringPtrNext != NULL) {\r
+ TempCharA = *StringPtrNext;\r
+ *StringPtrNext = L'\0';\r
+ }\r
+\r
+ //\r
+ // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.\r
+ //\r
+ ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);\r
+ if (ConfigAltResp == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.\r
+ //\r
+ BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");\r
+ if (BlockPtr != NULL) {\r
+ //\r
+ // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.\r
+ // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.\r
+ // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.\r
+ //\r
+ Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ //\r
+ // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.\r
+ // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.\r
+ // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.\r
+ //\r
+ Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Restore the AltCfgResp.\r
+ //\r
+ if (StringPtrNext != NULL) {\r
+ *StringPtrNext = TempCharA;\r
+ }\r
+\r
+ //\r
+ // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.\r
+ //\r
+ if (!ConfigAltRespChanged) {\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // ConfigAltResp has been changed, need to update the content in AltCfgResp.\r
+ //\r
+ if (StringPtrNext != NULL) {\r
+ ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);\r
+ } else {\r
+ ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);\r
+ }\r
+\r
+ AltCfgRespBackup = (EFI_STRING)AllocateZeroPool (ReallocateSize);\r
+ if (AltCfgRespBackup == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);\r
+ if (StringPtrNext != NULL) {\r
+ StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);\r
+ }\r
+\r
+ FreePool (*AltCfgResp);\r
+ *AltCfgResp = AltCfgRespBackup;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ if (ConfigAltResp != NULL) {\r
+ FreePool (ConfigAltResp);\r
+ }\r
+\r
+ //\r
+ // Restore the DefaultAltCfgResp.\r
+ //\r
+ if ( AltConfigHdrPtrNext != NULL) {\r
+ *AltConfigHdrPtrNext = TempChar;\r
+ AltConfigHdrPtrNext = NULL;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function merges DefaultAltCfgResp string into AltCfgResp string for\r
+ the missing AltCfgId in AltCfgResq.\r
+\r
+ @param AltCfgResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format. The default value string\r
+ will be merged into it.\r
+ @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in\r
+ <MultiConfigAltResp> format. The default value\r
+ string may contain more than one ConfigAltResp\r
+ string for the different varstore buffer.\r
+\r
+ @retval EFI_SUCCESS The merged string returns.\r
+ @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MergeDefaultString (\r
+ IN OUT EFI_STRING *AltCfgResp,\r
+ IN EFI_STRING DefaultAltCfgResp\r
+ )\r
+{\r
+ EFI_STRING StringPtrDefault;\r
+ EFI_STRING StringPtrEnd;\r
+ CHAR16 TempChar;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING AltConfigHdr;\r
+ UINTN HeaderLength;\r
+ UINTN SizeAltCfgResp;\r
+ UINTN MaxLen;\r
+ UINTN TotalSize;\r
+\r
+ if (*AltCfgResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Get the request ConfigHdr\r
+ //\r
+ SizeAltCfgResp = 0;\r
+ StringPtr = *AltCfgResp;\r
+\r
+ //\r
+ // Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&PATH=");\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+\r
+ HeaderLength = StringPtr - *AltCfgResp;\r
+\r
+ //\r
+ // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |\r
+ //\r
+ MaxLen = 1 + HeaderLength + 8 + 4 + 1;\r
+ AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+ if (AltConfigHdr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StrCpyS (AltConfigHdr, MaxLen, L"&");\r
+ StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);\r
+ StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");\r
+ HeaderLength = StrLen (AltConfigHdr);\r
+\r
+ StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+ while (StringPtrDefault != NULL) {\r
+ //\r
+ // Get AltCfg Name\r
+ //\r
+ StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);\r
+ StringPtr = StrStr (*AltCfgResp, AltConfigHdr);\r
+\r
+ //\r
+ // Append the found default value string to the input AltCfgResp\r
+ //\r
+ if (StringPtr == NULL) {\r
+ StringPtrEnd = StrStr (StringPtrDefault + 1, L"&GUID");\r
+ SizeAltCfgResp = StrSize (*AltCfgResp);\r
+ if (StringPtrEnd == NULL) {\r
+ //\r
+ // No more default string is found.\r
+ //\r
+ TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);\r
+ *AltCfgResp = (EFI_STRING)ReallocatePool (\r
+ SizeAltCfgResp,\r
+ TotalSize,\r
+ (VOID *)(*AltCfgResp)\r
+ );\r
+ if (*AltCfgResp == NULL) {\r
+ FreePool (AltConfigHdr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);\r
+ break;\r
+ } else {\r
+ TempChar = *StringPtrEnd;\r
+ *StringPtrEnd = L'\0';\r
+ TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);\r
+ *AltCfgResp = (EFI_STRING)ReallocatePool (\r
+ SizeAltCfgResp,\r
+ TotalSize,\r
+ (VOID *)(*AltCfgResp)\r
+ );\r
+ if (*AltCfgResp == NULL) {\r
+ FreePool (AltConfigHdr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);\r
+ *StringPtrEnd = TempChar;\r
+ }\r
+ } else {\r
+ //\r
+ // The AltCfgResp contains <AltCfgResp>.\r
+ // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the\r
+ // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.\r
+ //\r
+ CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);\r
+ }\r
+\r
+ //\r
+ // Find next AltCfg String\r
+ //\r
+ *(AltConfigHdr + HeaderLength) = L'\0';\r
+ StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);\r
+ }\r
+\r
+ FreePool (AltConfigHdr);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function inserts new DefaultValueData into the BlockData DefaultValue array.\r
+\r
+ @param BlockData The BlockData is updated to add new default value.\r
+ @param DefaultValueData The DefaultValue is added.\r
+\r
+**/\r
+VOID\r
+InsertDefaultValue (\r
+ IN IFR_BLOCK_DATA *BlockData,\r
+ IN IFR_DEFAULT_DATA *DefaultValueData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_DEFAULT_DATA *DefaultValueArray;\r
+ LIST_ENTRY *DefaultLink;\r
+\r
+ DefaultLink = &BlockData->DefaultValueEntry;\r
+\r
+ for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {\r
+ DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {\r
+ //\r
+ // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.\r
+ // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.\r
+ //\r
+ if ((DefaultValueData->Type > DefaultValueArray->Type) || ((DefaultValueData->Type == DefaultValueArray->Type) && (DefaultValueData->Type == DefaultValueFromOtherDefault))) {\r
+ //\r
+ // Update the default value array in BlockData.\r
+ //\r
+ CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ DefaultValueArray->Type = DefaultValueData->Type;\r
+ DefaultValueArray->Cleaned = DefaultValueData->Cleaned;\r
+ }\r
+\r
+ return;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Insert new default value data in tail.\r
+ //\r
+ DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ ASSERT (DefaultValueArray != NULL);\r
+ CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));\r
+ InsertTailList (Link, &DefaultValueArray->Entry);\r
+}\r
+\r
+/**\r
+ This function inserts new BlockData into the block link\r
+\r
+ @param BlockLink The list entry points to block array.\r
+ @param BlockData The point to BlockData is added.\r
+\r
+**/\r
+VOID\r
+InsertBlockData (\r
+ IN LIST_ENTRY *BlockLink,\r
+ IN IFR_BLOCK_DATA **BlockData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *BlockArray;\r
+ IFR_BLOCK_DATA *BlockSingleData;\r
+\r
+ BlockSingleData = *BlockData;\r
+\r
+ if (BlockSingleData->Name != NULL) {\r
+ InsertTailList (BlockLink, &BlockSingleData->Entry);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Insert block data in its Offset and Width order.\r
+ //\r
+ for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
+ BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (BlockArray->Offset == BlockSingleData->Offset) {\r
+ if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && (BlockArray->Width == BlockSingleData->Width))) {\r
+ //\r
+ // Insert this block data in the front of block array\r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+ return;\r
+ }\r
+\r
+ if ((!BlockSingleData->IsBitVar) && (BlockArray->Width == BlockSingleData->Width)) {\r
+ //\r
+ // The same block array has been added.\r
+ //\r
+ if (BlockSingleData != BlockArray) {\r
+ FreePool (BlockSingleData);\r
+ *BlockData = BlockArray;\r
+ }\r
+\r
+ return;\r
+ }\r
+ } else if (BlockArray->Offset > BlockSingleData->Offset) {\r
+ //\r
+ // Insert new block data in the front of block array\r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+ return;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add new block data into the tail.\r
+ //\r
+ InsertTailList (Link, &BlockSingleData->Entry);\r
+}\r
+\r
+/**\r
+ Retrieves a pointer to the a Null-terminated ASCII string containing the list\r
+ of languages that an HII handle in the HII Database supports. The returned\r
+ string is allocated using AllocatePool(). The caller is responsible for freeing\r
+ the returned string using FreePool(). The format of the returned string follows\r
+ the language format assumed the HII Database.\r
+\r
+ If HiiHandle is NULL, then ASSERT().\r
+\r
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
+\r
+ @retval NULL HiiHandle is not registered in the HII database\r
+ @retval NULL There are not enough resources available to retrieve the supported\r
+ languages.\r
+ @retval NULL The list of supported languages could not be retrieved.\r
+ @retval Other A pointer to the Null-terminated ASCII string of supported languages.\r
+\r
+**/\r
+CHAR8 *\r
+GetSupportedLanguages (\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN LanguageSize;\r
+ CHAR8 TempSupportedLanguages;\r
+ CHAR8 *SupportedLanguages;\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+\r
+ //\r
+ // Retrieve the size required for the supported languages buffer.\r
+ //\r
+ LanguageSize = 0;\r
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);\r
+\r
+ //\r
+ // If GetLanguages() returns EFI_SUCCESS for a zero size,\r
+ // then there are no supported languages registered for HiiHandle. If GetLanguages()\r
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
+ // in the HII Database\r
+ //\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Allocate the supported languages buffer.\r
+ //\r
+ SupportedLanguages = AllocateZeroPool (LanguageSize);\r
+ if (SupportedLanguages == NULL) {\r
+ //\r
+ // Return NULL if allocation fails.\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve the supported languages string\r
+ //\r
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Free the buffer and return NULL if the supported languages can not be retrieved.\r
+ //\r
+ FreePool (SupportedLanguages);\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Return the Null-terminated ASCII string of supported languages\r
+ //\r
+ return SupportedLanguages;\r
+}\r
+\r
+/**\r
+ Retrieves a string from a string package.\r
+\r
+ If HiiHandle is NULL, then ASSERT().\r
+ If StringId is 0, then ASSET.\r
+\r
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.\r
+ @param[in] StringId The identifier of the string to retrieved from the string\r
+ package associated with HiiHandle.\r
+\r
+ @retval NULL The string specified by StringId is not present in the string package.\r
+ @retval Other The string was returned.\r
+\r
+**/\r
+EFI_STRING\r
+InternalGetString (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_STRING_ID StringId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN StringSize;\r
+ CHAR16 TempString;\r
+ EFI_STRING String;\r
+ CHAR8 *SupportedLanguages;\r
+ CHAR8 *PlatformLanguage;\r
+ CHAR8 *BestLanguage;\r
+ CHAR8 *Language;\r
+\r
+ ASSERT (HiiHandle != NULL);\r
+ ASSERT (StringId != 0);\r
+\r
+ //\r
+ // Initialize all allocated buffers to NULL\r
+ //\r
+ SupportedLanguages = NULL;\r
+ PlatformLanguage = NULL;\r
+ BestLanguage = NULL;\r
+ String = NULL;\r
+ Language = "";\r
+\r
+ //\r
+ // Get the languages that the package specified by HiiHandle supports\r
+ //\r
+ SupportedLanguages = GetSupportedLanguages (HiiHandle);\r
+ if (SupportedLanguages == NULL) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Get the current platform language setting\r
+ //\r
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);\r
+\r
+ //\r
+ // Get the best matching language from SupportedLanguages\r
+ //\r
+ BestLanguage = GetBestLanguage (\r
+ SupportedLanguages,\r
+ FALSE, // RFC 4646 mode\r
+ Language, // Highest priority\r
+ PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority\r
+ SupportedLanguages, // Lowest priority\r
+ NULL\r
+ );\r
+ if (BestLanguage == NULL) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Retrieve the size of the string in the string package for the BestLanguage\r
+ //\r
+ StringSize = 0;\r
+ Status = mPrivate.HiiString.GetString (\r
+ &mPrivate.HiiString,\r
+ BestLanguage,\r
+ HiiHandle,\r
+ StringId,\r
+ &TempString,\r
+ &StringSize,\r
+ NULL\r
+ );\r
+ //\r
+ // If GetString() returns EFI_SUCCESS for a zero size,\r
+ // then there are no supported languages registered for HiiHandle. If GetString()\r
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
+ // in the HII Database\r
+ //\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Allocate a buffer for the return string\r
+ //\r
+ String = AllocateZeroPool (StringSize);\r
+ if (String == NULL) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Retrieve the string from the string package\r
+ //\r
+ Status = mPrivate.HiiString.GetString (\r
+ &mPrivate.HiiString,\r
+ BestLanguage,\r
+ HiiHandle,\r
+ StringId,\r
+ String,\r
+ &StringSize,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Free the buffer and return NULL if the supported languages can not be retrieved.\r
+ //\r
+ FreePool (String);\r
+ String = NULL;\r
+ }\r
+\r
+Error:\r
+ //\r
+ // Free allocated buffers\r
+ //\r
+ if (SupportedLanguages != NULL) {\r
+ FreePool (SupportedLanguages);\r
+ }\r
+\r
+ if (PlatformLanguage != NULL) {\r
+ FreePool (PlatformLanguage);\r
+ }\r
+\r
+ if (BestLanguage != NULL) {\r
+ FreePool (BestLanguage);\r
+ }\r
+\r
+ //\r
+ // Return the Null-terminated Unicode string\r
+ //\r
+ return String;\r
+}\r
+\r
+/**\r
+ This function checks VarOffset and VarWidth is in the block range.\r
+\r
+ @param RequestBlockArray The block array is to be checked.\r
+ @param VarOffset Offset of var to the structure\r
+ @param VarWidth Width of var.\r
+ @param IsNameValueType Whether this varstore is name/value varstore or not.\r
+ @param HiiHandle Hii handle for this hii package.\r
+\r
+ @retval TRUE This Var is in the block range.\r
+ @retval FALSE This Var is not in the block range.\r
+**/\r
+BOOLEAN\r
+BlockArrayCheck (\r
+ IN IFR_BLOCK_DATA *RequestBlockArray,\r
+ IN UINT16 VarOffset,\r
+ IN UINT16 VarWidth,\r
+ IN BOOLEAN IsNameValueType,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ EFI_STRING Name;\r
+\r
+ //\r
+ // No Request Block array, all vars are got.\r
+ //\r
+ if (RequestBlockArray == NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check the input var is in the request block range.\r
+ //\r
+ for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+\r
+ if (IsNameValueType) {\r
+ Name = InternalGetString (HiiHandle, VarOffset);\r
+ ASSERT (Name != NULL);\r
+\r
+ if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {\r
+ FreePool (Name);\r
+ return TRUE;\r
+ }\r
+\r
+ FreePool (Name);\r
+ } else {\r
+ if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get form package data from data base.\r
+\r
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
+ @param HiiFormPackage The buffer saves the package data.\r
+ @param PackageSize The buffer size of the package data.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFormPackageData (\r
+ IN HII_DATABASE_RECORD *DataBaseRecord,\r
+ IN OUT UINT8 **HiiFormPackage,\r
+ OUT UINTN *PackageSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ UINTN ResultSize;\r
+\r
+ if ((DataBaseRecord == NULL) || (HiiFormPackage == NULL) || (PackageSize == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Size = 0;\r
+ ResultSize = 0;\r
+ //\r
+ // 0. Get Hii Form Package by HiiHandle\r
+ //\r
+ Status = ExportFormPackages (\r
+ &mPrivate,\r
+ DataBaseRecord->Handle,\r
+ DataBaseRecord->PackageList,\r
+ 0,\r
+ Size,\r
+ HiiFormPackage,\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ (*HiiFormPackage) = AllocatePool (ResultSize);\r
+ if (*HiiFormPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get HiiFormPackage by HiiHandle\r
+ //\r
+ Size = ResultSize;\r
+ ResultSize = 0;\r
+ Status = ExportFormPackages (\r
+ &mPrivate,\r
+ DataBaseRecord->Handle,\r
+ DataBaseRecord->PackageList,\r
+ 0,\r
+ Size,\r
+ *HiiFormPackage,\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (*HiiFormPackage);\r
+ }\r
+\r
+ *PackageSize = Size;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
+\r
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
+ the first found varstore will be as ConfigHdr.\r
+ @param IsEfiVarstore Whether the request storage type is efi varstore type.\r
+ @param EfiVarStore The efi varstore info which will return.\r
+**/\r
+EFI_STATUS\r
+GetVarStoreType (\r
+ IN HII_DATABASE_RECORD *DataBaseRecord,\r
+ IN EFI_STRING ConfigHdr,\r
+ OUT BOOLEAN *IsEfiVarstore,\r
+ OUT EFI_IFR_VARSTORE_EFI **EfiVarStore\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN IfrOffset;\r
+ UINTN PackageOffset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ CHAR16 *VarStoreName;\r
+ UINTN NameSize;\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING TempStr;\r
+ UINTN LengthString;\r
+ UINT8 *HiiFormPackage;\r
+ UINTN PackageSize;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+ EFI_HII_PACKAGE_HEADER *PackageHeader;\r
+\r
+ HiiFormPackage = NULL;\r
+ LengthString = 0;\r
+ Status = EFI_SUCCESS;\r
+ GuidStr = NULL;\r
+ NameStr = NULL;\r
+ TempStr = NULL;\r
+ *IsEfiVarstore = FALSE;\r
+\r
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageOffset = IfrOffset;\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;\r
+\r
+ while (IfrOffset < PackageSize) {\r
+ //\r
+ // More than one form packages exist.\r
+ //\r
+ if (PackageOffset >= PackageHeader->Length) {\r
+ //\r
+ // Process the new form package.\r
+ //\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ IfrOffset += PackageOffset;\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);\r
+ }\r
+\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);\r
+ IfrOffset += IfrOpHdr->Length;\r
+ PackageOffset += IfrOpHdr->Length;\r
+\r
+ if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;\r
+ //\r
+ // If the length is small than the structure, this is from old efi\r
+ // varstore definition. Old efi varstore get config directly from\r
+ // GetVariable function.\r
+ //\r
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+ continue;\r
+ }\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);\r
+\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&IfrEfiVarStore->Guid, 1, &GuidStr);\r
+ GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *)VarStoreName, 2, &NameStr);\r
+ LengthString = StrLen (GuidStr);\r
+ LengthString = LengthString + StrLen (NameStr) + 1;\r
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
+ if (TempStr == NULL) {\r
+ FreePool (GuidStr);\r
+ FreePool (NameStr);\r
+ FreePool (VarStoreName);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ StrCpyS (TempStr, LengthString, GuidStr);\r
+ StrCatS (TempStr, LengthString, NameStr);\r
+ if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {\r
+ *EfiVarStore = (EFI_IFR_VARSTORE_EFI *)AllocateZeroPool (IfrOpHdr->Length);\r
+ if (*EfiVarStore == NULL) {\r
+ FreePool (VarStoreName);\r
+ FreePool (GuidStr);\r
+ FreePool (NameStr);\r
+ FreePool (TempStr);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ *IsEfiVarstore = TRUE;\r
+ CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);\r
+ }\r
+\r
+ //\r
+ // Free allocated temp string.\r
+ //\r
+ FreePool (VarStoreName);\r
+ FreePool (GuidStr);\r
+ FreePool (NameStr);\r
+ FreePool (TempStr);\r
+\r
+ //\r
+ // Already found the varstore, break;\r
+ //\r
+ if (*IsEfiVarstore) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+ if (HiiFormPackage != NULL) {\r
+ FreePool (HiiFormPackage);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check whether the ConfigRequest string has the request elements.\r
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
+\r
+ @param ConfigRequest The input config request string.\r
+\r
+ @retval TRUE The input include config request elements.\r
+ @retval FALSE The input string not includes.\r
+\r
+**/\r
+BOOLEAN\r
+GetElementsFromRequest (\r
+ IN EFI_STRING ConfigRequest\r
+ )\r
+{\r
+ EFI_STRING TmpRequest;\r
+\r
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
+ ASSERT (TmpRequest != NULL);\r
+\r
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Check whether the this varstore is the request varstore.\r
+\r
+ @param VarstoreGuid Varstore guid.\r
+ @param Name Varstore name.\r
+ @param ConfigHdr Current configRequest info.\r
+\r
+ @retval TRUE This varstore is the request one.\r
+ @retval FALSE This varstore is not the request one.\r
+\r
+**/\r
+BOOLEAN\r
+IsThisVarstore (\r
+ IN EFI_GUID *VarstoreGuid,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *ConfigHdr\r
+ )\r
+{\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING TempStr;\r
+ UINTN LengthString;\r
+ BOOLEAN RetVal;\r
+\r
+ RetVal = FALSE;\r
+ GuidStr = NULL;\r
+ TempStr = NULL;\r
+\r
+ //\r
+ // If ConfigHdr has name field and varstore not has name, return FALSE.\r
+ //\r
+ if ((Name == NULL) && (ConfigHdr != NULL) && (StrStr (ConfigHdr, L"NAME=&") == NULL)) {\r
+ return FALSE;\r
+ }\r
+\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);\r
+ if (Name != NULL) {\r
+ GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);\r
+ } else {\r
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
+ }\r
+\r
+ LengthString = StrLen (GuidStr);\r
+ LengthString = LengthString + StrLen (NameStr) + 1;\r
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));\r
+ if (TempStr == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ StrCpyS (TempStr, LengthString, GuidStr);\r
+ StrCatS (TempStr, LengthString, NameStr);\r
+\r
+ if ((ConfigHdr == NULL) || (StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0)) {\r
+ RetVal = TRUE;\r
+ }\r
+\r
+Done:\r
+ if (GuidStr != NULL) {\r
+ FreePool (GuidStr);\r
+ }\r
+\r
+ if (NameStr != NULL) {\r
+ FreePool (NameStr);\r
+ }\r
+\r
+ if (TempStr != NULL) {\r
+ FreePool (TempStr);\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\r
+ This function parses Form Package to get the efi varstore info according to the request ConfigHdr.\r
+\r
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
+ the first found varstore will be as ConfigHdr.\r
+ @retval TRUE This hii package is the request one.\r
+ @retval FALSE This hii package is not the request one.\r
+**/\r
+BOOLEAN\r
+IsThisPackageList (\r
+ IN HII_DATABASE_RECORD *DataBaseRecord,\r
+ IN EFI_STRING ConfigHdr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN IfrOffset;\r
+ UINTN PackageOffset;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ CHAR16 *VarStoreName;\r
+ UINTN NameSize;\r
+ UINT8 *HiiFormPackage;\r
+ UINTN PackageSize;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+ EFI_HII_PACKAGE_HEADER *PackageHeader;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\r
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
+ BOOLEAN FindVarstore;\r
+\r
+ HiiFormPackage = NULL;\r
+ VarStoreName = NULL;\r
+ Status = EFI_SUCCESS;\r
+ FindVarstore = FALSE;\r
+\r
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageOffset = IfrOffset;\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiFormPackage;\r
+\r
+ while (IfrOffset < PackageSize) {\r
+ //\r
+ // More than one form packages exist.\r
+ //\r
+ if (PackageOffset >= PackageHeader->Length) {\r
+ //\r
+ // Process the new form package.\r
+ //\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ IfrOffset += PackageOffset;\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiFormPackage + IfrOffset);\r
+ }\r
+\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(HiiFormPackage + IfrOffset);\r
+ IfrOffset += IfrOpHdr->Length;\r
+ PackageOffset += IfrOpHdr->Length;\r
+\r
+ switch (IfrOpHdr->OpCode) {\r
+ case EFI_IFR_VARSTORE_OP:\r
+ IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);\r
+\r
+ if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
+ FindVarstore = TRUE;\r
+ goto Done;\r
+ } else {\r
+ FreePool (VarStoreName);\r
+ VarStoreName = NULL;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;\r
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);\r
+\r
+ if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
+ FindVarstore = TRUE;\r
+ goto Done;\r
+ } else {\r
+ FreePool (VarStoreName);\r
+ VarStoreName = NULL;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+ IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;\r
+\r
+ if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
+ FindVarstore = TRUE;\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+ //\r
+ // No matched varstore is found and directly return.\r
+ //\r
+ goto Done;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+Done:\r
+ if (HiiFormPackage != NULL) {\r
+ FreePool (HiiFormPackage);\r
+ }\r
+\r
+ if (VarStoreName != NULL) {\r
+ FreePool (VarStoreName);\r
+ }\r
+\r
+ return FindVarstore;\r
+}\r
+\r
+/**\r
+ Check whether the this op code is required.\r
+\r
+ @param RequestBlockArray The array includes all the request info or NULL.\r
+ @param HiiHandle The hii handle for this form package.\r
+ @param VarStorageData The varstore data structure.\r
+ @param IfrOpHdr Ifr opcode header for this opcode.\r
+ @param VarWidth The buffer width for this opcode.\r
+ @param ReturnData The data block added for this opcode.\r
+ @param IsBitVar Whether the the opcode refers to bit storage.\r
+\r
+ @retval EFI_SUCCESS This opcode is required.\r
+ @retval EFI_NOT_FOUND This opcode is not required.\r
+ @retval Others Contain some error.\r
+\r
+**/\r
+EFI_STATUS\r
+IsThisOpcodeRequired (\r
+ IN IFR_BLOCK_DATA *RequestBlockArray,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
+ IN EFI_IFR_OP_HEADER *IfrOpHdr,\r
+ IN UINT16 VarWidth,\r
+ OUT IFR_BLOCK_DATA **ReturnData,\r
+ IN BOOLEAN IsBitVar\r
+ )\r
+{\r
+ IFR_BLOCK_DATA *BlockData;\r
+ UINT16 VarOffset;\r
+ EFI_STRING_ID NameId;\r
+ EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;\r
+ UINT16 BitOffset;\r
+ UINT16 BitWidth;\r
+ UINT16 TotalBits;\r
+\r
+ NameId = 0;\r
+ VarOffset = 0;\r
+ BitOffset = 0;\r
+ BitWidth = 0;\r
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));\r
+\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ NameId = IfrQuestionHdr->VarStoreInfo.VarName;\r
+\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ } else {\r
+ //\r
+ // Get the byte offset/with and bit offset/width\r
+ //\r
+ if (IsBitVar) {\r
+ BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
+ BitWidth = VarWidth;\r
+ VarOffset = BitOffset / 8;\r
+ //\r
+ // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.\r
+ //\r
+ TotalBits = BitOffset % 8 + BitWidth;\r
+ VarWidth = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);\r
+ } else {\r
+ VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;\r
+ BitWidth = VarWidth;\r
+ BitOffset = VarOffset * 8;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if (((VarOffset + VarWidth) > VarStorageData->Size)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ BlockData->Name = InternalGetString (HiiHandle, NameId);\r
+ } else {\r
+ BlockData->Offset = VarOffset;\r
+ }\r
+\r
+ BlockData->Width = VarWidth;\r
+ BlockData->QuestionId = IfrQuestionHdr->QuestionId;\r
+ BlockData->OpCode = IfrOpHdr->OpCode;\r
+ BlockData->Scope = IfrOpHdr->Scope;\r
+ BlockData->IsBitVar = IsBitVar;\r
+ BlockData->BitOffset = BitOffset;\r
+ BlockData->BitWidth = BitWidth;\r
+ InitializeListHead (&BlockData->DefaultValueEntry);\r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+ *ReturnData = BlockData;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function parses Form Package to get the block array and the default\r
+ value array according to the request ConfigHdr.\r
+\r
+ @param HiiHandle Hii Handle for this hii package.\r
+ @param Package Pointer to the form package data.\r
+ @param PackageLength Length of the package.\r
+ @param ConfigHdr Request string ConfigHdr. If it is NULL,\r
+ the first found varstore will be as ConfigHdr.\r
+ @param RequestBlockArray The block array is retrieved from the request string.\r
+ @param VarStorageData VarStorage structure contains the got block and default value.\r
+ @param DefaultIdArray Point to the got default id and default name array.\r
+\r
+ @retval EFI_SUCCESS The block array and the default value array are got.\r
+ @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages\r
+ are conflicted.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ParseIfrData (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN UINT8 *Package,\r
+ IN UINT32 PackageLength,\r
+ IN EFI_STRING ConfigHdr,\r
+ IN IFR_BLOCK_DATA *RequestBlockArray,\r
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,\r
+ OUT IFR_DEFAULT_DATA *DefaultIdArray\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN IfrOffset;\r
+ UINTN PackageOffset;\r
+ EFI_IFR_VARSTORE *IfrVarStore;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;\r
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStoreTmp;\r
+ EFI_IFR_OP_HEADER *IfrOpHdr;\r
+ EFI_IFR_ONE_OF *IfrOneOf;\r
+ EFI_IFR_REF4 *IfrRef;\r
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;\r
+ EFI_IFR_DEFAULT *IfrDefault;\r
+ EFI_IFR_ORDERED_LIST *IfrOrderedList;\r
+ EFI_IFR_CHECKBOX *IfrCheckBox;\r
+ EFI_IFR_PASSWORD *IfrPassword;\r
+ EFI_IFR_STRING *IfrString;\r
+ EFI_IFR_DATE *IfrDate;\r
+ EFI_IFR_TIME *IfrTime;\r
+ IFR_DEFAULT_DATA DefaultData;\r
+ IFR_DEFAULT_DATA *DefaultDataPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ CHAR16 *VarStoreName;\r
+ UINTN NameSize;\r
+ UINTN NvDefaultStoreSize;\r
+ UINT16 VarWidth;\r
+ UINT16 VarDefaultId;\r
+ BOOLEAN FirstOneOfOption;\r
+ BOOLEAN FirstOrderedList;\r
+ LIST_ENTRY *LinkData;\r
+ LIST_ENTRY *LinkDefault;\r
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;\r
+ EFI_HII_PACKAGE_HEADER *PackageHeader;\r
+ EFI_VARSTORE_ID VarStoreId;\r
+ UINT16 SmallestDefaultId;\r
+ BOOLEAN SmallestIdFromFlag;\r
+ BOOLEAN FromOtherDefaultOpcode;\r
+ BOOLEAN QuestionReferBitField;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BlockData = NULL;\r
+ DefaultDataPtr = NULL;\r
+ FirstOneOfOption = FALSE;\r
+ VarStoreId = 0;\r
+ FirstOrderedList = FALSE;\r
+ VarStoreName = NULL;\r
+ ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));\r
+ SmallestDefaultId = 0xFFFF;\r
+ FromOtherDefaultOpcode = FALSE;\r
+ QuestionReferBitField = FALSE;\r
+ IfrEfiVarStoreTmp = NULL;\r
+\r
+ //\r
+ // Go through the form package to parse OpCode one by one.\r
+ //\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;\r
+ IfrOffset = PackageOffset;\r
+ while (IfrOffset < PackageLength) {\r
+ //\r
+ // More than one form package found.\r
+ //\r
+ if (PackageOffset >= PackageHeader->Length) {\r
+ //\r
+ // Already found varstore for this request, break;\r
+ //\r
+ if (VarStoreId != 0) {\r
+ VarStoreId = 0;\r
+ }\r
+\r
+ //\r
+ // Get next package header info.\r
+ //\r
+ IfrOffset += sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *)(Package + IfrOffset);\r
+ }\r
+\r
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)(Package + IfrOffset);\r
+ switch (IfrOpHdr->OpCode) {\r
+ case EFI_IFR_VARSTORE_OP:\r
+ //\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStoreId != 0) {\r
+ break;\r
+ }\r
+\r
+ IfrVarStore = (EFI_IFR_VARSTORE *)IfrOpHdr;\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);\r
+\r
+ if (IsThisVarstore ((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {\r
+ //\r
+ // Find the matched VarStore\r
+ //\r
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrVarStore->Guid);\r
+ VarStorageData->Size = IfrVarStore->Size;\r
+ VarStorageData->Name = VarStoreName;\r
+ VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;\r
+ VarStoreId = IfrVarStore->VarStoreId;\r
+ } else {\r
+ FreePool (VarStoreName);\r
+ VarStoreName = NULL;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_EFI_OP:\r
+ //\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStoreId != 0) {\r
+ break;\r
+ }\r
+\r
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;\r
+\r
+ //\r
+ // If the length is small than the structure, this is from old efi\r
+ // varstore definition. Old efi varstore get config directly from\r
+ // GetVariable function.\r
+ //\r
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+ break;\r
+ }\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);\r
+ if (IfrEfiVarStoreTmp != NULL) {\r
+ FreePool (IfrEfiVarStoreTmp);\r
+ }\r
+\r
+ IfrEfiVarStoreTmp = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));\r
+ if (IfrEfiVarStoreTmp == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ CopyMem (IfrEfiVarStoreTmp, IfrEfiVarStore, IfrEfiVarStore->Header.Length);\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(IfrEfiVarStoreTmp->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));\r
+\r
+ if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {\r
+ //\r
+ // Find the matched VarStore\r
+ //\r
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrEfiVarStore->Guid);\r
+ VarStorageData->Size = IfrEfiVarStore->Size;\r
+ VarStorageData->Name = VarStoreName;\r
+ VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;\r
+ VarStoreId = IfrEfiVarStore->VarStoreId;\r
+ } else {\r
+ FreePool (VarStoreName);\r
+ VarStoreName = NULL;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+ //\r
+ // VarStore is found. Don't need to search any more.\r
+ //\r
+ if (VarStoreId != 0) {\r
+ break;\r
+ }\r
+\r
+ IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *)IfrOpHdr;\r
+\r
+ if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {\r
+ //\r
+ // Find the matched VarStore\r
+ //\r
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *)(VOID *)&IfrNameValueVarStore->Guid);\r
+ VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
+ VarStoreId = IfrNameValueVarStore->VarStoreId;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_DEFAULTSTORE_OP:\r
+ //\r
+ // Add new the map between default id and default name.\r
+ //\r
+ DefaultDataPtr = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultDataPtr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ DefaultDataPtr->DefaultId = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;\r
+ InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);\r
+ DefaultDataPtr = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ case EFI_IFR_FORM_MAP_OP:\r
+ //\r
+ // No matched varstore is found and directly return.\r
+ //\r
+ if ( VarStoreId == 0) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_REF_OP:\r
+ //\r
+ // Ref question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if ( VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrRef = (EFI_IFR_REF4 *)IfrOpHdr;\r
+ if (IfrRef->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ VarWidth = (UINT16)(sizeof (EFI_HII_REF));\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Numeric and OneOf has the same opcode structure.\r
+ //\r
+\r
+ //\r
+ // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrOneOf = (EFI_IFR_ONE_OF *)IfrOpHdr;\r
+ if (IfrOneOf->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ if (QuestionReferBitField) {\r
+ VarWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+ } else {\r
+ VarWidth = (UINT16)(1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+ }\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // when go to there,BlockData can't be NULLL.\r
+ //\r
+ ASSERT (BlockData != NULL);\r
+\r
+ if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {\r
+ //\r
+ // Set this flag to TRUE for the first oneof option.\r
+ //\r
+ FirstOneOfOption = TRUE;\r
+ } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
+ //\r
+ // Numeric minimum value will be used as default value when no default is specified.\r
+ //\r
+ DefaultData.Type = DefaultValueFromDefault;\r
+ if (QuestionReferBitField) {\r
+ //\r
+ // Since default value in bit field was stored as UINT32 type.\r
+ //\r
+ CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
+ } else {\r
+ switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set default value base on the DefaultId list get from IFR data.\r
+ //\r
+ NvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ if (NvDefaultStoreSize > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {\r
+ FindQuestionDefaultSetting (DefaultData.DefaultId, IfrEfiVarStoreTmp, &(IfrOneOf->Question), &DefaultData.Value, VarWidth, QuestionReferBitField);\r
+ }\r
+\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // offset by question header\r
+ // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type\r
+ //\r
+\r
+ FirstOrderedList = TRUE;\r
+ //\r
+ // OrderedList question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrOrderedList = (EFI_IFR_ORDERED_LIST *)IfrOpHdr;\r
+ if (IfrOrderedList->Question.VarStoreId != VarStoreId) {\r
+ BlockData = NULL;\r
+ break;\r
+ }\r
+\r
+ VarWidth = IfrOrderedList->MaxContainers;\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ //\r
+ // EFI_IFR_DEFAULT_OP\r
+ // offset by question header\r
+ // width is 1 sizeof (BOOLEAN)\r
+ // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.\r
+ // value by DefaultOption\r
+ // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.\r
+ //\r
+\r
+ //\r
+ // CheckBox question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;\r
+ if (IfrCheckBox->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ VarWidth = (UINT16)sizeof (BOOLEAN);\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ if (QuestionReferBitField) {\r
+ VarWidth = 1;\r
+ }\r
+\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, QuestionReferBitField);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // when go to there,BlockData can't be NULLL.\r
+ //\r
+ ASSERT (BlockData != NULL);\r
+\r
+ SmallestIdFromFlag = FALSE;\r
+\r
+ //\r
+ // Add default value for standard ID by CheckBox Flag\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.DefaultId = VarDefaultId;\r
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {\r
+ //\r
+ // When flag is set, default value is TRUE.\r
+ //\r
+ DefaultData.Type = DefaultValueFromFlag;\r
+ if (QuestionReferBitField) {\r
+ DefaultData.Value.u32 = TRUE;\r
+ } else {\r
+ DefaultData.Value.b = TRUE;\r
+ }\r
+\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+\r
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ //\r
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
+ //\r
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ SmallestIdFromFlag = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Add default value for Manufacture ID by CheckBox Flag\r
+ //\r
+ VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.DefaultId = VarDefaultId;\r
+ if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {\r
+ //\r
+ // When flag is set, default value is TRUE.\r
+ //\r
+ DefaultData.Type = DefaultValueFromFlag;\r
+ if (QuestionReferBitField) {\r
+ DefaultData.Value.u32 = TRUE;\r
+ } else {\r
+ DefaultData.Value.b = TRUE;\r
+ }\r
+\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+\r
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
+ //\r
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ SmallestIdFromFlag = TRUE;\r
+ }\r
+ }\r
+\r
+ if (SmallestIdFromFlag) {\r
+ //\r
+ // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.\r
+ //\r
+ DefaultData.Type = DefaultValueFromOtherDefault;\r
+ if (QuestionReferBitField) {\r
+ DefaultData.Value.u32 = TRUE;\r
+ } else {\r
+ DefaultData.Value.b = TRUE;\r
+ }\r
+\r
+ //\r
+ // Set default value for all the default id in the DefaultId list.\r
+ //\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ } else {\r
+ //\r
+ // When flag is not set, default value is FASLE.\r
+ //\r
+ DefaultData.Type = DefaultValueFromDefault;\r
+ if (QuestionReferBitField) {\r
+ DefaultData.Value.u32 = FALSE;\r
+ } else {\r
+ DefaultData.Value.b = FALSE;\r
+ }\r
+\r
+ //\r
+ // Set default value for all the default id in the DefaultId list.\r
+ //\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_DATE_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // Date question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrDate = (EFI_IFR_DATE *)IfrOpHdr;\r
+ if (IfrDate->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ VarWidth = (UINT16)sizeof (EFI_HII_DATE);\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_TIME_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // Time question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrTime = (EFI_IFR_TIME *)IfrOpHdr;\r
+ if (IfrTime->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ VarWidth = (UINT16)sizeof (EFI_HII_TIME);\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // String question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrString = (EFI_IFR_STRING *)IfrOpHdr;\r
+ if (IfrString->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ VarWidth = (UINT16)(IfrString->MaxSize * sizeof (UINT16));\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_PASSWORD_OP:\r
+ //\r
+ // offset by question header\r
+ // width MaxSize * sizeof (CHAR16)\r
+ // no default value, only block array\r
+ //\r
+\r
+ //\r
+ // Password question is not in IFR Form. This IFR form is not valid.\r
+ //\r
+ if (VarStoreId == 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether this question is for the requested varstore.\r
+ //\r
+ IfrPassword = (EFI_IFR_PASSWORD *)IfrOpHdr;\r
+ if (IfrPassword->Question.VarStoreId != VarStoreId) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The BlockData may allocate by other opcode,need to clean.\r
+ //\r
+ if (BlockData != NULL) {\r
+ BlockData = NULL;\r
+ }\r
+\r
+ VarWidth = (UINT16)(IfrPassword->MaxSize * sizeof (UINT16));\r
+ Status = IsThisOpcodeRequired (RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The opcode is not required,exit and parse other opcode.\r
+ //\r
+ break;\r
+ }\r
+\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // No default value for string.\r
+ //\r
+ BlockData = NULL;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OPTION_OP:\r
+ //\r
+ // No matched block data is ignored.\r
+ //\r
+ if ((BlockData == NULL) || (BlockData->Scope == 0)) {\r
+ break;\r
+ }\r
+\r
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;\r
+ if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
+ if (!FirstOrderedList) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get ordered list option data type.\r
+ //\r
+ if ((IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN)) {\r
+ VarWidth = 1;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {\r
+ VarWidth = 2;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {\r
+ VarWidth = 4;\r
+ } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ VarWidth = 8;\r
+ } else {\r
+ //\r
+ // Invalid ordered list option data type.\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+\r
+ FreePool (BlockData);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Calculate Ordered list QuestionId width.\r
+ //\r
+ BlockData->Width = (UINT16)(BlockData->Width * VarWidth);\r
+ //\r
+ // Check whether this question is in requested block array.\r
+ //\r
+ if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {\r
+ //\r
+ // This question is not in the requested string. Skip it.\r
+ //\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+\r
+ FreePool (BlockData);\r
+ BlockData = NULL;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Check this var question is in the var storage\r
+ //\r
+ if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ FreePool (BlockData);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Add Block Data into VarStorageData BlockEntry\r
+ //\r
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);\r
+\r
+ FirstOrderedList = FALSE;\r
+\r
+ break;\r
+ }\r
+\r
+ //\r
+ // 1. Set default value for OneOf option when flag field has default attribute.\r
+ // And set the default value with the smallest default id for other default id in the DefaultId list.\r
+ //\r
+ if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||\r
+ ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG))\r
+ {\r
+ //\r
+ // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.\r
+ // The first oneof option value will be used as default value when no default value is specified.\r
+ //\r
+ FirstOneOfOption = FALSE;\r
+\r
+ SmallestIdFromFlag = FALSE;\r
+\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.Type = DefaultValueFromFlag;\r
+ CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {\r
+ DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ //\r
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
+ //\r
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ SmallestIdFromFlag = TRUE;\r
+ }\r
+ }\r
+\r
+ if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {\r
+ DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Record the SmallestDefaultId and update the SmallestIdFromFlag.\r
+ //\r
+ SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;\r
+ SmallestIdFromFlag = TRUE;\r
+ }\r
+ }\r
+\r
+ if (SmallestIdFromFlag) {\r
+ //\r
+ // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.\r
+ //\r
+ DefaultData.Type = DefaultValueFromOtherDefault;\r
+ //\r
+ // Set default value for other default id in the DefaultId list.\r
+ //\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // 2. Set as the default value when this is the first option.\r
+ // The first oneof option value will be used as default value when no default value is specified.\r
+ //\r
+ if (FirstOneOfOption) {\r
+ // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.\r
+ FirstOneOfOption = FALSE;\r
+\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.Type = DefaultValueFromDefault;\r
+ CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_DEFAULT_OP:\r
+ //\r
+ // Update Current BlockData to the default value.\r
+ //\r
+ if ((BlockData == NULL) || (BlockData->Scope == 0)) {\r
+ //\r
+ // No matched block data is ignored.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the DefaultId\r
+ //\r
+ IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;\r
+ VarDefaultId = IfrDefault->DefaultId;\r
+ //\r
+ // Prepare new DefaultValue\r
+ //\r
+ DefaultData.Type = DefaultValueFromOpcode;\r
+ DefaultData.DefaultId = VarDefaultId;\r
+ if (QuestionReferBitField) {\r
+ CopyMem (&DefaultData.Value.u32, &IfrDefault->Value.u32, sizeof (UINT32));\r
+ } else {\r
+ CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));\r
+ }\r
+\r
+ // If the value field is expression, set the cleaned flag.\r
+ if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {\r
+ DefaultData.Cleaned = TRUE;\r
+ }\r
+\r
+ //\r
+ // Add DefaultValue into current BlockData\r
+ //\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+\r
+ //\r
+ // Set default value for other default id in the DefaultId list.\r
+ // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.\r
+ // If the two defaults are both from default opcode, use the first default as the default value of other default Id.\r
+ // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.\r
+ //\r
+ if ((SmallestDefaultId > VarDefaultId) || ((SmallestDefaultId == VarDefaultId) && !FromOtherDefaultOpcode)) {\r
+ FromOtherDefaultOpcode = TRUE;\r
+ SmallestDefaultId = VarDefaultId;\r
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {\r
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultDataPtr->DefaultId != DefaultData.DefaultId) {\r
+ DefaultData.Type = DefaultValueFromOtherDefault;\r
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;\r
+ InsertDefaultValue (BlockData, &DefaultData);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // After insert the default value, reset the cleaned value for next\r
+ // time used. If not set here, need to set the value before every time.\r
+ // use it.\r
+ //\r
+ DefaultData.Cleaned = FALSE;\r
+ break;\r
+\r
+ case EFI_IFR_END_OP:\r
+ //\r
+ // End Opcode is for Var question.\r
+ //\r
+ QuestionReferBitField = FALSE;\r
+ if (BlockData != NULL) {\r
+ if (BlockData->Scope > 0) {\r
+ BlockData->Scope--;\r
+ }\r
+\r
+ if (BlockData->Scope == 0) {\r
+ BlockData = NULL;\r
+ //\r
+ // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.\r
+ //\r
+ SmallestDefaultId = 0xFFFF;\r
+ FromOtherDefaultOpcode = FALSE;\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case EFI_IFR_GUID_OP:\r
+ if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+ QuestionReferBitField = TRUE;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ if (BlockData != NULL) {\r
+ if (BlockData->Scope > 0) {\r
+ BlockData->Scope = (UINT8)(BlockData->Scope + IfrOpHdr->Scope);\r
+ }\r
+\r
+ if (BlockData->Scope == 0) {\r
+ BlockData = NULL;\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ IfrOffset += IfrOpHdr->Length;\r
+ PackageOffset += IfrOpHdr->Length;\r
+ }\r
+\r
+ //\r
+ // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,\r
+ // so set the Status to EFI_SUCCESS.\r
+ //\r
+ if (Status == EFI_NOT_FOUND) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+Done:\r
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
+ for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {\r
+ DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ LinkDefault = LinkDefault->ForwardLink;\r
+ if (DefaultDataPtr->Cleaned == TRUE) {\r
+ RemoveEntryList (&DefaultDataPtr->Entry);\r
+ FreePool (DefaultDataPtr);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (IfrEfiVarStoreTmp != NULL) {\r
+ FreePool (IfrEfiVarStoreTmp);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ parse the configrequest string, get the elements.\r
+\r
+ @param ConfigRequest The input configrequest string.\r
+ @param Progress Return the progress data.\r
+\r
+ @retval Block data pointer.\r
+**/\r
+IFR_BLOCK_DATA *\r
+GetBlockElement (\r
+ IN EFI_STRING ConfigRequest,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ EFI_STATUS Status;\r
+ UINT8 *TmpBuffer;\r
+ UINT16 Offset;\r
+ UINT16 Width;\r
+ LIST_ENTRY *Link;\r
+ IFR_BLOCK_DATA *NextBlockData;\r
+ UINTN Length;\r
+\r
+ TmpBuffer = NULL;\r
+\r
+ //\r
+ // Init RequestBlockArray\r
+ //\r
+ RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (RequestBlockArray == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ InitializeListHead (&RequestBlockArray->Entry);\r
+\r
+ //\r
+ // Get the request Block array from the request string\r
+ // Offset and Width\r
+ //\r
+\r
+ //\r
+ // Parse each <RequestElement> if exists\r
+ // Only <BlockName> format is supported by this help function.\r
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
+ //\r
+ StringPtr = ConfigRequest;\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
+ //\r
+ // Skip the OFFSET string\r
+ //\r
+ *Progress = StringPtr;\r
+ StringPtr += StrLen (L"&OFFSET=");\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Offset = 0;\r
+ CopyMem (\r
+ &Offset,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+ );\r
+ FreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+ goto Done;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&WIDTH=");\r
+\r
+ //\r
+ // Get Width\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Width = 0;\r
+ CopyMem (\r
+ &Width,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+ );\r
+ FreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ BlockData->Offset = Offset;\r
+ BlockData->Width = Width;\r
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
+\r
+ //\r
+ // Skip &VALUE string if &VALUE does exists.\r
+ //\r
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {\r
+ StringPtr += StrLen (L"&VALUE=");\r
+\r
+ //\r
+ // Get Value\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ FreePool (TmpBuffer);\r
+ StringPtr += Length;\r
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If '\0', parsing is finished.\r
+ //\r
+ if (*StringPtr == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Merge the requested block data.\r
+ //\r
+ Link = RequestBlockArray->Entry.ForwardLink;\r
+ while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
+ if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
+ BlockData->Width = (UINT16)(NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);\r
+ }\r
+\r
+ RemoveEntryList (Link->ForwardLink);\r
+ FreePool (NextBlockData);\r
+ continue;\r
+ }\r
+\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ return RequestBlockArray;\r
+\r
+Done:\r
+ if (RequestBlockArray != NULL) {\r
+ //\r
+ // Free Link Array RequestBlockArray\r
+ //\r
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ FreePool (RequestBlockArray);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ parse the configrequest string, get the elements.\r
+\r
+ @param ConfigRequest The input config request string.\r
+ @param Progress Return the progress data.\r
+\r
+ @retval return data block array.\r
+**/\r
+IFR_BLOCK_DATA *\r
+GetNameElement (\r
+ IN EFI_STRING ConfigRequest,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING NextTag;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ BOOLEAN HasValue;\r
+\r
+ StringPtr = ConfigRequest;\r
+\r
+ //\r
+ // Init RequestBlockArray\r
+ //\r
+ RequestBlockArray = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (RequestBlockArray == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ InitializeListHead (&RequestBlockArray->Entry);\r
+\r
+ //\r
+ // Get the request Block array from the request string\r
+ //\r
+\r
+ //\r
+ // Parse each <RequestElement> if exists\r
+ // Only <BlockName> format is supported by this help function.\r
+ // <BlockName> ::= &'Name***=***\r
+ //\r
+ while (StringPtr != NULL && *StringPtr == L'&') {\r
+ *Progress = StringPtr;\r
+ //\r
+ // Skip the L"&" string\r
+ //\r
+ StringPtr += 1;\r
+\r
+ HasValue = FALSE;\r
+ if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {\r
+ *NextTag = L'\0';\r
+ HasValue = TRUE;\r
+ } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {\r
+ *NextTag = L'\0';\r
+ }\r
+\r
+ //\r
+ // Set Block Data\r
+ //\r
+ BlockData = (IFR_BLOCK_DATA *)AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+ if (BlockData == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get Name\r
+ //\r
+ BlockData->Name = AllocateCopyPool (StrSize (StringPtr), StringPtr);\r
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);\r
+\r
+ if (HasValue) {\r
+ //\r
+ // If has value, skip the value.\r
+ //\r
+ StringPtr = NextTag + 1;\r
+ *NextTag = L'=';\r
+ StringPtr = StrStr (StringPtr, L"&");\r
+ } else if (NextTag != NULL) {\r
+ //\r
+ // restore the '&' text.\r
+ //\r
+ StringPtr = NextTag;\r
+ *NextTag = L'&';\r
+ }\r
+ }\r
+\r
+ return RequestBlockArray;\r
+\r
+Done:\r
+ if (RequestBlockArray != NULL) {\r
+ //\r
+ // Free Link Array RequestBlockArray\r
+ //\r
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ FreePool (RequestBlockArray);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Generate ConfigRequest string base on the varstore info.\r
+\r
+ @param ConfigHdr The config header for this varstore.\r
+ @param VarStorageData The varstore info.\r
+ @param Status Return Status.\r
+ @param ConfigRequest The ConfigRequest info may be return.\r
+\r
+ @retval TRUE Need to continue\r
+ @retval Others NO need to continue or error occur.\r
+**/\r
+BOOLEAN\r
+GenerateConfigRequest (\r
+ IN CHAR16 *ConfigHdr,\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ OUT EFI_STATUS *Status,\r
+ IN OUT EFI_STRING *ConfigRequest\r
+ )\r
+{\r
+ BOOLEAN DataExist;\r
+ UINTN Length;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *FullConfigRequest;\r
+ CHAR16 *StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+\r
+ //\r
+ // Append VarStorageData BlockEntry into *Request string\r
+ // Now support only one varstore in a form package.\r
+ //\r
+\r
+ //\r
+ // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package\r
+ // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig\r
+ //\r
+\r
+ //\r
+ // Compute the length of the entire request starting with <ConfigHdr> and a\r
+ // Null-terminator\r
+ //\r
+ DataExist = FALSE;\r
+ Length = StrLen (ConfigHdr) + 1;\r
+\r
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
+ DataExist = TRUE;\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Add <BlockName> length for each Name\r
+ //\r
+ // <BlockName> ::= &Name1&Name2&...\r
+ // |1| StrLen(Name1)\r
+ //\r
+ Length = Length + (1 + StrLen (BlockData->Name));\r
+ } else {\r
+ //\r
+ // Add <BlockName> length for each Offset/Width pair\r
+ //\r
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
+ // | 8 | 4 | 7 | 4 |\r
+ //\r
+ Length = Length + (8 + 4 + 7 + 4);\r
+ }\r
+ }\r
+\r
+ //\r
+ // No any request block data is found. The request string can't be constructed.\r
+ //\r
+ if (!DataExist) {\r
+ *Status = EFI_SUCCESS;\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the entire <ConfigRequest>\r
+ //\r
+ FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (FullConfigRequest == NULL) {\r
+ *Status = EFI_OUT_OF_RESOURCES;\r
+ return FALSE;\r
+ }\r
+\r
+ StringPtr = FullConfigRequest;\r
+\r
+ //\r
+ // Start with <ConfigHdr>\r
+ //\r
+ StrCpyS (StringPtr, Length, ConfigHdr);\r
+ StringPtr += StrLen (StringPtr);\r
+\r
+ //\r
+ // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
+ //\r
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Append &Name1\0\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),\r
+ L"&%s",\r
+ BlockData->Name\r
+ );\r
+ } else {\r
+ //\r
+ // Append &OFFSET=XXXX&WIDTH=YYYY\0\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),\r
+ L"&OFFSET=%04X&WIDTH=%04X",\r
+ BlockData->Offset,\r
+ BlockData->Width\r
+ );\r
+ }\r
+\r
+ StringPtr += StrLen (StringPtr);\r
+ }\r
+\r
+ //\r
+ // Set to the got full request string.\r
+ //\r
+ HiiToLower (FullConfigRequest);\r
+\r
+ if (*ConfigRequest != NULL) {\r
+ FreePool (*ConfigRequest);\r
+ }\r
+\r
+ *ConfigRequest = FullConfigRequest;\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Generate ConfigRequest Header base on the varstore info.\r
+\r
+ @param VarStorageData The varstore info.\r
+ @param DevicePath Device path for this varstore.\r
+ @param ConfigHdr The config header for this varstore.\r
+\r
+ @retval EFI_SUCCESS Generate the header success.\r
+ @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.\r
+**/\r
+EFI_STATUS\r
+GenerateHdr (\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT EFI_STRING *ConfigHdr\r
+ )\r
+{\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING PathStr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ NameStr = NULL;\r
+ GuidStr = NULL;\r
+ PathStr = NULL;\r
+\r
+ //\r
+ // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle\r
+ //\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)&VarStorageData->Guid, 1, &GuidStr);\r
+ if (VarStorageData->Name != NULL) {\r
+ GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *)VarStorageData->Name, 2, &NameStr);\r
+ } else {\r
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
+ }\r
+\r
+ GenerateSubStr (\r
+ L"PATH=",\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),\r
+ (VOID *)DevicePath,\r
+ 1,\r
+ &PathStr\r
+ );\r
+ Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;\r
+ if (VarStorageData->Name == NULL) {\r
+ Length += 1;\r
+ }\r
+\r
+ *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (*ConfigHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ StrCpyS (*ConfigHdr, Length, GuidStr);\r
+ StrCatS (*ConfigHdr, Length, NameStr);\r
+ if (VarStorageData->Name == NULL) {\r
+ StrCatS (*ConfigHdr, Length, L"&");\r
+ }\r
+\r
+ StrCatS (*ConfigHdr, Length, PathStr);\r
+\r
+ //\r
+ // Remove the last character L'&'\r
+ //\r
+ *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';\r
+\r
+Done:\r
+ if (GuidStr != NULL) {\r
+ FreePool (GuidStr);\r
+ }\r
+\r
+ if (NameStr != NULL) {\r
+ FreePool (NameStr);\r
+ }\r
+\r
+ if (PathStr != NULL) {\r
+ FreePool (PathStr);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Update the default value in the block data which is used as bit var store.\r
+\r
+ For example:\r
+ A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.\r
+ And corresponding block data info: offset==0; width==1;currently the default value\r
+ is saved as 1.Actually the default value 1 need to be set to bit field 1, so the\r
+ default value of this block data shuold be:2.\r
+\r
+ typedef struct {\r
+ UINT8 Bit1 : 1; //\r
+ UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.\r
+ // (default value record for the bit field)\r
+ ......\r
+ }ExampleData;\r
+\r
+ After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.\r
+ (default value record for the Block)\r
+\r
+ UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.\r
+\r
+ @param BlockLink The Link of the block data.\r
+\r
+**/\r
+VOID\r
+UpdateDefaultValue (\r
+ IN LIST_ENTRY *BlockLink\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *ListEntry;\r
+ LIST_ENTRY *LinkDefault;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_DEFAULT_DATA *DefaultValueData;\r
+ UINTN StartBit;\r
+ UINTN EndBit;\r
+ UINT32 BitFieldDefaultValue;\r
+\r
+ for ( Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (!BlockData->IsBitVar) {\r
+ continue;\r
+ }\r
+\r
+ ListEntry = &BlockData->DefaultValueEntry;\r
+ //\r
+ // Update the default value in the block data with all existing default id.\r
+ //\r
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ //\r
+ // Get the default data, and the value of the default data is for some field in the block.\r
+ // Note: Default value for bit field question is stored as UINT32.\r
+ //\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ BitFieldDefaultValue = DefaultValueData->Value.u32;\r
+\r
+ StartBit = BlockData->BitOffset % 8;\r
+ EndBit = StartBit + BlockData->BitWidth - 1;\r
+\r
+ //\r
+ // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.\r
+ //\r
+ DefaultValueData->Value.u32 = BitFieldWrite32 (0, StartBit, EndBit, BitFieldDefaultValue);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+Merge the default value in two block datas which have overlap region.\r
+\r
+For bit fields, their related block data may have overlap region, such as:\r
+\r
+typedef struct {\r
+ UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1\r
+ UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5\r
+ // (default value record for the bit field)\r
+ ......\r
+}ExampleData;\r
+\r
+After function UpdateDefaultValue:\r
+Block1: offset = 0; width = 1;(byte level) default = 1\r
+Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))\r
+(default value record for block)\r
+\r
+After function MergeBlockDefaultValue:\r
+Block1: offset = 0; width = 1;(byte level) default = 65\r
+Block2: offset = 0; width = 2;(byte level) default = 321\r
+(Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)\r
+\r
+Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains\r
+value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).\r
+\r
+This fuction merge the default value of these two blocks, and make the default value of block1\r
+also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also\r
+contain the default value of Bit1.\r
+\r
+We can get the total value of the whole block that just cover these two blocks(in this case is:\r
+block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is\r
+the first byte value of block.\r
+\r
+@param FirstBlock Point to the block date whose default value need to be merged.\r
+@param SecondBlock Point to the block date whose default value need to be merged.\r
+\r
+**/\r
+VOID\r
+MergeBlockDefaultValue (\r
+ IN OUT IFR_BLOCK_DATA *FirstBlock,\r
+ IN OUT IFR_BLOCK_DATA *SecondBlock\r
+ )\r
+{\r
+ LIST_ENTRY *FirstListEntry;\r
+ LIST_ENTRY *SecondListEntry;\r
+ LIST_ENTRY *FirstDefaultLink;\r
+ LIST_ENTRY *SecondDefaultLink;\r
+ IFR_DEFAULT_DATA *FirstDefaultValueData;\r
+ IFR_DEFAULT_DATA *SecondDefaultValueData;\r
+ UINT32 *FirstDefaultValue;\r
+ UINT32 *SecondDefaultValue;\r
+ UINT64 TotalValue;\r
+ UINT64 ShiftedValue;\r
+ UINT16 OffsetShift;\r
+\r
+ FirstListEntry = &FirstBlock->DefaultValueEntry;\r
+ for (FirstDefaultLink = FirstListEntry->ForwardLink; FirstDefaultLink != FirstListEntry; FirstDefaultLink = FirstDefaultLink->ForwardLink) {\r
+ FirstDefaultValueData = BASE_CR (FirstDefaultLink, IFR_DEFAULT_DATA, Entry);\r
+ SecondListEntry = &SecondBlock->DefaultValueEntry;\r
+ for (SecondDefaultLink = SecondListEntry->ForwardLink; SecondDefaultLink != SecondListEntry; SecondDefaultLink = SecondDefaultLink->ForwardLink) {\r
+ SecondDefaultValueData = BASE_CR (SecondDefaultLink, IFR_DEFAULT_DATA, Entry);\r
+ if (FirstDefaultValueData->DefaultId != SecondDefaultValueData->DefaultId) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find default value with same default id in the two blocks.\r
+ // Note: Default value for bit field question is stored as UINT32 type.\r
+ //\r
+ FirstDefaultValue = &FirstDefaultValueData->Value.u32;\r
+ SecondDefaultValue = &SecondDefaultValueData->Value.u32;\r
+ //\r
+ // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.\r
+ // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based\r
+ // on the offset and width of FirstBlock and SecondBlock.\r
+ //\r
+ if (FirstBlock->Offset > SecondBlock->Offset) {\r
+ OffsetShift = FirstBlock->Offset - SecondBlock->Offset;\r
+ ShiftedValue = LShiftU64 ((UINT64)(*FirstDefaultValue), OffsetShift * 8);\r
+ TotalValue = ShiftedValue | (UINT64)(*SecondDefaultValue);\r
+ *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, SecondBlock->Width * 8 -1);\r
+ *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + FirstBlock->Width *8 -1);\r
+ } else {\r
+ OffsetShift = SecondBlock->Offset -FirstBlock->Offset;\r
+ ShiftedValue = LShiftU64 ((UINT64)(*SecondDefaultValue), OffsetShift * 8);\r
+ TotalValue = ShiftedValue | (UINT64)(*FirstDefaultValue);\r
+ *FirstDefaultValue = (UINT32)BitFieldRead64 (TotalValue, 0, FirstBlock->Width * 8 -1);\r
+ *SecondDefaultValue = (UINT32)BitFieldRead64 (TotalValue, OffsetShift * 8, OffsetShift * 8 + SecondBlock->Width *8 -1);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+\r
+Update the default value in the block data which used as Bit VarStore\r
+\r
+@param BlockLink The Link of the block data.\r
+\r
+**/\r
+VOID\r
+UpdateBlockDataArray (\r
+ IN LIST_ENTRY *BlockLink\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *TempLink;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_BLOCK_DATA *NextBlockData;\r
+\r
+ //\r
+ // 1. Update default value in BitVar block data.\r
+ // Sine some block datas are used as BitVarStore, then the default value recored in the block\r
+ // is for related bit field in the block. so we need to set the default value to the related bit\r
+ // fields in the block data if the block data is used as bit varstore, then the default value of\r
+ // the block will be updated.\r
+ //\r
+ UpdateDefaultValue (BlockLink);\r
+\r
+ //\r
+ // 2.Update default value for overlap BitVar blcok datas.\r
+ // For block datas have overlap region, we need to merge the default value in different blocks.\r
+ //\r
+ for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {\r
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+ if (!BlockData->IsBitVar) {\r
+ continue;\r
+ }\r
+\r
+ for (TempLink = Link->ForwardLink; TempLink != BlockLink; TempLink = TempLink->ForwardLink) {\r
+ NextBlockData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);\r
+ if (!NextBlockData->IsBitVar || (NextBlockData->Offset >= BlockData->Offset + BlockData->Width) || (BlockData->Offset >= NextBlockData->Offset + NextBlockData->Width)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.\r
+ //\r
+ MergeBlockDefaultValue (BlockData, NextBlockData);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Generate ConfigAltResp string base on the varstore info.\r
+\r
+ @param HiiHandle Hii Handle for this hii package.\r
+ @param ConfigHdr The config header for this varstore.\r
+ @param VarStorageData The varstore info.\r
+ @param DefaultIdArray The Default id array.\r
+ @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.\r
+\r
+ @retval TRUE Need to continue\r
+ @retval Others NO need to continue or error occur.\r
+**/\r
+EFI_STATUS\r
+GenerateAltConfigResp (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN CHAR16 *ConfigHdr,\r
+ IN IFR_VARSTORAGE_DATA *VarStorageData,\r
+ IN IFR_DEFAULT_DATA *DefaultIdArray,\r
+ IN OUT EFI_STRING *DefaultAltCfgResp\r
+ )\r
+{\r
+ BOOLEAN DataExist;\r
+ UINTN Length;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *LinkData;\r
+ LIST_ENTRY *LinkDefault;\r
+ LIST_ENTRY *ListEntry;\r
+ CHAR16 *StringPtr;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_DEFAULT_DATA *DefaultId;\r
+ IFR_DEFAULT_DATA *DefaultValueData;\r
+ UINTN Width;\r
+ UINT8 *TmpBuffer;\r
+ CHAR16 *DefaultString;\r
+ UINTN StrSize;\r
+\r
+ BlockData = NULL;\r
+ DataExist = FALSE;\r
+ DefaultString = NULL;\r
+ //\r
+ // Add length for <ConfigHdr> + '\0'\r
+ //\r
+ Length = StrLen (ConfigHdr) + 1;\r
+\r
+ UpdateBlockDataArray (&VarStorageData->BlockEntry);\r
+\r
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ //\r
+ // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 |\r
+ //\r
+ Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
+\r
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
+ ListEntry = &BlockData->DefaultValueEntry;\r
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
+ continue;\r
+ }\r
+\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Add length for "&Name1=zzzzzzzzzzzz"\r
+ // |1|Name|1|Value|\r
+ //\r
+ Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);\r
+ } else {\r
+ //\r
+ // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
+ // | 8 | 4 | 7 | 4 | 7 | Width * 2 |\r
+ //\r
+ Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);\r
+ }\r
+\r
+ DataExist = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // No default value is found. The default string doesn't exist.\r
+ //\r
+ if (!DataExist) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the entire <DefaultAltCfgResp>\r
+ //\r
+ *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (*DefaultAltCfgResp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StringPtr = *DefaultAltCfgResp;\r
+\r
+ //\r
+ // Start with <ConfigHdr>\r
+ //\r
+ StrCpyS (StringPtr, Length, ConfigHdr);\r
+ StringPtr += StrLen (StringPtr);\r
+\r
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {\r
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);\r
+ //\r
+ // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"\r
+ // |1| StrLen (ConfigHdr) | 8 | 4 |\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),\r
+ L"&%s&ALTCFG=%04X",\r
+ ConfigHdr,\r
+ DefaultId->DefaultId\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+\r
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {\r
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);\r
+ ListEntry = &BlockData->DefaultValueEntry;\r
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {\r
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);\r
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {\r
+ continue;\r
+ }\r
+\r
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),\r
+ L"&%s=",\r
+ BlockData->Name\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+ } else {\r
+ //\r
+ // Add <BlockConfig>\r
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+ //\r
+ UnicodeSPrint (\r
+ StringPtr,\r
+ (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),\r
+ L"&OFFSET=%04X&WIDTH=%04X&VALUE=",\r
+ BlockData->Offset,\r
+ BlockData->Width\r
+ );\r
+ StringPtr += StrLen (StringPtr);\r
+ }\r
+\r
+ Width = BlockData->Width;\r
+ //\r
+ // Convert Value to a hex string in "%x" format\r
+ // NOTE: This is in the opposite byte that GUID and PATH use\r
+ //\r
+ if (BlockData->OpCode == EFI_IFR_STRING_OP) {\r
+ DefaultString = InternalGetString (HiiHandle, DefaultValueData->Value.string);\r
+ TmpBuffer = AllocateZeroPool (Width);\r
+ ASSERT (TmpBuffer != NULL);\r
+ if (DefaultString != NULL) {\r
+ StrSize = StrLen (DefaultString)* sizeof (CHAR16);\r
+ if (StrSize > Width) {\r
+ StrSize = Width;\r
+ }\r
+\r
+ CopyMem (TmpBuffer, (UINT8 *)DefaultString, StrSize);\r
+ }\r
+ } else {\r
+ TmpBuffer = (UINT8 *)&(DefaultValueData->Value);\r
+ }\r
+\r
+ for ( ; Width > 0 && (TmpBuffer != NULL); Width--) {\r
+ UnicodeValueToStringS (\r
+ StringPtr,\r
+ Length * sizeof (CHAR16) - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ TmpBuffer[Width - 1],\r
+ 2\r
+ );\r
+ StringPtr += StrnLenS (StringPtr, Length - ((UINTN)StringPtr - (UINTN)*DefaultAltCfgResp) / sizeof (CHAR16));\r
+ }\r
+\r
+ if (DefaultString != NULL) {\r
+ FreePool (DefaultString);\r
+ DefaultString = NULL;\r
+ }\r
+\r
+ if ((BlockData->OpCode == EFI_IFR_STRING_OP) && (TmpBuffer != NULL)) {\r
+ FreePool (TmpBuffer);\r
+ TmpBuffer = NULL;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ HiiToLower (*DefaultAltCfgResp);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function gets the full request string and full default value string by\r
+ parsing IFR data in HII form packages.\r
+\r
+ When Request points to NULL string, the request string and default value string\r
+ for each varstore in form package will return.\r
+\r
+ @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.\r
+ @param DevicePath Device Path which Hii Config Access Protocol is registered.\r
+ @param Request Pointer to a null-terminated Unicode string in\r
+ <ConfigRequest> format. When it doesn't contain\r
+ any RequestElement, it will be updated to return\r
+ the full RequestElement retrieved from IFR data.\r
+ If it points to NULL, the request string for the first\r
+ varstore in form package will be merged into a\r
+ <MultiConfigRequest> format string and return.\r
+ @param AltCfgResp Pointer to a null-terminated Unicode string in\r
+ <ConfigAltResp> format. When the pointer is to NULL,\r
+ the full default value string retrieved from IFR data\r
+ will return. When the pinter is to a string, the\r
+ full default value string retrieved from IFR data\r
+ will be merged into the input string and return.\r
+ When Request points to NULL, the default value string\r
+ for each varstore in form package will be merged into\r
+ a <MultiConfigAltResp> format string and return.\r
+ @param PointerProgress Optional parameter, it can be NULL.\r
+ When it is not NULL, if Request is NULL, it returns NULL.\r
+ On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ & before the first failing name / value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name / value pair) if the request was\r
+ not successful.\r
+ @retval EFI_SUCCESS The Results string is set to the full request string.\r
+ And AltCfgResp contains all default value string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
+ @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string\r
+ can't be found in Form package.\r
+ @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.\r
+ @retval EFI_INVALID_PARAMETER Request points to NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetFullStringFromHiiFormPackages (\r
+ IN HII_DATABASE_RECORD *DataBaseRecord,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN OUT EFI_STRING *Request,\r
+ IN OUT EFI_STRING *AltCfgResp,\r
+ OUT EFI_STRING *PointerProgress OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *HiiFormPackage;\r
+ UINTN PackageSize;\r
+ IFR_BLOCK_DATA *RequestBlockArray;\r
+ IFR_BLOCK_DATA *BlockData;\r
+ IFR_DEFAULT_DATA *DefaultValueData;\r
+ IFR_DEFAULT_DATA *DefaultId;\r
+ IFR_DEFAULT_DATA *DefaultIdArray;\r
+ IFR_VARSTORAGE_DATA *VarStorageData;\r
+ EFI_STRING DefaultAltCfgResp;\r
+ EFI_STRING ConfigHdr;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING Progress;\r
+\r
+ if ((DataBaseRecord == NULL) || (DevicePath == NULL) || (Request == NULL) || (AltCfgResp == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the local variables.\r
+ //\r
+ RequestBlockArray = NULL;\r
+ DefaultIdArray = NULL;\r
+ VarStorageData = NULL;\r
+ DefaultAltCfgResp = NULL;\r
+ ConfigHdr = NULL;\r
+ HiiFormPackage = NULL;\r
+ PackageSize = 0;\r
+ Progress = *Request;\r
+\r
+ Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 1. Get the request block array by Request String when Request string contains the block array.\r
+ //\r
+ StringPtr = NULL;\r
+ if (*Request != NULL) {\r
+ StringPtr = *Request;\r
+ //\r
+ // Jump <ConfigHdr>\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ StringPtr += StrLen (L"GUID=");\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&NAME=");\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&PATH=");\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ //\r
+ // No request block is found.\r
+ //\r
+ StringPtr = NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If StringPtr != NULL, get the request elements.\r
+ //\r
+ if (StringPtr != NULL) {\r
+ if (StrStr (StringPtr, L"&OFFSET=") != NULL) {\r
+ RequestBlockArray = GetBlockElement (StringPtr, &Progress);\r
+ } else {\r
+ RequestBlockArray = GetNameElement (StringPtr, &Progress);\r
+ }\r
+\r
+ if (RequestBlockArray == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Initialize DefaultIdArray to store the map between DeaultId and DefaultName\r
+ //\r
+ DefaultIdArray = (IFR_DEFAULT_DATA *)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));\r
+ if (DefaultIdArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ InitializeListHead (&DefaultIdArray->Entry);\r
+\r
+ //\r
+ // Initialize VarStorageData to store the var store Block and Default value information.\r
+ //\r
+ VarStorageData = (IFR_VARSTORAGE_DATA *)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));\r
+ if (VarStorageData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ InitializeListHead (&VarStorageData->Entry);\r
+ InitializeListHead (&VarStorageData->BlockEntry);\r
+\r
+ //\r
+ // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.\r
+ //\r
+\r
+ //\r
+ // Parse the opcode in form package to get the default setting.\r
+ //\r
+ Status = ParseIfrData (\r
+ DataBaseRecord->Handle,\r
+ HiiFormPackage,\r
+ (UINT32)PackageSize,\r
+ *Request,\r
+ RequestBlockArray,\r
+ VarStorageData,\r
+ DefaultIdArray\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // No requested varstore in IFR data and directly return\r
+ //\r
+ if ((VarStorageData->Type == 0) && (VarStorageData->Name == NULL)) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.\r
+ //\r
+ Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (RequestBlockArray == NULL) {\r
+ if (!GenerateConfigRequest (ConfigHdr, VarStorageData, &Status, Request)) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // 4. Construct Default Value string in AltResp according to request element.\r
+ // Go through all VarStorageData Entry and get the DefaultId array for each one\r
+ // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody\r
+ //\r
+ Status = GenerateAltConfigResp (DataBaseRecord->Handle, ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.\r
+ //\r
+ if ((*AltCfgResp != NULL) && (DefaultAltCfgResp != NULL)) {\r
+ Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);\r
+ FreePool (DefaultAltCfgResp);\r
+ } else if (*AltCfgResp == NULL) {\r
+ *AltCfgResp = DefaultAltCfgResp;\r
+ }\r
+\r
+Done:\r
+ if (RequestBlockArray != NULL) {\r
+ //\r
+ // Free Link Array RequestBlockArray\r
+ //\r
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {\r
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ FreePool (RequestBlockArray);\r
+ }\r
+\r
+ if (VarStorageData != NULL) {\r
+ //\r
+ // Free link array VarStorageData\r
+ //\r
+ while (!IsListEmpty (&VarStorageData->BlockEntry)) {\r
+ BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+ RemoveEntryList (&BlockData->Entry);\r
+ if (BlockData->Name != NULL) {\r
+ FreePool (BlockData->Name);\r
+ }\r
+\r
+ //\r
+ // Free default value link array\r
+ //\r
+ while (!IsListEmpty (&BlockData->DefaultValueEntry)) {\r
+ DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
+ RemoveEntryList (&DefaultValueData->Entry);\r
+ FreePool (DefaultValueData);\r
+ }\r
+\r
+ FreePool (BlockData);\r
+ }\r
+\r
+ if (VarStorageData->Name != NULL) {\r
+ FreePool (VarStorageData->Name);\r
+ VarStorageData->Name = NULL;\r
+ }\r
+\r
+ FreePool (VarStorageData);\r
+ }\r
+\r
+ if (DefaultIdArray != NULL) {\r
+ //\r
+ // Free DefaultId Array\r
+ //\r
+ while (!IsListEmpty (&DefaultIdArray->Entry)) {\r
+ DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);\r
+ RemoveEntryList (&DefaultId->Entry);\r
+ FreePool (DefaultId);\r
+ }\r
+\r
+ FreePool (DefaultIdArray);\r
+ }\r
+\r
+ //\r
+ // Free the allocated string\r
+ //\r
+ if (ConfigHdr != NULL) {\r
+ FreePool (ConfigHdr);\r
+ }\r
+\r
+ //\r
+ // Free Package data\r
+ //\r
+ if (HiiFormPackage != NULL) {\r
+ FreePool (HiiFormPackage);\r
+ }\r
+\r
+ if (PointerProgress != NULL) {\r
+ if (*Request == NULL) {\r
+ *PointerProgress = NULL;\r
+ } else if (EFI_ERROR (Status)) {\r
+ *PointerProgress = *Request;\r
+ } else {\r
+ *PointerProgress = *Request + StrLen (*Request);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function gets the full request resp string by\r
+ parsing IFR data in HII form packages.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param EfiVarStoreInfo The efi varstore info which is save in the EFI\r
+ varstore data structure.\r
+ @param Request Pointer to a null-terminated Unicode string in\r
+ <ConfigRequest> format.\r
+ @param RequestResp Pointer to a null-terminated Unicode string in\r
+ <ConfigResp> format.\r
+ @param AccessProgress On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ & before the first failing name / value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name / value pair) if the request was\r
+ not successful.\r
+\r
+ @retval EFI_SUCCESS The Results string is set to the full request string.\r
+ And AltCfgResp contains all default value string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
+ @retval EFI_INVALID_PARAMETER Request points to NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+GetConfigRespFromEfiVarStore (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,\r
+ IN EFI_STRING Request,\r
+ OUT EFI_STRING *RequestResp,\r
+ OUT EFI_STRING *AccessProgress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING VarStoreName;\r
+ UINTN NameSize;\r
+ UINT8 *VarStore;\r
+ UINTN BufferSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BufferSize = 0;\r
+ VarStore = NULL;\r
+ VarStoreName = NULL;\r
+ *AccessProgress = Request;\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
+\r
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ goto Done;\r
+ }\r
+\r
+ VarStore = AllocateZeroPool (BufferSize);\r
+ ASSERT (VarStore != NULL);\r
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = HiiBlockToConfig (This, Request, VarStore, BufferSize, RequestResp, AccessProgress);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ if (VarStoreName != NULL) {\r
+ FreePool (VarStoreName);\r
+ }\r
+\r
+ if (VarStore != NULL) {\r
+ FreePool (VarStore);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function route the full request resp string for efi varstore.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param EfiVarStoreInfo The efi varstore info which is save in the EFI\r
+ varstore data structure.\r
+ @param RequestResp Pointer to a null-terminated Unicode string in\r
+ <ConfigResp> format.\r
+ @param Result Pointer to a null-terminated Unicode string in\r
+ <ConfigResp> format.\r
+\r
+ @retval EFI_SUCCESS The Results string is set to the full request string.\r
+ And AltCfgResp contains all default value string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.\r
+ @retval EFI_INVALID_PARAMETER Request points to NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+RouteConfigRespForEfiVarStore (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo,\r
+ IN EFI_STRING RequestResp,\r
+ OUT EFI_STRING *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING VarStoreName;\r
+ UINTN NameSize;\r
+ UINT8 *VarStore;\r
+ UINTN BufferSize;\r
+ UINTN BlockSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BufferSize = 0;\r
+ VarStore = NULL;\r
+ VarStoreName = NULL;\r
+ *Result = RequestResp;\r
+\r
+ NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);\r
+ VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));\r
+ if (VarStoreName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ AsciiStrToUnicodeStrS ((CHAR8 *)EfiVarStoreInfo->Name, VarStoreName, NameSize);\r
+\r
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ DEBUG ((DEBUG_ERROR, "The variable does not exist!"));\r
+ goto Done;\r
+ }\r
+\r
+ BlockSize = BufferSize;\r
+ VarStore = AllocateZeroPool (BufferSize);\r
+ ASSERT (VarStore != NULL);\r
+ Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = HiiConfigToBlock (This, RequestResp, VarStore, &BlockSize, Result);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);\r
+ if (EFI_ERROR (Status)) {\r
+ *Result = RequestResp;\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ if (VarStoreName != NULL) {\r
+ FreePool (VarStoreName);\r
+ }\r
+\r
+ if (VarStore != NULL) {\r
+ FreePool (VarStore);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Validate the config request elements.\r
+\r
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,\r
+ without configHdr field.\r
+\r
+ @retval CHAR16 * THE first Name/value pair not correct.\r
+ @retval NULL Success parse the name/value pair\r
+**/\r
+CHAR16 *\r
+OffsetWidthValidate (\r
+ CHAR16 *ConfigElements\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *RetVal;\r
+\r
+ StringPtr = ConfigElements;\r
+\r
+ while (1) {\r
+ RetVal = StringPtr;\r
+ if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
+ return RetVal;\r
+ }\r
+\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return RetVal;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&WIDTH=");\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Validate the config request elements.\r
+\r
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,\r
+ without configHdr field.\r
+\r
+ @retval CHAR16 * THE first Name/value pair not correct.\r
+ @retval NULL Success parse the name/value pair\r
+\r
+**/\r
+CHAR16 *\r
+NameValueValidate (\r
+ CHAR16 *ConfigElements\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *RetVal;\r
+\r
+ StringPtr = ConfigElements;\r
+\r
+ while (1) {\r
+ RetVal = StringPtr;\r
+ if (*StringPtr != L'&') {\r
+ return RetVal;\r
+ }\r
+\r
+ StringPtr += 1;\r
+\r
+ StringPtr = StrStr (StringPtr, L"&");\r
+\r
+ if (StringPtr == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Validate the config request string.\r
+\r
+ @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.\r
+\r
+ @retval CHAR16 * THE first element not correct.\r
+ @retval NULL Success parse the name/value pair\r
+\r
+**/\r
+CHAR16 *\r
+ConfigRequestValidate (\r
+ CHAR16 *ConfigRequest\r
+ )\r
+{\r
+ BOOLEAN HasNameField;\r
+ CHAR16 *StringPtr;\r
+\r
+ HasNameField = TRUE;\r
+ StringPtr = ConfigRequest;\r
+\r
+ //\r
+ // Check <ConfigHdr>\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return ConfigRequest;\r
+ }\r
+\r
+ StringPtr += StrLen (L"GUID=");\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return ConfigRequest;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&NAME=");\r
+ if (*StringPtr == L'&') {\r
+ HasNameField = FALSE;\r
+ }\r
+\r
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return ConfigRequest;\r
+ }\r
+\r
+ StringPtr += StrLen (L"&PATH=");\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr == L'\0') {\r
+ return NULL;\r
+ }\r
+\r
+ if (HasNameField) {\r
+ //\r
+ // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.\r
+ //\r
+ return OffsetWidthValidate (StringPtr);\r
+ } else {\r
+ //\r
+ // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.\r
+ //\r
+ return NameValueValidate (StringPtr);\r
+ }\r
+}\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration\r
+ for one or more named elements from one or more drivers.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param Request A null-terminated Unicode string in\r
+ <MultiConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ & before the first failing name / value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name / value pair) if the request was\r
+ not successful.\r
+ @param Results Null-terminated Unicode string in\r
+ <MultiConfigAltResp> format which has all values\r
+ filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results string is filled with the values\r
+ corresponding to all requested names.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
+ results that must be stored awaiting possible\r
+ future protocols.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
+ Progress set to the "G" in "GUID" of the routing\r
+ header that doesn't match. Note: There is no\r
+ requirement that all routing data be validated\r
+ before any configuration extraction.\r
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
+ parameter would result in this type of error. The\r
+ Progress parameter is set to NULL.\r
+ @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
+ before the error or the beginning of the string.\r
+ @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII\r
+ Configuration Access Protocol returned\r
+ EFI_INVALID_PARAMETER. Progress set to most recent\r
+ & before the error or the beginning of the string.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN Length;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Database;\r
+ UINT8 *DevicePathPkg;\r
+ UINT8 *CurrentDevicePath;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessProgress;\r
+ EFI_STRING AccessResults;\r
+ EFI_STRING AccessProgressBackup;\r
+ EFI_STRING AccessResultsBackup;\r
+ EFI_STRING DefaultResults;\r
+ BOOLEAN FirstElement;\r
+ BOOLEAN IfrDataParsedFlag;\r
+ BOOLEAN IsEfiVarStore;\r
+ EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
+ EFI_STRING ErrorPtr;\r
+ UINTN DevicePathSize;\r
+ UINTN ConigStringSize;\r
+ UINTN ConigStringSizeNewsize;\r
+ EFI_STRING ConfigStringPtr;\r
+\r
+ if ((This == NULL) || (Progress == NULL) || (Results == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Request == NULL) {\r
+ *Progress = NULL;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ StringPtr = Request;\r
+ *Progress = StringPtr;\r
+ DefaultResults = NULL;\r
+ ConfigRequest = NULL;\r
+ Status = EFI_SUCCESS;\r
+ AccessResults = NULL;\r
+ AccessProgress = NULL;\r
+ AccessResultsBackup = NULL;\r
+ AccessProgressBackup = NULL;\r
+ DevicePath = NULL;\r
+ IfrDataParsedFlag = FALSE;\r
+ IsEfiVarStore = FALSE;\r
+ EfiVarStoreInfo = NULL;\r
+\r
+ //\r
+ // The first element of <MultiConfigRequest> should be\r
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FirstElement = TRUE;\r
+\r
+ //\r
+ // Allocate a fix length of memory to store Results. Reallocate memory for\r
+ // Results if this fix length is insufficient.\r
+ //\r
+ *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
+ if (*Results == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+ //\r
+ // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
+ // or most recent & before the error.\r
+ //\r
+ if (StringPtr == Request) {\r
+ *Progress = StringPtr;\r
+ } else {\r
+ *Progress = StringPtr - 1;\r
}\r
\r
//\r
// Process each <ConfigRequest> of <MultiConfigRequest>\r
//\r
- Length = CalculateConfigStringLen (StringPtr);\r
+ Length = CalculateConfigStringLen (StringPtr);\r
ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
if (ConfigRequest == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
}\r
+\r
*(ConfigRequest + Length) = 0;\r
\r
//\r
// Get the UEFI device path\r
//\r
- Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
+ Status = GetDevicePath (ConfigRequest, (UINT8 **)&DevicePath);\r
if (EFI_ERROR (Status)) {\r
- SafeFreePool (ConfigRequest);\r
- return Status;\r
+ goto Done;\r
}\r
\r
//\r
// Find driver which matches the routing data.\r
//\r
DriverHandle = NULL;\r
+ HiiHandle = NULL;\r
+ Database = NULL;\r
for (Link = Private->DatabaseList.ForwardLink;\r
Link != &Private->DatabaseList;\r
Link = Link->ForwardLink\r
- ) {\r
+ )\r
+ {\r
Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
- \r
if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
- if (CompareMem (\r
- DevicePath,\r
- CurrentDevicePath,\r
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
- ) == 0) {\r
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);\r
+ if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigRequest)) {\r
DriverHandle = Database->DriverHandle;\r
+ HiiHandle = Database->Handle;\r
break;\r
}\r
}\r
}\r
\r
- SafeFreePool (DevicePath);\r
-\r
+ //\r
+ // Try to find driver handle by device path.\r
+ //\r
if (DriverHandle == NULL) {\r
+ TempDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TempDevicePath,\r
+ &DriverHandle\r
+ );\r
+ if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
+ //\r
+ // Routing data does not match any known driver.\r
+ // Set Progress to the 'G' in "GUID" of the routing header.\r
+ //\r
+ *Progress = StringPtr;\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Validate ConfigRequest String.\r
+ //\r
+ ErrorPtr = ConfigRequestValidate (ConfigRequest);\r
+ if (ErrorPtr != NULL) {\r
+ *Progress = StrStr (StringPtr, ErrorPtr);\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check whether ConfigRequest contains request string.\r
+ //\r
+ IfrDataParsedFlag = FALSE;\r
+ if ((HiiHandle != NULL) && !GetElementsFromRequest (ConfigRequest)) {\r
//\r
- // Routing data does not match any known driver.\r
- // Set Progress to the 'G' in "GUID" of the routing header.\r
+ // Get the full request string from IFR when HiiPackage is registered to HiiHandle\r
//\r
- *Progress = StringPtr;\r
- SafeFreePool (ConfigRequest);\r
- return EFI_NOT_FOUND;\r
+ IfrDataParsedFlag = TRUE;\r
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
+ // Map it to the progress on <MultiConfigRequest> then return it.\r
+ //\r
+ ASSERT (AccessProgress != NULL);\r
+ *Progress = StrStr (StringPtr, AccessProgress);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Not any request block is found.\r
+ //\r
+ if (!GetElementsFromRequest (ConfigRequest)) {\r
+ AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);\r
+ goto NextConfigString;\r
+ }\r
}\r
\r
//\r
- // Call corresponding ConfigAccess protocol to extract settings\r
+ // Check whether this ConfigRequest is search from Efi varstore type storage.\r
//\r
- Status = gBS->HandleProtocol (\r
- DriverHandle,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- (VOID **) &ConfigAccess\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ Status = GetVarStoreType (Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (IsEfiVarStore) {\r
+ //\r
+ // Call the GetVariable function to extract settings.\r
+ //\r
+ Status = GetConfigRespFromEfiVarStore (This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
+ FreePool (EfiVarStoreInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
+ // Map it to the progress on <MultiConfigRequest> then return it.\r
+ //\r
+ *Progress = StrStr (StringPtr, AccessProgress);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The driver has EfiVarStore, may not install ConfigAccess protocol.\r
+ // So ignore the error status in this case.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ ConfigRequest,\r
+ &AccessProgressBackup,\r
+ &AccessResultsBackup\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Merge the AltCfgResp in AccessResultsBackup to AccessResults\r
+ //\r
+ if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {\r
+ ConigStringSize = StrSize (AccessResults);\r
+ ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");\r
+ ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);\r
+ AccessResults = (EFI_STRING)ReallocatePool (\r
+ ConigStringSize,\r
+ ConigStringSizeNewsize,\r
+ AccessResults\r
+ );\r
+ StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);\r
+ }\r
+ } else {\r
+ //\r
+ // In the ExtractConfig function of some driver may not support EfiVarStore,\r
+ // may return error status, just ignore the error status in this case.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ if (AccessResultsBackup != NULL) {\r
+ FreePool (AccessResultsBackup);\r
+ AccessResultsBackup = NULL;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Call corresponding ConfigAccess protocol to extract settings\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ ConfigRequest,\r
+ &AccessProgress,\r
+ &AccessResults\r
+ );\r
+ }\r
\r
- Status = ConfigAccess->ExtractConfig (\r
- ConfigAccess,\r
- ConfigRequest,\r
- &AccessProgress,\r
- &AccessResults\r
- );\r
if (EFI_ERROR (Status)) {\r
//\r
// AccessProgress indicates the parsing progress on <ConfigRequest>.\r
// Map it to the progress on <MultiConfigRequest> then return it.\r
//\r
- RemainSize = StrSize (AccessProgress);\r
- for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
- *Progress = TmpPtr;\r
-\r
- SafeFreePool (ConfigRequest);\r
- return Status;\r
+ *Progress = StrStr (StringPtr, AccessProgress);\r
+ goto Done;\r
}\r
\r
//\r
- // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
+ // which separates the first <ConfigAltResp> and the following ones.\r
//\r
ASSERT (*AccessProgress == 0);\r
+\r
+ //\r
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
+ //\r
+ if (!IfrDataParsedFlag && (HiiHandle != NULL)) {\r
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ FreePool (DevicePath);\r
+ DevicePath = NULL;\r
+\r
+ if (DefaultResults != NULL) {\r
+ Status = MergeDefaultString (&AccessResults, DefaultResults);\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (DefaultResults);\r
+ DefaultResults = NULL;\r
+ }\r
+\r
+NextConfigString:\r
+ if (!FirstElement) {\r
+ Status = AppendToMultiString (Results, L"&");\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
Status = AppendToMultiString (Results, AccessResults);\r
ASSERT_EFI_ERROR (Status);\r
- SafeFreePool (AccessResults);\r
+\r
+ FirstElement = FALSE;\r
+\r
+ FreePool (AccessResults);\r
AccessResults = NULL;\r
- SafeFreePool (ConfigRequest);\r
+ FreePool (ConfigRequest);\r
ConfigRequest = NULL;\r
\r
//\r
}\r
\r
StringPtr++;\r
+ }\r
\r
+Done:\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (*Results);\r
+ *Results = NULL;\r
}\r
\r
- return EFI_SUCCESS;\r
+ if (ConfigRequest != NULL) {\r
+ FreePool (ConfigRequest);\r
+ }\r
\r
-}\r
+ if (AccessResults != NULL) {\r
+ FreePool (AccessResults);\r
+ }\r
\r
+ if (DefaultResults != NULL) {\r
+ FreePool (DefaultResults);\r
+ }\r
+\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+\r
+ return Status;\r
+}\r
\r
/**\r
This function allows the caller to request the current configuration for the\r
instance.\r
@param Results Null-terminated Unicode string in\r
<MultiConfigAltResp> format which has all values\r
- filled in for the names in the Request string.\r
- String to be allocated by the called function.\r
- De-allocation is up to the caller.\r
+ filled in for the entirety of the current HII\r
+ database. String to be allocated by the called\r
+ function. De-allocation is up to the caller.\r
\r
@retval EFI_SUCCESS The Results string is filled with the values\r
corresponding to all requested names.\r
OUT EFI_STRING *Results\r
)\r
{\r
- EFI_STATUS Status;\r
- HII_DATABASE_PRIVATE_DATA *Private;\r
- LIST_ENTRY StorageListHdr;\r
- HII_FORMSET_STORAGE *Storage;\r
- LIST_ENTRY *Link;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UINTN Length;\r
- EFI_STRING PathHdr;\r
- UINTN PathHdrSize;\r
- EFI_STRING ConfigRequest;\r
- UINTN RequestSize;\r
- EFI_STRING StringPtr;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_STRING AccessProgress;\r
- EFI_STRING AccessResults;\r
-\r
- //\r
- // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
- // as FALSE. But this renders the system to not 100% compliant with\r
- // UEFI 2.1. Use this with caution.\r
- //\r
- if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (This == NULL || Results == NULL) {\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessResults;\r
+ EFI_STRING Progress;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN Index;\r
+ EFI_HANDLE *ConfigAccessHandles;\r
+ UINTN NumberConfigAccessHandles;\r
+ BOOLEAN FirstElement;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_STRING DefaultResults;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Database;\r
+ UINT8 *DevicePathPkg;\r
+ UINT8 *CurrentDevicePath;\r
+ BOOLEAN IfrDataParsedFlag;\r
+\r
+ if ((This == NULL) || (Results == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
\r
- InitializeListHead (&StorageListHdr);\r
-\r
- Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
//\r
// Allocate a fix length of memory to store Results. Reallocate memory for\r
// Results if this fix length is insufficient.\r
//\r
- *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+ *Results = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
if (*Results == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- //\r
- // Parsing all formset storages.\r
- //\r
- for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {\r
- Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);\r
- //\r
- // Find the corresponding device path instance\r
- //\r
+ NumberConfigAccessHandles = 0;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ NULL,\r
+ &NumberConfigAccessHandles,\r
+ &ConfigAccessHandles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FirstElement = TRUE;\r
+\r
+ for (Index = 0; Index < NumberConfigAccessHandles; Index++) {\r
Status = gBS->HandleProtocol (\r
- Storage->DriverHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &DevicePath\r
+ ConfigAccessHandles[Index],\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&ConfigAccess\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Convert the device path binary to hex UNICODE %02x bytes in the same order\r
- // as the device path resides in RAM memory.\r
- //\r
- Length = GetDevicePathSize (DevicePath);\r
- PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);\r
- PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize);\r
- if (PathHdr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ continue;\r
}\r
- Status = BufInReverseOrderToHexString (PathHdr, (UINT8 *) DevicePath, Length);\r
- ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.\r
- // It means extract all possible configurations from this specific driver.\r
+ // Get DevicePath and HiiHandle for this ConfigAccess driver handle\r
//\r
- RequestSize = (StrLen (L"GUID=&NAME=&PATH=") + 32) * sizeof (CHAR16) + PathHdrSize;\r
- if (Storage->Name != NULL) {\r
- RequestSize += StrLen (Storage->Name) * 4 * sizeof (CHAR16);\r
- }\r
- \r
- ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);\r
- if (ConfigRequest == NULL) {\r
- SafeFreePool (PathHdr);\r
- return EFI_OUT_OF_RESOURCES;\r
+ IfrDataParsedFlag = FALSE;\r
+ Progress = NULL;\r
+ HiiHandle = NULL;\r
+ DefaultResults = NULL;\r
+ Database = NULL;\r
+ ConfigRequest = NULL;\r
+ DevicePath = DevicePathFromHandle (ConfigAccessHandles[Index]);\r
+ if (DevicePath != NULL) {\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ )\r
+ {\r
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
+ CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+ if (CompareMem (\r
+ DevicePath,\r
+ CurrentDevicePath,\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath)\r
+ ) == 0)\r
+ {\r
+ HiiHandle = Database->Handle;\r
+ break;\r
+ }\r
+ }\r
+ }\r
}\r
\r
- //\r
- // Add <GuidHdr>\r
- // <GuidHdr> ::= 'GUID='<Guid>\r
- // Convert <Guid> in the same order as it resides in RAM memory.\r
- //\r
- StringPtr = ConfigRequest;\r
- StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));\r
- StringPtr += StrLen (L"GUID=");\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ NULL,\r
+ &Progress,\r
+ &AccessResults\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
+ //\r
+ if ((HiiHandle != NULL) && (DevicePath != NULL)) {\r
+ IfrDataParsedFlag = TRUE;\r
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);\r
+ //\r
+ // Get the full request string to get the Current setting again.\r
+ //\r
+ if (!EFI_ERROR (Status) && (ConfigRequest != NULL)) {\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &AccessResults\r
+ );\r
+ FreePool (ConfigRequest);\r
+ } else {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ }\r
\r
- Status = BufInReverseOrderToHexString (StringPtr, (UINT8 *) (&Storage->Guid), sizeof (EFI_GUID));\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- StringPtr += 32;\r
- ASSERT (*StringPtr == 0);\r
- *StringPtr = L'&';\r
- StringPtr++;\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle\r
+ //\r
+ if (!IfrDataParsedFlag && (HiiHandle != NULL) && (DevicePath != NULL)) {\r
+ StringPtr = StrStr (AccessResults, L"&GUID=");\r
+ if (StringPtr != NULL) {\r
+ *StringPtr = 0;\r
+ }\r
\r
- //\r
- // Add <NameHdr>\r
- // <NameHdr> ::= 'NAME='<String>\r
- //\r
- StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));\r
- StringPtr += StrLen (L"NAME=");\r
+ if (GetElementsFromRequest (AccessResults)) {\r
+ Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
\r
- if (Storage->Name != NULL) {\r
- Length = (StrLen (Storage->Name) * 4 + 1) * sizeof (CHAR16);\r
- Status = UnicodeToConfigString (StringPtr, &Length, Storage->Name);\r
- ASSERT_EFI_ERROR (Status);\r
- StringPtr += StrLen (Storage->Name) * 4;\r
- }\r
- \r
- *StringPtr = L'&';\r
- StringPtr++;\r
+ if (StringPtr != NULL) {\r
+ *StringPtr = L'&';\r
+ }\r
+ }\r
\r
- //\r
- // Add <PathHdr>\r
- // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>\r
- //\r
- StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));\r
- StringPtr += StrLen (L"PATH=");\r
- StrCpy (StringPtr, PathHdr);\r
+ //\r
+ // Merge the default sting from IFR code into the got setting from driver.\r
+ //\r
+ if (DefaultResults != NULL) {\r
+ Status = MergeDefaultString (&AccessResults, DefaultResults);\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (DefaultResults);\r
+ DefaultResults = NULL;\r
+ }\r
\r
- SafeFreePool (PathHdr);\r
- PathHdr = NULL;\r
+ //\r
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'\r
+ // which separates the first <ConfigAltResp> and the following ones.\r
+ //\r
+ if (!FirstElement) {\r
+ Status = AppendToMultiString (Results, L"&");\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
\r
- //\r
- // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the\r
- // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>\r
- // is required to call ConfigAccess.ExtractConfig().\r
- //\r
- // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess\r
- // to handle such kind of "ConfigRequest". It is not supported till now.\r
- //\r
- // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()\r
- // will be updated as soon as the decision is made.\r
+ Status = AppendToMultiString (Results, AccessResults);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Route the request to corresponding ConfigAccess protocol to extract settings.\r
- //\r
- Status = gBS->HandleProtocol (\r
- Storage->DriverHandle,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- (VOID **) &ConfigAccess\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ FirstElement = FALSE;\r
\r
- Status = ConfigAccess->ExtractConfig (\r
- ConfigAccess,\r
- ConfigRequest,\r
- &AccessProgress,\r
- &AccessResults\r
- );\r
- if (EFI_ERROR (Status)) {\r
- SafeFreePool (ConfigRequest);\r
- SafeFreePool (AccessResults);\r
- return EFI_INVALID_PARAMETER;\r
+ FreePool (AccessResults);\r
+ AccessResults = NULL;\r
}\r
-\r
- //\r
- // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
- //\r
- ASSERT (*AccessProgress == 0);\r
- Status = AppendToMultiString (Results, AccessResults);\r
- ASSERT_EFI_ERROR (Status);\r
- SafeFreePool (AccessResults);\r
- AccessResults = NULL;\r
- SafeFreePool (ConfigRequest);\r
- ConfigRequest = NULL;\r
-\r
}\r
\r
- //\r
- // Free the exported storage resource\r
- //\r
- while (!IsListEmpty (&StorageListHdr)) {\r
- Storage = CR (\r
- StorageListHdr.ForwardLink,\r
- HII_FORMSET_STORAGE,\r
- Entry,\r
- HII_FORMSET_STORAGE_SIGNATURE\r
- );\r
- RemoveEntryList (&Storage->Entry);\r
- SafeFreePool (Storage->Name);\r
- SafeFreePool (Storage);\r
- }\r
+ FreePool (ConfigAccessHandles);\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
This function processes the results of processing forms and routes it to the\r
appropriate handlers or storage.\r
OUT EFI_STRING *Progress\r
)\r
{\r
- HII_DATABASE_PRIVATE_DATA *Private;\r
- EFI_STRING StringPtr;\r
- EFI_STRING ConfigResp;\r
- UINTN Length;\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- LIST_ENTRY *Link;\r
- HII_DATABASE_RECORD *Database;\r
- UINT8 *DevicePathPkg;\r
- UINT8 *CurrentDevicePath;\r
- EFI_HANDLE DriverHandle;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_STRING AccessProgress;\r
- UINTN RemainSize;\r
- EFI_STRING TmpPtr;\r
-\r
- //\r
- // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
- // as FALSE. But this renders the system to not 100% compliant with\r
- // UEFI 2.1. Use this with caution.\r
- //\r
- if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (This == NULL || Progress == NULL) {\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING ConfigResp;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Database;\r
+ UINT8 *DevicePathPkg;\r
+ UINT8 *CurrentDevicePath;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessProgress;\r
+ EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;\r
+ BOOLEAN IsEfiVarstore;\r
+ UINTN DevicePathSize;\r
+\r
+ if ((This == NULL) || (Progress == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
- StringPtr = Configuration;\r
- *Progress = StringPtr;\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ StringPtr = Configuration;\r
+ *Progress = StringPtr;\r
+ Database = NULL;\r
+ AccessProgress = NULL;\r
+ EfiVarStoreInfo = NULL;\r
+ IsEfiVarstore = FALSE;\r
\r
//\r
// The first element of <MultiConfigResp> should be\r
//\r
// Process each <ConfigResp> of <MultiConfigResp>\r
//\r
- Length = CalculateConfigStringLen (StringPtr);\r
+ Length = CalculateConfigStringLen (StringPtr);\r
ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
if (ConfigResp == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+\r
//\r
// Append '\0' to the end of ConfigRequest\r
//\r
//\r
// Get the UEFI device path\r
//\r
- Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
+ Status = GetDevicePath (ConfigResp, (UINT8 **)&DevicePath);\r
if (EFI_ERROR (Status)) {\r
- SafeFreePool (ConfigResp);\r
+ FreePool (ConfigResp);\r
return Status;\r
}\r
\r
for (Link = Private->DatabaseList.ForwardLink;\r
Link != &Private->DatabaseList;\r
Link = Link->ForwardLink\r
- ) {\r
+ )\r
+ {\r
Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
\r
if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {\r
CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
- if (CompareMem (\r
- DevicePath,\r
- CurrentDevicePath,\r
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
- ) == 0) {\r
+ DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);\r
+ if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0) && IsThisPackageList (Database, ConfigResp)) {\r
DriverHandle = Database->DriverHandle;\r
break;\r
}\r
}\r
}\r
\r
- SafeFreePool (DevicePath);\r
-\r
+ //\r
+ // Try to find driver handle by device path.\r
+ //\r
if (DriverHandle == NULL) {\r
- //\r
- // Routing data does not match any known driver.\r
- // Set Progress to the 'G' in "GUID" of the routing header.\r
- //\r
- *Progress = StringPtr;\r
- SafeFreePool (ConfigResp);\r
- return EFI_NOT_FOUND;\r
+ TempDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TempDevicePath,\r
+ &DriverHandle\r
+ );\r
+ if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
+ //\r
+ // Routing data does not match any known driver.\r
+ // Set Progress to the 'G' in "GUID" of the routing header.\r
+ //\r
+ FreePool (DevicePath);\r
+ *Progress = StringPtr;\r
+ FreePool (ConfigResp);\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r
\r
+ FreePool (DevicePath);\r
+\r
//\r
- // Call corresponding ConfigAccess protocol to route settings\r
+ // Check whether this ConfigRequest is search from Efi varstore type storage.\r
//\r
- Status = gBS->HandleProtocol (\r
- DriverHandle,\r
- &gEfiHiiConfigAccessProtocolGuid,\r
- (VOID **) &ConfigAccess\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ Status = GetVarStoreType (Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- Status = ConfigAccess->RouteConfig (\r
- ConfigAccess,\r
- ConfigResp,\r
- &AccessProgress\r
- );\r
+ if (IsEfiVarstore) {\r
+ //\r
+ // Call the SetVariable function to route settings.\r
+ //\r
+ Status = RouteConfigRespForEfiVarStore (This, EfiVarStoreInfo, ConfigResp, &AccessProgress);\r
+ FreePool (EfiVarStoreInfo);\r
+ } else {\r
+ //\r
+ // Call corresponding ConfigAccess protocol to route settings\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **)&ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = StringPtr;\r
+ FreePool (ConfigResp);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Status = ConfigAccess->RouteConfig (\r
+ ConfigAccess,\r
+ ConfigResp,\r
+ &AccessProgress\r
+ );\r
+ }\r
\r
if (EFI_ERROR (Status)) {\r
+ ASSERT (AccessProgress != NULL);\r
//\r
// AccessProgress indicates the parsing progress on <ConfigResp>.\r
// Map it to the progress on <MultiConfigResp> then return it.\r
//\r
- RemainSize = StrSize (AccessProgress);\r
- for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
- *Progress = TmpPtr;\r
+ *Progress = StrStr (StringPtr, AccessProgress);\r
\r
- SafeFreePool (ConfigResp);\r
+ FreePool (ConfigResp);\r
return Status;\r
}\r
\r
- SafeFreePool (ConfigResp);\r
+ FreePool (ConfigResp);\r
ConfigResp = NULL;\r
\r
//\r
}\r
\r
StringPtr++;\r
-\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
This helper function is to be called by drivers to map configuration data\r
stored in byte array ("block") formats such as UEFI Variables into current\r
@param BlockSize Length in bytes of Block.\r
@param Config Filled-in configuration string. String allocated\r
by the function. Returned only if call is\r
- successful.\r
+ successful. It is <ConfigResp> string format.\r
@param Progress A pointer to a string filled in with the offset of\r
the most recent & before the first failing\r
name/value pair (or the beginning of the string if\r
OUT EFI_STRING *Progress\r
)\r
{\r
- HII_DATABASE_PRIVATE_DATA *Private;\r
- EFI_STRING StringPtr;\r
- UINTN Length;\r
- EFI_STATUS Status;\r
- EFI_STRING TmpPtr;\r
- UINT8 *TmpBuffer;\r
- UINTN Offset;\r
- UINTN Width;\r
- UINT8 *Value;\r
- EFI_STRING ValueStr;\r
- EFI_STRING ConfigElement;\r
-\r
- if (This == NULL || Progress == NULL || Config == NULL) {\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ EFI_STRING TmpPtr;\r
+ UINT8 *TmpBuffer;\r
+ UINTN Offset;\r
+ UINTN Width;\r
+ UINT8 *Value;\r
+ EFI_STRING ValueStr;\r
+ EFI_STRING ConfigElement;\r
+ UINTN Index;\r
+ UINT8 *TemBuffer;\r
+ CHAR16 *TemString;\r
+\r
+ TmpBuffer = NULL;\r
+\r
+ if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (Block == NULL || ConfigRequest == NULL) {\r
+ if ((Block == NULL) || (ConfigRequest == NULL)) {\r
*Progress = ConfigRequest;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
-\r
Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
ASSERT (Private != NULL);\r
\r
// Allocate a fix length of memory to store Results. Reallocate memory for\r
// Results if this fix length is insufficient.\r
//\r
- *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+ *Config = (EFI_STRING)AllocateZeroPool (MAX_STRING_LENGTH);\r
if (*Config == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
//\r
if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
*Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
+\r
while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
StringPtr++;\r
}\r
+\r
if (*StringPtr == 0) {\r
- *Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
+ *Progress = StringPtr - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
while (*StringPtr != L'&' && *StringPtr != 0) {\r
StringPtr++;\r
}\r
+\r
if (*StringPtr == 0) {\r
*Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Exit;\r
+\r
+ AppendToMultiString (Config, ConfigRequest);\r
+ HiiToLower (*Config);\r
+\r
+ return EFI_SUCCESS;\r
}\r
+\r
//\r
// Skip '&'\r
//\r
//\r
// Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
//\r
- Length = StringPtr - ConfigRequest;\r
- CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
+ TemString = AllocateCopyPool (sizeof (CHAR16) * (StringPtr - ConfigRequest + 1), ConfigRequest);\r
+ if (TemString == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TemString[StringPtr - ConfigRequest] = '\0';\r
+ AppendToMultiString (Config, TemString);\r
+ FreePool (TemString);\r
\r
//\r
// Parse each <RequestElement> if exists\r
// Get Offset\r
//\r
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- *Progress = ConfigRequest;\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = TmpPtr - 1;\r
goto Exit;\r
}\r
+\r
Offset = 0;\r
CopyMem (\r
&Offset,\r
TmpBuffer,\r
(((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
);\r
- SafeFreePool (TmpBuffer);\r
+ FreePool (TmpBuffer);\r
\r
StringPtr += Length;\r
if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
- *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
- Status = EFI_INVALID_PARAMETER;\r
+ *Progress = TmpPtr - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
+\r
StringPtr += StrLen (L"&WIDTH=");\r
\r
//\r
// Get Width\r
//\r
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- *Progress = ConfigRequest;\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = TmpPtr - 1;\r
goto Exit;\r
}\r
+\r
Width = 0;\r
CopyMem (\r
&Width,\r
TmpBuffer,\r
(((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
);\r
- SafeFreePool (TmpBuffer);\r
+ FreePool (TmpBuffer);\r
\r
StringPtr += Length;\r
- if (*StringPtr != 0 && *StringPtr != L'&') {\r
- *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
- Status = EFI_INVALID_PARAMETER;\r
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
+ *Progress = TmpPtr - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
//\r
if (Offset + Width > BlockSize) {\r
*Progress = StringPtr;\r
- Status = EFI_DEVICE_ERROR;\r
+ Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
\r
- Value = (UINT8 *) AllocateZeroPool (Width);\r
+ Value = (UINT8 *)AllocateZeroPool (Width);\r
if (Value == NULL) {\r
*Progress = ConfigRequest;\r
- Status = EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
\r
- CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
+ CopyMem (Value, (UINT8 *)Block + Offset, Width);\r
\r
- Length = Width * 2 + 1;\r
- ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+ Length = Width * 2 + 1;\r
+ ValueStr = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));\r
if (ValueStr == NULL) {\r
*Progress = ConfigRequest;\r
- Status = EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
\r
- Status = BufToHexString (ValueStr, &Length, Value, Width);\r
- ASSERT_EFI_ERROR (Status);\r
- ToLower (ValueStr);\r
+ TemString = ValueStr;\r
+ TemBuffer = Value + Width - 1;\r
+ for (Index = 0; Index < Width; Index++, TemBuffer--) {\r
+ UnicodeValueToStringS (\r
+ TemString,\r
+ Length * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),\r
+ PREFIX_ZERO | RADIX_HEX,\r
+ *TemBuffer,\r
+ 2\r
+ );\r
+ TemString += StrnLenS (TemString, Length - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));\r
+ }\r
\r
- SafeFreePool (Value);\r
+ FreePool (Value);\r
Value = NULL;\r
\r
//\r
// Build a ConfigElement\r
//\r
- Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
- ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+ Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
+ ConfigElement = (EFI_STRING)AllocateZeroPool (Length * sizeof (CHAR16));\r
if (ConfigElement == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
+\r
CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
if (*StringPtr == 0) {\r
*(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
}\r
+\r
*(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
- StrCat (ConfigElement, L"VALUE=");\r
- StrCat (ConfigElement, ValueStr);\r
+ StrCatS (ConfigElement, Length, L"VALUE=");\r
+ StrCatS (ConfigElement, Length, ValueStr);\r
\r
AppendToMultiString (Config, ConfigElement);\r
\r
- SafeFreePool (ConfigElement);\r
- SafeFreePool (ValueStr);\r
+ FreePool (ConfigElement);\r
+ FreePool (ValueStr);\r
ConfigElement = NULL;\r
- ValueStr = NULL;\r
+ ValueStr = NULL;\r
\r
//\r
// If '\0', parsing is finished. Otherwise skip '&' to continue\r
if (*StringPtr == 0) {\r
break;\r
}\r
+\r
AppendToMultiString (Config, L"&");\r
StringPtr++;\r
-\r
}\r
\r
if (*StringPtr != 0) {\r
*Progress = StringPtr - 1;\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
+ HiiToLower (*Config);\r
*Progress = StringPtr;\r
return EFI_SUCCESS;\r
\r
Exit:\r
+ if (*Config != NULL) {\r
+ FreePool (*Config);\r
+ *Config = NULL;\r
+ }\r
\r
- SafeFreePool (*Config);\r
- SafeFreePool (ValueStr);\r
- SafeFreePool (Value);\r
- SafeFreePool (ConfigElement);\r
+ if (ValueStr != NULL) {\r
+ FreePool (ValueStr);\r
+ }\r
\r
- return Status;\r
+ if (Value != NULL) {\r
+ FreePool (Value);\r
+ }\r
\r
-}\r
+ if (ConfigElement != NULL) {\r
+ FreePool (ConfigElement);\r
+ }\r
\r
+ return Status;\r
+}\r
\r
/**\r
This helper function is to be called by drivers to map configuration strings\r
(see below) is returned.\r
@param BlockSize The length of the Block in units of UINT8. On\r
input, this is the size of the Block. On output,\r
- if successful, contains the index of the last\r
- modified byte in the Block.\r
+ if successful, contains the largest index of the\r
+ modified byte in the Block, or the required buffer\r
+ size if the Block is not large enough.\r
@param Progress On return, points to an element of the ConfigResp\r
string filled in with the offset of the most\r
recent '&' before the first failing name / value\r
value pair. Block is left updated and\r
Progress points at the '&' preceding the first\r
non-<BlockName>.\r
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.\r
+ BlockSize is updated with the required buffer size.\r
+ @retval EFI_NOT_FOUND Target for the specified routing data was not found.\r
+ Progress points to the "G" in "GUID" of the errant\r
+ routing data.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
HiiConfigToBlock (\r
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
- IN CONST EFI_STRING ConfigResp,\r
- IN OUT UINT8 *Block,\r
- IN OUT UINTN *BlockSize,\r
- OUT EFI_STRING *Progress\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING ConfigResp,\r
+ IN OUT UINT8 *Block,\r
+ IN OUT UINTN *BlockSize,\r
+ OUT EFI_STRING *Progress\r
)\r
{\r
- HII_DATABASE_PRIVATE_DATA *Private;\r
- EFI_STRING StringPtr;\r
- UINTN Length;\r
- EFI_STATUS Status;\r
- UINT8 *TmpBuffer;\r
- UINTN Offset;\r
- UINTN Width;\r
- UINT8 *Value;\r
- UINTN BufferSize;\r
-\r
- if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ UINT8 *TmpBuffer;\r
+ UINTN Offset;\r
+ UINTN Width;\r
+ UINT8 *Value;\r
+ UINTN BufferSize;\r
+ UINTN MaxBlockSize;\r
+\r
+ TmpBuffer = NULL;\r
+\r
+ if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (ConfigResp == NULL || Block == NULL) {\r
- *Progress = ConfigResp;\r
+ *Progress = ConfigResp;\r
+ if (ConfigResp == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
ASSERT (Private != NULL);\r
\r
- StringPtr = ConfigResp;\r
- BufferSize = *BlockSize;\r
- Value = NULL;\r
+ StringPtr = ConfigResp;\r
+ BufferSize = *BlockSize;\r
+ Value = NULL;\r
+ MaxBlockSize = 0;\r
\r
//\r
// Jump <ConfigHdr>\r
//\r
if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
*Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
+\r
while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
StringPtr++;\r
}\r
+\r
if (*StringPtr == 0) {\r
*Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
while (*StringPtr != L'&' && *StringPtr != 0) {\r
StringPtr++;\r
}\r
+\r
if (*StringPtr == 0) {\r
*Progress = StringPtr;\r
- Status = EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
- //\r
- // Skip '&'\r
- //\r
- StringPtr++;\r
\r
//\r
// Parse each <ConfigElement> if exists\r
- // Only <BlockConfig> format is supported by this help function.\r
+ // Only '&'<BlockConfig> format is supported by this help function.\r
// <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
//\r
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
- StringPtr += StrLen (L"OFFSET=");\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
+ TmpPtr = StringPtr;\r
+ StringPtr += StrLen (L"&OFFSET=");\r
//\r
// Get Offset\r
//\r
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- *Progress = ConfigResp;\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = TmpPtr;\r
goto Exit;\r
}\r
+\r
Offset = 0;\r
CopyMem (\r
&Offset,\r
TmpBuffer,\r
(((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
);\r
- SafeFreePool (TmpBuffer);\r
+ FreePool (TmpBuffer);\r
\r
StringPtr += Length;\r
if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
- *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
- Status = EFI_INVALID_PARAMETER;\r
+ *Progress = TmpPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
+\r
StringPtr += StrLen (L"&WIDTH=");\r
\r
//\r
// Get Width\r
//\r
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- *Progress = ConfigResp;\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = TmpPtr;\r
goto Exit;\r
}\r
+\r
Width = 0;\r
CopyMem (\r
&Width,\r
TmpBuffer,\r
(((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
);\r
- SafeFreePool (TmpBuffer);\r
+ FreePool (TmpBuffer);\r
\r
StringPtr += Length;\r
if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
- *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
- Status = EFI_INVALID_PARAMETER;\r
+ *Progress = TmpPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
+\r
StringPtr += StrLen (L"&VALUE=");\r
\r
//\r
// Get Value\r
//\r
Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- *Progress = ConfigResp;\r
+ if (EFI_ERROR (Status)) {\r
+ *Progress = TmpPtr;\r
goto Exit;\r
}\r
\r
StringPtr += Length;\r
- if (*StringPtr != 0 && *StringPtr != L'&') {\r
- *Progress = StringPtr - Length - 7;\r
- Status = EFI_INVALID_PARAMETER;\r
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {\r
+ *Progress = TmpPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
//\r
// Update the Block with configuration info\r
//\r
-\r
- if (Offset + Width > BufferSize) {\r
- return EFI_DEVICE_ERROR;\r
+ if ((Block != NULL) && (Offset + Width <= BufferSize)) {\r
+ CopyMem (Block + Offset, Value, Width);\r
}\r
\r
- CopyMem (Block + Offset, Value, Width);\r
- *BlockSize = Offset + Width - 1;\r
+ if (Offset + Width > MaxBlockSize) {\r
+ MaxBlockSize = Offset + Width;\r
+ }\r
\r
- SafeFreePool (Value);\r
+ FreePool (Value);\r
Value = NULL;\r
\r
//\r
- // If '\0', parsing is finished. Otherwise skip '&' to continue\r
+ // If '\0', parsing is finished.\r
//\r
if (*StringPtr == 0) {\r
break;\r
}\r
-\r
- StringPtr++;\r
}\r
\r
+ //\r
+ // The input string is not ConfigResp format, return error.\r
+ //\r
if (*StringPtr != 0) {\r
- *Progress = StringPtr - 1;\r
- Status = EFI_INVALID_PARAMETER;\r
+ *Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
goto Exit;\r
}\r
\r
- *Progress = StringPtr;\r
+ *Progress = StringPtr + StrLen (StringPtr);\r
+ *BlockSize = MaxBlockSize - 1;\r
+\r
+ if (MaxBlockSize > BufferSize) {\r
+ *BlockSize = MaxBlockSize;\r
+ if (Block != NULL) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+\r
+ if (Block == NULL) {\r
+ *Progress = ConfigResp;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
return EFI_SUCCESS;\r
\r
Exit:\r
\r
- SafeFreePool (Value);\r
+ if (Value != NULL) {\r
+ FreePool (Value);\r
+ }\r
+\r
return Status;\r
}\r
\r
-\r
/**\r
This helper function is to be called by drivers to extract portions of\r
a larger configuration string.\r
@param AltCfgResp A pointer to a buffer which will be allocated by\r
the function which contains the retrieved string\r
as requested. This buffer is only allocated if\r
- the call was successful.\r
+ the call was successful. It is <ConfigResp> format.\r
\r
@retval EFI_SUCCESS The request succeeded. The requested data was\r
extracted and placed in the newly allocated\r
EFI_STATUS\r
EFIAPI\r
HiiGetAltCfg (\r
- IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
- IN CONST EFI_STRING Configuration,\r
- IN CONST EFI_GUID *Guid,\r
- IN CONST EFI_STRING Name,\r
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN CONST UINT16 *AltCfgId,\r
- OUT EFI_STRING *AltCfgResp\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN CONST EFI_STRING Name,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN CONST UINT16 *AltCfgId,\r
+ OUT EFI_STRING *AltCfgResp\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_STRING StringPtr;\r
- EFI_STRING HdrStart;\r
- EFI_STRING HdrEnd;\r
- EFI_STRING TmpPtr;\r
- UINTN Length;\r
- EFI_STRING GuidStr;\r
- EFI_STRING NameStr;\r
- EFI_STRING PathStr;\r
- EFI_STRING AltIdStr;\r
- EFI_STRING Result;\r
- BOOLEAN GuidFlag;\r
- BOOLEAN NameFlag;\r
- BOOLEAN PathFlag;\r
-\r
- //\r
- // For size reduction, please define PcdSupportFullConfigRoutingProtocol \r
- // as FALSE. But this renders the system to not 100% compliant with\r
- // UEFI 2.1. Use this with caution.\r
- //\r
- if (!FeaturePcdGet (PcdSupportFullConfigRoutingProtocol)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
+ EFI_STATUS Status;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING HdrStart;\r
+ EFI_STRING HdrEnd;\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STRING GuidStr;\r
+ EFI_STRING NameStr;\r
+ EFI_STRING PathStr;\r
+ EFI_STRING AltIdStr;\r
+ EFI_STRING Result;\r
+ BOOLEAN GuidFlag;\r
+ BOOLEAN NameFlag;\r
+ BOOLEAN PathFlag;\r
\r
HdrStart = NULL;\r
HdrEnd = NULL;\r
NameFlag = FALSE;\r
PathFlag = FALSE;\r
\r
- if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
+ if ((This == NULL) || (Configuration == NULL) || (AltCfgResp == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Generate the sub string for later matching.\r
//\r
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)Guid, 1, &GuidStr);\r
GenerateSubStr (\r
L"PATH=",\r
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
- (VOID *) DevicePath,\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),\r
+ (VOID *)DevicePath,\r
1,\r
&PathStr\r
);\r
if (AltCfgId != NULL) {\r
- GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr); \r
+ GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *)AltCfgId, 3, &AltIdStr);\r
}\r
+\r
if (Name != NULL) {\r
- GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr); \r
+ GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *)Name, 2, &NameStr);\r
} else {\r
GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);\r
}\r
Status = EFI_NOT_FOUND;\r
goto Exit;\r
}\r
+\r
HdrStart = TmpPtr;\r
\r
//\r
goto Exit;\r
}\r
}\r
+\r
GuidFlag = TRUE;\r
}\r
\r
goto Exit;\r
}\r
}\r
+\r
NameFlag = TRUE;\r
}\r
}\r
Status = EFI_NOT_FOUND;\r
goto Exit;\r
}\r
+\r
+ StringPtr++;\r
}\r
+\r
PathFlag = TRUE;\r
- HdrEnd = ++StringPtr;\r
+ HdrEnd = StringPtr;\r
}\r
}\r
\r
Status = OutputConfigBody (StringPtr, &Result);\r
goto Exit;\r
}\r
+\r
//\r
// Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
//\r
NameFlag = FALSE;\r
PathFlag = FALSE;\r
} else {\r
- Status = OutputConfigBody (StringPtr, &Result);\r
+ //\r
+ // Skip AltIdStr and &\r
+ //\r
+ StringPtr = StringPtr + StrLen (AltIdStr);\r
+ Status = OutputConfigBody (StringPtr, &Result);\r
goto Exit;\r
}\r
}\r
Status = EFI_NOT_FOUND;\r
\r
Exit:\r
-\r
- if (!EFI_ERROR (Status)) {\r
+ *AltCfgResp = NULL;\r
+ if (!EFI_ERROR (Status) && (Result != NULL)) {\r
//\r
// Copy the <ConfigHdr> and <ConfigBody>\r
//\r
- Length = HdrEnd - HdrStart + StrLen (Result);\r
+ Length = HdrEnd - HdrStart + StrLen (Result) + 1;\r
*AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
if (*AltCfgResp == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
} else {\r
- StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
- StrCat (*AltCfgResp, Result);\r
+ StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);\r
+ StrCatS (*AltCfgResp, Length, Result);\r
Status = EFI_SUCCESS;\r
}\r
}\r
\r
- SafeFreePool (GuidStr);\r
- SafeFreePool (NameStr);\r
- SafeFreePool (PathStr);\r
- SafeFreePool (AltIdStr);\r
- SafeFreePool (Result);\r
+ if (GuidStr != NULL) {\r
+ FreePool (GuidStr);\r
+ }\r
\r
- return Status;\r
+ if (NameStr != NULL) {\r
+ FreePool (NameStr);\r
+ }\r
\r
-}\r
+ if (PathStr != NULL) {\r
+ FreePool (PathStr);\r
+ }\r
+\r
+ if (AltIdStr != NULL) {\r
+ FreePool (AltIdStr);\r
+ }\r
\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
\r
+ return Status;\r
+}\r