IN OUT EFI_HII_UPDATE_DATA *Data\r
)\r
;\r
+/**\r
+ Construct <ConfigAltResp> for a buffer storage.\r
+\r
+ @param ConfigRequest The Config request string. If set to NULL, all the\r
+ configurable elements will be extracted from BlockNameArray.\r
+ @param ConfigAltResp The returned <ConfigAltResp>.\r
+ @param Progress On return, points to a character in the Request.\r
+ @param Guid GUID of the buffer storage.\r
+ @param Name Name of the buffer storage.\r
+ @param DriverHandle The DriverHandle which is used to invoke HiiDatabase\r
+ protocol interface NewPackageList().\r
+ @param BufferStorage Content of the buffer storage.\r
+ @param BufferStorageSize Length in bytes of the buffer storage.\r
+ @param BlockNameArray Array generated by VFR compiler.\r
+ @param NumberAltCfg Number of Default value array generated by VFR compiler.\r
+ The sequential input parameters will be number of\r
+ AltCfgId and DefaultValueArray pairs. When set to 0,\r
+ there will be no <AltResp>.\r
+\r
+ retval EFI_OUT_OF_RESOURCES Run out of memory resource.\r
+ retval EFI_INVALID_PARAMETER ConfigAltResp is NULL.\r
+ retval EFI_SUCCESS Operation successful.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructConfigAltResp (\r
+ IN EFI_STRING ConfigRequest, OPTIONAL\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *ConfigAltResp,\r
+ IN EFI_GUID *Guid,\r
+ IN CHAR16 *Name,\r
+ IN EFI_HANDLE *DriverHandle,\r
+ IN VOID *BufferStorage,\r
+ IN UINTN BufferStorageSize,\r
+ IN VOID *BlockNameArray, OPTIONAL\r
+ IN UINTN NumberAltCfg,\r
+ ...\r
+//IN UINT16 AltCfgId,\r
+//IN VOID *DefaultValueArray,\r
+ )\r
+;\r
\r
/**\r
Converts the unicode character of the string from uppercase to lowercase.\r
\r
;\r
\r
+/**\r
+ Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.\r
+\r
+ @param ConfigString Either <ConfigRequest> or <ConfigResp>.\r
+ @param StorageGuid GUID of the storage.\r
+ @param StorageName Name of the stoarge.\r
+\r
+ @retval TRUE Routing information is correct in ConfigString.\r
+ @retval FALSE Routing information is incorrect in ConfigString.\r
+\r
+**/\r
+BOOLEAN\r
+IsConfigHdrMatch (\r
+ IN EFI_STRING ConfigString,\r
+ IN EFI_GUID *StorageGuid, OPTIONAL\r
+ IN CHAR16 *StorageName OPTIONAL\r
+ )\r
+;\r
+\r
/**\r
Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
\r
return Status;\r
}\r
\r
+/**\r
+ Extract block name from the array generated by VFR compiler. The name of\r
+ this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName".\r
+ Format of this array is:\r
+ Array length | 4-bytes\r
+ Offset | 2-bytes\r
+ Width | 2-bytes\r
+ Offset | 2-bytes\r
+ Width | 2-bytes\r
+ ... ...\r
+\r
+ @param Buffer Array generated by VFR compiler.\r
+ @param BlockName The returned <BlockName>\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Run out of memory resource.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL.\r
+ @retval EFI_SUCCESS Operation successful.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractBlockName (\r
+ IN UINT8 *Buffer,\r
+ OUT CHAR16 **BlockName\r
+ )\r
+\r
+{\r
+ UINTN Index;\r
+ UINT32 Length;\r
+ UINT32 BlockNameNumber;\r
+ UINTN HexStringBufferLen;\r
+ CHAR16 *StringPtr;\r
+\r
+ if ((Buffer == NULL) || (BlockName == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Calculate number of Offset/Width pair\r
+ //\r
+ CopyMem (&Length, Buffer, sizeof (UINT32));\r
+ BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2);\r
+\r
+ //\r
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
+ // | 8 | 4 | 7 | 4 |\r
+ //\r
+ StringPtr = AllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16));\r
+ *BlockName = StringPtr;\r
+ if (StringPtr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Buffer += sizeof (UINT32);\r
+ for (Index = 0; Index < BlockNameNumber; Index++) {\r
+ StrCpy (StringPtr, L"&OFFSET=");\r
+ StringPtr += 8;\r
+\r
+ HexStringBufferLen = 5;\r
+ BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
+ Buffer += sizeof (UINT16);\r
+ StringPtr += 4;\r
+\r
+ StrCpy (StringPtr, L"&WIDTH=");\r
+ StringPtr += 7;\r
+\r
+ HexStringBufferLen = 5;\r
+ BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
+ Buffer += sizeof (UINT16);\r
+ StringPtr += 4;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Extract block config from the array generated by VFR compiler. The name of\r
+ this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000".\r
+\r
+ @param Buffer - Array generated by VFR compiler.\r
+ @param BlockConfig - The returned <BlockConfig>\r
+\r
+ @retval EFI_OUT_OF_RESOURCES - Run out of memory resource.\r
+ @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL.\r
+ @retval EFI_SUCCESS - Operation successful.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractBlockConfig (\r
+ IN UINT8 *Buffer,\r
+ OUT CHAR16 **BlockConfig\r
+ )\r
+{\r
+ UINT32 Length;\r
+ UINT16 Width;\r
+ UINTN HexStringBufferLen;\r
+ CHAR16 *StringPtr;\r
+ UINT8 *BufferEnd;\r
+ CHAR16 *StringEnd;\r
+ EFI_STATUS Status;\r
+\r
+ if ((Buffer == NULL) || (BlockConfig == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Calculate length of AltResp string\r
+ // Format of Default value array is:\r
+ // Array length | 4-bytes\r
+ // Offset | 2-bytes\r
+ // Width | 2-bytes\r
+ // Value | Variable length\r
+ // Offset | 2-bytes\r
+ // Width | 2-bytes\r
+ // Value | Variable length\r
+ // ... ...\r
+ // When value is 1 byte in length, overhead of AltResp string will be maximum,\r
+ // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+\r
+ // | 8 | 4 | 7 | 4 | 7 |2|\r
+ // so the maximum length of BlockConfig could be calculated as:\r
+ // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7\r
+ //\r
+ CopyMem (&Length, Buffer, sizeof (UINT32));\r
+ BufferEnd = Buffer + Length;\r
+ StringPtr = AllocatePool (Length * 7 * sizeof (CHAR16));\r
+ *BlockConfig = StringPtr;\r
+ if (StringPtr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StringEnd = StringPtr + (Length * 7);\r
+\r
+ Buffer += sizeof (UINT32);\r
+ while (Buffer < BufferEnd) {\r
+ StrCpy (StringPtr, L"&OFFSET=");\r
+ StringPtr += 8;\r
+\r
+ HexStringBufferLen = 5;\r
+ BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
+ Buffer += sizeof (UINT16);\r
+ StringPtr += 4;\r
+\r
+ StrCpy (StringPtr, L"&WIDTH=");\r
+ StringPtr += 7;\r
+\r
+ HexStringBufferLen = 5;\r
+ BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16));\r
+ CopyMem (&Width, Buffer, sizeof (UINT16));\r
+ Buffer += sizeof (UINT16);\r
+ StringPtr += 4;\r
+\r
+ StrCpy (StringPtr, L"&VALUE=");\r
+ StringPtr += 7;\r
+\r
+ HexStringBufferLen = StringEnd - StringPtr;\r
+ Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Buffer += Width;\r
+ StringPtr += (Width * 2);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Construct <ConfigAltResp> for a buffer storage.\r
+\r
+ @param ConfigRequest The Config request string. If set to NULL, all the\r
+ configurable elements will be extracted from BlockNameArray.\r
+ @param ConfigAltResp The returned <ConfigAltResp>.\r
+ @param Progress On return, points to a character in the Request.\r
+ @param Guid GUID of the buffer storage.\r
+ @param Name Name of the buffer storage.\r
+ @param DriverHandle The DriverHandle which is used to invoke HiiDatabase\r
+ protocol interface NewPackageList().\r
+ @param BufferStorage Content of the buffer storage.\r
+ @param BufferStorageSize Length in bytes of the buffer storage.\r
+ @param BlockNameArray Array generated by VFR compiler.\r
+ @param NumberAltCfg Number of Default value array generated by VFR compiler.\r
+ The sequential input parameters will be number of\r
+ AltCfgId and DefaultValueArray pairs. When set to 0,\r
+ there will be no <AltResp>.\r
+\r
+ retval EFI_OUT_OF_RESOURCES Run out of memory resource.\r
+ retval EFI_INVALID_PARAMETER ConfigAltResp is NULL.\r
+ retval EFI_SUCCESS Operation successful.\r
+\r
+**/\r
+EFI_STATUS\r
+ConstructConfigAltResp (\r
+ IN EFI_STRING ConfigRequest, OPTIONAL\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *ConfigAltResp,\r
+ IN EFI_GUID *Guid,\r
+ IN CHAR16 *Name,\r
+ IN EFI_HANDLE *DriverHandle,\r
+ IN VOID *BufferStorage,\r
+ IN UINTN BufferStorageSize,\r
+ IN VOID *BlockNameArray, OPTIONAL\r
+ IN UINTN NumberAltCfg,\r
+ ...\r
+//IN UINT16 AltCfgId,\r
+//IN VOID *DefaultValueArray,\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *ConfigHdr;\r
+ CHAR16 *BlockName;\r
+ CHAR16 *DescHdr;\r
+ CHAR16 *StringPtr;\r
+ CHAR16 **AltCfg;\r
+ UINT16 AltCfgId;\r
+ VOID *DefaultValueArray;\r
+ UINTN StrBufferLen;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING TempStr;\r
+ VA_LIST Args;\r
+ UINTN AltRespLen;\r
+ UINTN Index;\r
+ BOOLEAN NeedFreeConfigRequest;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+ UINTN Len;\r
+\r
+ if (ConfigAltResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
+ //\r
+ ConfigHdr = NULL;\r
+ StrBufferLen = 0;\r
+ Status = ConstructConfigHdr (\r
+ ConfigHdr,\r
+ &StrBufferLen,\r
+ Guid,\r
+ Name,\r
+ DriverHandle\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ ConfigHdr = AllocateZeroPool (StrBufferLen);\r
+ Status = ConstructConfigHdr (\r
+ ConfigHdr,\r
+ &StrBufferLen,\r
+ Guid,\r
+ Name,\r
+ DriverHandle\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Construct <ConfigResp>\r
+ //\r
+ NeedFreeConfigRequest = FALSE;\r
+ if (ConfigRequest == NULL) {\r
+ //\r
+ // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray\r
+ //\r
+ Status = ExtractBlockName (BlockNameArray, &BlockName);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ Len = StrSize (ConfigHdr);\r
+ ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16));\r
+ StrCpy (ConfigRequest, ConfigHdr);\r
+ StrCat (ConfigRequest, BlockName);\r
+ NeedFreeConfigRequest = TRUE;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = HiiConfigRouting->BlockToConfig (\r
+ HiiConfigRouting,\r
+ ConfigRequest,\r
+ BufferStorage,\r
+ BufferStorageSize,\r
+ &ConfigResp,\r
+ (Progress == NULL) ? &TempStr : Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Construct <AltResp>\r
+ //\r
+ DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16));\r
+ StringPtr = DescHdr;\r
+ AltCfg = AllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *));\r
+ AltRespLen = 0;\r
+ VA_START (Args, NumberAltCfg);\r
+ for (Index = 0; Index < NumberAltCfg; Index++) {\r
+ AltCfgId = (UINT16) VA_ARG (Args, UINT16);\r
+ DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *);\r
+\r
+ //\r
+ // '&' <ConfigHdr>\r
+ //\r
+ AltRespLen += (StrLen (ConfigHdr) + 1);\r
+\r
+ StringPtr = DescHdr + Index * 16;\r
+ StrCpy (StringPtr, L"&ALTCFG=");\r
+ AltRespLen += (8 + sizeof (UINT16) * 2);\r
+\r
+ StrBufferLen = 5;\r
+ BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16));\r
+ Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ AltRespLen += StrLen (AltCfg[Index]);\r
+ }\r
+ VA_END (Args);\r
+\r
+ //\r
+ // Generate the final <ConfigAltResp>\r
+ //\r
+ StrBufferLen = (StrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16);\r
+ TempStr = AllocateZeroPool (StrBufferLen);\r
+ *ConfigAltResp = TempStr;\r
+ if (TempStr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]*\r
+ //\r
+ StrCpy (TempStr, ConfigResp);\r
+ for (Index = 0; Index < NumberAltCfg; Index++) {\r
+ StrCat (TempStr, L"&");\r
+ StrCat (TempStr, ConfigHdr);\r
+ StrCat (TempStr, DescHdr + Index * 16);\r
+ StrCat (TempStr, AltCfg[Index]);\r
+\r
+ gBS->FreePool (AltCfg[Index]);\r
+ }\r
+\r
+ if (NeedFreeConfigRequest) {\r
+ gBS->FreePool (ConfigRequest);\r
+ }\r
+ gBS->FreePool (ConfigHdr);\r
+ gBS->FreePool (ConfigResp);\r
+ gBS->FreePool (DescHdr);\r
+ gBS->FreePool (AltCfg);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Swap bytes in the buffer. This is a internal function.\r
\r
ConvertedStrLen = 0;\r
Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);\r
if (!EFI_ERROR (Status)) {\r
- SwapBuffer (Buffer, ConvertedStrLen);\r
+ SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2);\r
}\r
\r
return Status;\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>.\r
+\r
+ @param ConfigString Either <ConfigRequest> or <ConfigResp>.\r
+ @param StorageGuid GUID of the storage.\r
+ @param StorageName Name of the stoarge.\r
+\r
+ @retval TRUE Routing information is correct in ConfigString.\r
+ @retval FALSE Routing information is incorrect in ConfigString.\r
+\r
+**/\r
+BOOLEAN\r
+IsConfigHdrMatch (\r
+ IN EFI_STRING ConfigString,\r
+ IN EFI_GUID *StorageGuid, OPTIONAL\r
+ IN CHAR16 *StorageName OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Match;\r
+ EFI_GUID Guid;\r
+ CHAR16 *Name;\r
+ CHAR16 *StrPtr;\r
+ UINTN BufferSize;\r
+\r
+ //\r
+ // <ConfigHdr> ::=\r
+ // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>\r
+ // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 |\r
+ //\r
+ if (StrLen (ConfigString) <= (5 + 32 + 6)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Compare GUID\r
+ //\r
+ if (StorageGuid != NULL) {\r
+\r
+ StrPtr = ConfigString + 5 + 32;\r
+ if (*StrPtr != L'&') {\r
+ return FALSE;\r
+ }\r
+ *StrPtr = L'\0';\r
+\r
+ BufferSize = sizeof (EFI_GUID);\r
+ Status = HexStringToBufInReverseOrder (\r
+ (UINT8 *) &Guid,\r
+ &BufferSize,\r
+ ConfigString + 5\r
+ );\r
+ *StrPtr = L'&';\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (!CompareGuid (&Guid, StorageGuid)) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Compare Name\r
+ //\r
+ Match = TRUE;\r
+ if (StorageName != NULL) {\r
+ StrPtr = ConfigString + 5 + 32 + 6;\r
+ while (*StrPtr != L'\0' && *StrPtr != L'&') {\r
+ StrPtr++;\r
+ }\r
+ if (*StrPtr != L'&') {\r
+ return FALSE;\r
+ }\r
+\r
+ *StrPtr = L'\0';\r
+ BufferSize = (((UINTN) StrPtr) - ((UINTN) &ConfigString[5 + 32 + 6])) / 4 + sizeof (CHAR16);\r
+ Name = AllocatePool (BufferSize);\r
+ ASSERT (Name != NULL);\r
+ Status = ConfigStringToUnicode (\r
+ Name,\r
+ &BufferSize,\r
+ ConfigString + 5 + 32 + 6\r
+ );\r
+ *StrPtr = L'&';\r
+\r
+ if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) {\r
+ Match = FALSE;\r
+ }\r
+ gBS->FreePool (Name);\r
+ }\r
+\r
+ return Match;\r
+}\r
\r
/**\r
Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.\r
&BufferSize,\r
StringPtr,\r
FALSE,\r
- NULL,\r
- NULL\r
+ VariableGuid,\r
+ VariableName\r
);\r
FreePool (ConfigRequest);\r
return Status;\r