From 9185c388a9e992bcbcf38d10fb24321a60950562 Mon Sep 17 00:00:00 2001 From: qwang12 Date: Tue, 4 Nov 2008 14:22:22 +0000 Subject: [PATCH] Sync in bug fix from EDK I: 1) issue with setup browser and IFR refresh opcode 2) [HII]HIIConfigRoutingExportConfig generate error format of 3) [HII] ConfigRouting->ExtractConfig() will cause overflow 4) [Hii Database] EFI_HII_DATABASE_NOTIFY should be invoked when a string package is created internally when a new String Token is created 5) [PT]HIIConfigAccessProtocolTest fail on NT32uefi 6) Incorrect HII package types in EDK git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@6377 6f19259b-4bc3-4df7-8a09-765794883524 --- MdePkg/Include/Library/IfrSupportLib.h | 60 +++ .../Uefi/UefiInternalFormRepresentation.h | 4 +- .../Library/UefiIfrSupportLib/UefiIfrForm.c | 457 +++++++++++++++++- 3 files changed, 516 insertions(+), 5 deletions(-) diff --git a/MdePkg/Include/Library/IfrSupportLib.h b/MdePkg/Include/Library/IfrSupportLib.h index 2904cb24cf..3f686bd49c 100644 --- a/MdePkg/Include/Library/IfrSupportLib.h +++ b/MdePkg/Include/Library/IfrSupportLib.h @@ -434,6 +434,47 @@ CreateStringOpCode ( IN OUT EFI_HII_UPDATE_DATA *Data ) ; +/** + Construct for a buffer storage. + + @param ConfigRequest The Config request string. If set to NULL, all the + configurable elements will be extracted from BlockNameArray. + @param ConfigAltResp The returned . + @param Progress On return, points to a character in the Request. + @param Guid GUID of the buffer storage. + @param Name Name of the buffer storage. + @param DriverHandle The DriverHandle which is used to invoke HiiDatabase + protocol interface NewPackageList(). + @param BufferStorage Content of the buffer storage. + @param BufferStorageSize Length in bytes of the buffer storage. + @param BlockNameArray Array generated by VFR compiler. + @param NumberAltCfg Number of Default value array generated by VFR compiler. + The sequential input parameters will be number of + AltCfgId and DefaultValueArray pairs. When set to 0, + there will be no . + + retval EFI_OUT_OF_RESOURCES Run out of memory resource. + retval EFI_INVALID_PARAMETER ConfigAltResp is NULL. + retval EFI_SUCCESS Operation successful. + +**/ +EFI_STATUS +ConstructConfigAltResp ( + IN EFI_STRING ConfigRequest, OPTIONAL + OUT EFI_STRING *Progress, + OUT EFI_STRING *ConfigAltResp, + IN EFI_GUID *Guid, + IN CHAR16 *Name, + IN EFI_HANDLE *DriverHandle, + IN VOID *BufferStorage, + IN UINTN BufferStorageSize, + IN VOID *BlockNameArray, OPTIONAL + IN UINTN NumberAltCfg, + ... +//IN UINT16 AltCfgId, +//IN VOID *DefaultValueArray, + ) +; /** Converts the unicode character of the string from uppercase to lowercase. @@ -578,6 +619,25 @@ ConstructConfigHdr ( ; +/** + Determines if the Routing data (Guid and Name) is correct in . + + @param ConfigString Either or . + @param StorageGuid GUID of the storage. + @param StorageName Name of the stoarge. + + @retval TRUE Routing information is correct in ConfigString. + @retval FALSE Routing information is incorrect in ConfigString. + +**/ +BOOLEAN +IsConfigHdrMatch ( + IN EFI_STRING ConfigString, + IN EFI_GUID *StorageGuid, OPTIONAL + IN CHAR16 *StorageName OPTIONAL + ) +; + /** Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. diff --git a/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h b/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h index 9c0f2a2f7d..a26ac8d5b3 100644 --- a/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h +++ b/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h @@ -66,13 +66,13 @@ typedef struct { // #define EFI_HII_PACKAGE_TYPE_ALL 0x00 #define EFI_HII_PACKAGE_TYPE_GUID 0x01 -#define EFI_HII_PACKAGE_FORM 0x02 -#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x03 +#define EFI_HII_PACKAGE_FORMS 0x02 #define EFI_HII_PACKAGE_STRINGS 0x04 #define EFI_HII_PACKAGE_FONTS 0x05 #define EFI_HII_PACKAGE_IMAGES 0x06 #define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 #define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09 #define EFI_HII_PACKAGE_END 0xDF #define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 #define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF diff --git a/MdePkg/Library/UefiIfrSupportLib/UefiIfrForm.c b/MdePkg/Library/UefiIfrSupportLib/UefiIfrForm.c index 5613a50d3e..b6da34a6b3 100644 --- a/MdePkg/Library/UefiIfrSupportLib/UefiIfrForm.c +++ b/MdePkg/Library/UefiIfrSupportLib/UefiIfrForm.c @@ -295,6 +295,363 @@ IfrLibCreatePopUp ( return Status; } +/** + Extract block name from the array generated by VFR compiler. The name of + this array is "Vfr + + BlockName", e.g. "VfrMyIfrNVDataBlockName". + Format of this array is: + Array length | 4-bytes + Offset | 2-bytes + Width | 2-bytes + Offset | 2-bytes + Width | 2-bytes + ... ... + + @param Buffer Array generated by VFR compiler. + @param BlockName The returned + + @retval EFI_OUT_OF_RESOURCES Run out of memory resource. + @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL. + @retval EFI_SUCCESS Operation successful. + +**/ +EFI_STATUS +ExtractBlockName ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockName + ) + +{ + UINTN Index; + UINT32 Length; + UINT32 BlockNameNumber; + UINTN HexStringBufferLen; + CHAR16 *StringPtr; + + if ((Buffer == NULL) || (BlockName == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate number of Offset/Width pair + // + CopyMem (&Length, Buffer, sizeof (UINT32)); + BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2); + + // + // ::= &OFFSET=1234&WIDTH=1234 + // | 8 | 4 | 7 | 4 | + // + StringPtr = AllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16)); + *BlockName = StringPtr; + if (StringPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Buffer += sizeof (UINT32); + for (Index = 0; Index < BlockNameNumber; Index++) { + StrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + } + + return EFI_SUCCESS; +} + +/** + + Extract block config from the array generated by VFR compiler. The name of + this array is "Vfr + + Default4", e.g. "VfrMyIfrNVDataDefault0000". + + @param Buffer - Array generated by VFR compiler. + @param BlockConfig - The returned + + @retval EFI_OUT_OF_RESOURCES - Run out of memory resource. + @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL. + @retval EFI_SUCCESS - Operation successful. + +**/ +EFI_STATUS +ExtractBlockConfig ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockConfig + ) +{ + UINT32 Length; + UINT16 Width; + UINTN HexStringBufferLen; + CHAR16 *StringPtr; + UINT8 *BufferEnd; + CHAR16 *StringEnd; + EFI_STATUS Status; + + if ((Buffer == NULL) || (BlockConfig == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate length of AltResp string + // Format of Default value array is: + // Array length | 4-bytes + // Offset | 2-bytes + // Width | 2-bytes + // Value | Variable length + // Offset | 2-bytes + // Width | 2-bytes + // Value | Variable length + // ... ... + // When value is 1 byte in length, overhead of AltResp string will be maximum, + // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+ + // | 8 | 4 | 7 | 4 | 7 |2| + // so the maximum length of BlockConfig could be calculated as: + // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7 + // + CopyMem (&Length, Buffer, sizeof (UINT32)); + BufferEnd = Buffer + Length; + StringPtr = AllocatePool (Length * 7 * sizeof (CHAR16)); + *BlockConfig = StringPtr; + if (StringPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + StringEnd = StringPtr + (Length * 7); + + Buffer += sizeof (UINT32); + while (Buffer < BufferEnd) { + StrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + CopyMem (&Width, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (StringPtr, L"&VALUE="); + StringPtr += 7; + + HexStringBufferLen = StringEnd - StringPtr; + Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width); + if (EFI_ERROR (Status)) { + return Status; + } + Buffer += Width; + StringPtr += (Width * 2); + } + + return EFI_SUCCESS; +} + +/** + Construct for a buffer storage. + + @param ConfigRequest The Config request string. If set to NULL, all the + configurable elements will be extracted from BlockNameArray. + @param ConfigAltResp The returned . + @param Progress On return, points to a character in the Request. + @param Guid GUID of the buffer storage. + @param Name Name of the buffer storage. + @param DriverHandle The DriverHandle which is used to invoke HiiDatabase + protocol interface NewPackageList(). + @param BufferStorage Content of the buffer storage. + @param BufferStorageSize Length in bytes of the buffer storage. + @param BlockNameArray Array generated by VFR compiler. + @param NumberAltCfg Number of Default value array generated by VFR compiler. + The sequential input parameters will be number of + AltCfgId and DefaultValueArray pairs. When set to 0, + there will be no . + + retval EFI_OUT_OF_RESOURCES Run out of memory resource. + retval EFI_INVALID_PARAMETER ConfigAltResp is NULL. + retval EFI_SUCCESS Operation successful. + +**/ +EFI_STATUS +ConstructConfigAltResp ( + IN EFI_STRING ConfigRequest, OPTIONAL + OUT EFI_STRING *Progress, + OUT EFI_STRING *ConfigAltResp, + IN EFI_GUID *Guid, + IN CHAR16 *Name, + IN EFI_HANDLE *DriverHandle, + IN VOID *BufferStorage, + IN UINTN BufferStorageSize, + IN VOID *BlockNameArray, OPTIONAL + IN UINTN NumberAltCfg, + ... +//IN UINT16 AltCfgId, +//IN VOID *DefaultValueArray, + ) +{ + EFI_STATUS Status; + CHAR16 *ConfigHdr; + CHAR16 *BlockName; + CHAR16 *DescHdr; + CHAR16 *StringPtr; + CHAR16 **AltCfg; + UINT16 AltCfgId; + VOID *DefaultValueArray; + UINTN StrBufferLen; + EFI_STRING ConfigResp; + EFI_STRING TempStr; + VA_LIST Args; + UINTN AltRespLen; + UINTN Index; + BOOLEAN NeedFreeConfigRequest; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + UINTN Len; + + if (ConfigAltResp == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Construct : "GUID=...&NAME=...&PATH=..." + // + ConfigHdr = NULL; + StrBufferLen = 0; + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ConfigHdr = AllocateZeroPool (StrBufferLen); + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Construct + // + NeedFreeConfigRequest = FALSE; + if (ConfigRequest == NULL) { + // + // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray + // + Status = ExtractBlockName (BlockNameArray, &BlockName); + if (EFI_ERROR (Status)) { + return Status; + } + + Len = StrSize (ConfigHdr); + ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16)); + StrCpy (ConfigRequest, ConfigHdr); + StrCat (ConfigRequest, BlockName); + NeedFreeConfigRequest = TRUE; + } + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = HiiConfigRouting->BlockToConfig ( + HiiConfigRouting, + ConfigRequest, + BufferStorage, + BufferStorageSize, + &ConfigResp, + (Progress == NULL) ? &TempStr : Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Construct + // + DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16)); + StringPtr = DescHdr; + AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *)); + AltRespLen = 0; + VA_START (Args, NumberAltCfg); + for (Index = 0; Index < NumberAltCfg; Index++) { + AltCfgId = (UINT16) VA_ARG (Args, UINT16); + DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *); + + // + // '&' + // + AltRespLen += (StrLen (ConfigHdr) + 1); + + StringPtr = DescHdr + Index * 16; + StrCpy (StringPtr, L"&ALTCFG="); + AltRespLen += (8 + sizeof (UINT16) * 2); + + StrBufferLen = 5; + BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16)); + Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]); + if (EFI_ERROR (Status)) { + return Status; + } + AltRespLen += StrLen (AltCfg[Index]); + } + VA_END (Args); + + // + // Generate the final + // + StrBufferLen = (StrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16); + TempStr = AllocateZeroPool (StrBufferLen); + *ConfigAltResp = TempStr; + if (TempStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // ::= ['&' ]* + // + StrCpy (TempStr, ConfigResp); + for (Index = 0; Index < NumberAltCfg; Index++) { + StrCat (TempStr, L"&"); + StrCat (TempStr, ConfigHdr); + StrCat (TempStr, DescHdr + Index * 16); + StrCat (TempStr, AltCfg[Index]); + + gBS->FreePool (AltCfg[Index]); + } + + if (NeedFreeConfigRequest) { + gBS->FreePool (ConfigRequest); + } + gBS->FreePool (ConfigHdr); + gBS->FreePool (ConfigResp); + gBS->FreePool (DescHdr); + gBS->FreePool (AltCfg); + + return EFI_SUCCESS; +} + /** Swap bytes in the buffer. This is a internal function. @@ -417,7 +774,7 @@ HexStringToBufInReverseOrder ( ConvertedStrLen = 0; Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen); if (!EFI_ERROR (Status)) { - SwapBuffer (Buffer, ConvertedStrLen); + SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2); } return Status; @@ -642,6 +999,100 @@ ConstructConfigHdr ( return EFI_SUCCESS; } +/** + Determines if the Routing data (Guid and Name) is correct in . + + @param ConfigString Either or . + @param StorageGuid GUID of the storage. + @param StorageName Name of the stoarge. + + @retval TRUE Routing information is correct in ConfigString. + @retval FALSE Routing information is incorrect in ConfigString. + +**/ +BOOLEAN +IsConfigHdrMatch ( + IN EFI_STRING ConfigString, + IN EFI_GUID *StorageGuid, OPTIONAL + IN CHAR16 *StorageName OPTIONAL + ) +{ + EFI_STATUS Status; + BOOLEAN Match; + EFI_GUID Guid; + CHAR16 *Name; + CHAR16 *StrPtr; + UINTN BufferSize; + + // + // ::= + // GUID=32&NAME=NameStrLen&PATH=DevicePathStrLen + // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | + // + if (StrLen (ConfigString) <= (5 + 32 + 6)) { + return FALSE; + } + + // + // Compare GUID + // + if (StorageGuid != NULL) { + + StrPtr = ConfigString + 5 + 32; + if (*StrPtr != L'&') { + return FALSE; + } + *StrPtr = L'\0'; + + BufferSize = sizeof (EFI_GUID); + Status = HexStringToBufInReverseOrder ( + (UINT8 *) &Guid, + &BufferSize, + ConfigString + 5 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!CompareGuid (&Guid, StorageGuid)) { + return FALSE; + } + } + + // + // Compare Name + // + Match = TRUE; + if (StorageName != NULL) { + StrPtr = ConfigString + 5 + 32 + 6; + while (*StrPtr != L'\0' && *StrPtr != L'&') { + StrPtr++; + } + if (*StrPtr != L'&') { + return FALSE; + } + + *StrPtr = L'\0'; + BufferSize = (((UINTN) StrPtr) - ((UINTN) &ConfigString[5 + 32 + 6])) / 4 + sizeof (CHAR16); + Name = AllocatePool (BufferSize); + ASSERT (Name != NULL); + Status = ConfigStringToUnicode ( + Name, + &BufferSize, + ConfigString + 5 + 32 + 6 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) { + Match = FALSE; + } + gBS->FreePool (Name); + } + + return Match; +} /** Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. @@ -935,8 +1386,8 @@ SetBrowserData ( &BufferSize, StringPtr, FALSE, - NULL, - NULL + VariableGuid, + VariableName ); FreePool (ConfigRequest); return Status;