--- /dev/null
+/**@file\r
+ This file contains the form processing code to the HII database.\r
+ \r
+Copyright (c) 2006 - 2007 Intel Corporation. <BR>\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
+**/\r
+\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "HiiDatabase.h"\r
+\r
+STATIC\r
+CHAR16*\r
+Ascii2Unicode (\r
+ OUT CHAR16 *UnicodeStr,\r
+ IN CHAR8 *AsciiStr\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+\r
+ This function converts ASCII string to Unicode string.\r
+ \r
+ Arguments:\r
+\r
+ UnicodeStr - NULL terminated Unicode output string.\r
+ AsciieStr - NULL terminated ASCII input string.\r
+ \r
+ Returns: \r
+\r
+ Start of the Unicode ouput string.\r
+ \r
+--*/\r
+\r
+{\r
+ CHAR16 *Str = UnicodeStr; \r
+ while (TRUE) {\r
+ *(UnicodeStr++) = (CHAR16) *AsciiStr;\r
+ if (*(AsciiStr++) == '\0') {\r
+ return Str;\r
+ }\r
+ }\r
+}\r
+\r
+STATIC\r
+CHAR8*\r
+Unicode2Ascii (\r
+ OUT CHAR8 *AsciiStr,\r
+ IN CHAR16 *UnicodeStr\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+\r
+ This function converts Unicode string to ASCII string.\r
+ \r
+ Arguments:\r
+\r
+ AsciieStr - NULL terminated ASCII output string.\r
+ UnicodeStr - NULL terminated Unicode input string.\r
+ \r
+ Returns: \r
+\r
+ Start of the ASCII ouput string.\r
+ \r
+--*/\r
+\r
+{\r
+ CHAR8 *Str = AsciiStr; \r
+ while (TRUE) {\r
+ *(AsciiStr++) = (CHAR8) *UnicodeStr;\r
+ if (*(UnicodeStr++) == '\0') {\r
+ return Str;\r
+ }\r
+ }\r
+}\r
+\r
+STATIC\r
+VOID\r
+ExtractDevicePathData (\r
+ IN EFI_HII_DATA_TABLE *DataTable,\r
+ IN UINT8 *IfrData,\r
+ IN OUT UINT8 **ExportBufferPtr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ UINT8 *ExportBuffer;\r
+\r
+ ExportBuffer = *ExportBufferPtr;\r
+\r
+ //\r
+ // BUGBUG - don't have devicepath data yet, setting dummy value\r
+ //\r
+ DataTable++;\r
+ ExportBuffer = (UINT8 *) DataTable;\r
+ ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH;\r
+ ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
+\r
+ //\r
+ // BUGBUG - part of hack - skip the Device Path Pack.....place some data\r
+ //\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK);\r
+\r
+ ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type = EFI_END_ENTIRE_DEVICE_PATH;\r
+ ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
+\r
+ //\r
+ // BUGBUG - still part of hack....\r
+ //\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+ *ExportBufferPtr = ExportBuffer;\r
+}\r
+\r
+STATIC\r
+VOID\r
+ExtractVariableData (\r
+ IN OUT EFI_HII_DATA_TABLE *DataTable,\r
+ IN UINT8 *IfrData,\r
+ IN OUT UINT8 **ExportBufferPtr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function extract the EFI_HII_VARIABLE_PACK portion from the \r
+ each of the EFI_HII_PACKAGE_INSTANCE in HII handle database.\r
+ \r
+Arguments:\r
+\r
+ DataTable - On input, this parameter point to the EFI_HII_DATA_TABLE structure\r
+ of the final data buffer for the EFI_HII_EXPORT interface. This function\r
+ update the NumberOfVariableData attribute.\r
+ IfrData - It points to a staring address of a EFI_HII_IFR_PACK structure.\r
+ ExportBufferPtr - On input, it points the starting address of the data buffer to \r
+ host the variable pack. On output, it is the starting address\r
+ of data buffer for the next extraction operation.\r
+Returns: \r
+\r
+ VOID\r
+ \r
+--*/\r
+{\r
+ EFI_HII_VARIABLE_PACK *VariableContents;\r
+ UINT8 *ExportBuffer;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN TempValue;\r
+ UINTN TempValue2;\r
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;\r
+ EFI_PHYSICAL_ADDRESS CallbackHandle;\r
+ EFI_STATUS Status;\r
+ CHAR16 *String;\r
+\r
+ FormCallback = NULL;\r
+ CallbackHandle = 0;\r
+ ExportBuffer = *ExportBufferPtr;\r
+\r
+ for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+ VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
+\r
+ switch (IfrData[Index]) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+ TempValue = EFI_HII_VARIABLE;\r
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
+ CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
+\r
+ //\r
+ // If the variable has 0 size, do not process it\r
+ //\r
+ if (TempValue == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Add the size of the variable pack overhead. Later, will also add the size of the\r
+ // name of the variable.\r
+ //\r
+ TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);\r
+\r
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
+ CopyMem (\r
+ &CallbackHandle,\r
+ &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle,\r
+ sizeof (EFI_PHYSICAL_ADDRESS)\r
+ );\r
+ if (CallbackHandle != 0) {\r
+ Status = gBS->HandleProtocol (\r
+ (EFI_HANDLE) (UINTN) CallbackHandle,\r
+ &gEfiFormCallbackProtocolGuid,\r
+ (VOID *) &FormCallback\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ //\r
+ // Since we have a "Setup" variable that wasn't specified by a variable op-code\r
+ // it will have a VariableId of 0. All other variable op-codes will have a designation\r
+ // of VariableId 1+\r
+ //\r
+ TempValue = 0;\r
+ CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16));\r
+ CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID));\r
+ TempValue = sizeof (SETUP_MAP_NAME);\r
+ CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));\r
+\r
+ //\r
+ // Add the size of the name to the Header Length\r
+ //\r
+ TempValue2 = 0;\r
+ CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));\r
+ TempValue2 = TempValue + TempValue2;\r
+ CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
+ CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME));\r
+ ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME);\r
+\r
+ CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));\r
+\r
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
+ Status = FormCallback->NvRead (\r
+ FormCallback,\r
+ (CHAR16 *) SETUP_MAP_NAME,\r
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
+ NULL,\r
+ &TempValue,\r
+ ExportBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ Status = gRT->GetVariable (\r
+ (CHAR16 *) SETUP_MAP_NAME,\r
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
+ NULL,\r
+ &TempValue,\r
+ ExportBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);\r
+ DataTable->NumberOfVariableData++;\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_OP:\r
+ TempValue = EFI_HII_VARIABLE;\r
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
+ CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));\r
+\r
+ //\r
+ // If the variable has 0 size, do not process it\r
+ //\r
+ if (TempValue == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Add the size of the variable pack overhead. Later, will also add the size of the\r
+ // name of the variable.\r
+ //\r
+ TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);\r
+\r
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
+ CopyMem (&VariableContents->VariableId, &((EFI_IFR_VARSTORE *) &IfrData[Index])->VarId, sizeof (UINT16));\r
+ CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Guid, sizeof (EFI_GUID));\r
+ TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &IfrData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);\r
+ TempValue = TempValue * 2;\r
+ CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));\r
+\r
+ //\r
+ // Add the size of the name to the Header Length\r
+ //\r
+ TempValue2 = 0;\r
+ CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));\r
+ TempValue2 = TempValue + TempValue2;\r
+ CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
+ String = (CHAR16 *) ExportBuffer;\r
+ for (Index2 = 0; Index2 < TempValue / 2; Index2++) {\r
+ ExportBuffer[Index2 * 2] = IfrData[Index + sizeof (EFI_IFR_VARSTORE) + Index2];\r
+ ExportBuffer[Index2 * 2 + 1] = 0;\r
+ }\r
+\r
+ ExportBuffer = ExportBuffer + TempValue;\r
+\r
+ CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));\r
+\r
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {\r
+ Status = FormCallback->NvRead (\r
+ FormCallback,\r
+ String,\r
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
+ NULL,\r
+ &TempValue,\r
+ ExportBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ Status = gRT->GetVariable (\r
+ String,\r
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,\r
+ NULL,\r
+ &TempValue,\r
+ ExportBuffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);\r
+ DataTable->NumberOfVariableData++;\r
+ break;\r
+ }\r
+\r
+ Index = IfrData[Index + 1] + Index;\r
+ }\r
+ //\r
+ // If we have added a variable pack, add a dummy empty one to signify the end\r
+ //\r
+ if (ExportBuffer != *ExportBufferPtr) {\r
+ VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;\r
+ TempValue = EFI_HII_VARIABLE;\r
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));\r
+ TempValue = sizeof (EFI_HII_VARIABLE_PACK);\r
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);\r
+ }\r
+\r
+ *ExportBufferPtr = ExportBuffer;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiExportDatabase (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function allows a program to extract a form or form package that has \r
+ previously been registered with the EFI HII database.\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_IFR_PACK *FormPack;\r
+ UINT8 *RawData;\r
+ UINT8 *ExportBuffer;\r
+ EFI_HII_EXPORT_TABLE *ExportTable;\r
+ EFI_HII_DATA_TABLE *DataTable;\r
+ BOOLEAN VariableExist;\r
+ UINT16 NumberOfHiiDataTables;\r
+ UINTN SizeNeeded;\r
+ UINTN Index;\r
+ UINTN VariableSize;\r
+ UINTN TempValue;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+\r
+ HandleDatabase = HiiData->DatabaseHead;\r
+\r
+ FormPack = NULL;\r
+ RawData = NULL;\r
+ PackageInstance = NULL;\r
+ NumberOfHiiDataTables = 0;\r
+ VariableSize = 0;\r
+ TempValue = 0;\r
+ SizeNeeded = sizeof (EFI_HII_EXPORT_TABLE);\r
+\r
+ //\r
+ // How many total tables are there?\r
+ //\r
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
+ if ((Handle != 0) && (Handle != HandleDatabase->Handle)) {\r
+ continue;\r
+ }\r
+\r
+ VariableExist = FALSE;\r
+ NumberOfHiiDataTables++;\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ if (PackageInstance == NULL) {\r
+ continue;\r
+ }\r
+ //\r
+ // Extract Size of Export Package\r
+ //\r
+ SizeNeeded = SizeNeeded + PackageInstance->IfrSize \r
+ + PackageInstance->StringSize\r
+ + sizeof (EFI_HII_DATA_TABLE)\r
+ + sizeof (EFI_HII_DEVICE_PATH_PACK);\r
+\r
+ //\r
+ // BUGBUG We aren't inserting Device path data yet\r
+ //\r
+ SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+\r
+ //\r
+ // Extract Size of Variable Data\r
+ //\r
+ if (PackageInstance->IfrSize > 0) {\r
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
+ } else {\r
+ //\r
+ // No IFR? No variable information\r
+ //\r
+ continue;\r
+ }\r
+\r
+ RawData = (UINT8 *) FormPack;\r
+\r
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+ switch (RawData[Index]) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+ CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16));\r
+ SizeNeeded = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK);\r
+ VariableExist = TRUE;\r
+ break;\r
+\r
+ case EFI_IFR_VARSTORE_OP:\r
+ CopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16));\r
+ SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK);\r
+ //\r
+ // We will be expanding the stored ASCII name to a Unicode string. This will cause some memory overhead\r
+ // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another\r
+ // instance of it. Essentially, 2 ASCII strings == 1 Unicode string in size.\r
+ //\r
+ TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);\r
+ SizeNeeded = SizeNeeded + TempValue * 2;\r
+ VariableExist = TRUE;\r
+ break;\r
+ }\r
+\r
+ Index = RawData[Index + 1] + Index;\r
+ }\r
+ //\r
+ // If a variable exists for this handle, add an additional variable pack overhead to\r
+ // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs\r
+ //\r
+ if (VariableExist) {\r
+ SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK);\r
+ }\r
+ }\r
+\r
+ if (SizeNeeded > *BufferSize) {\r
+ *BufferSize = SizeNeeded;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // Zero out the incoming buffer\r
+ //\r
+ ZeroMem (Buffer, *BufferSize);\r
+\r
+ //\r
+ // Cast the Buffer to EFI_HII_EXPORT_TABLE\r
+ //\r
+ ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer;\r
+\r
+ //\r
+ // Set the Revision for the Export Table\r
+ //\r
+ CopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID));\r
+\r
+ ExportBuffer = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE));\r
+ HandleDatabase = HiiData->DatabaseHead;\r
+\r
+ //\r
+ // Check numeric value against the head of the database\r
+ //\r
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
+ DataTable = (EFI_HII_DATA_TABLE *) ExportBuffer;\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ //\r
+ // If not asking for a specific handle, export the entire database\r
+ //\r
+ if (Handle == 0) {\r
+ ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;\r
+ CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));\r
+ DataTable->HiiHandle = PackageInstance->Handle;\r
+ DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE));\r
+\r
+ //\r
+ // Start Dumping DevicePath\r
+ //\r
+ ExtractDevicePathData (DataTable, RawData, &ExportBuffer);\r
+\r
+ if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) {\r
+ //\r
+ // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse\r
+ //\r
+ DataTable->DevicePathOffset = 0;\r
+ }\r
+\r
+ DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ if (PackageInstance->IfrSize > 0) {\r
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
+\r
+ RawData = (UINT8 *) FormPack;\r
+ TempValue = 0;\r
+\r
+ //\r
+ // Start dumping the Variable Data\r
+ //\r
+ ExtractVariableData (DataTable, RawData, &ExportBuffer);\r
+ DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {\r
+ DataTable->VariableDataOffset = 0;\r
+ }\r
+ //\r
+ // Start dumping the IFR data (Note: It is in an IFR PACK)\r
+ //\r
+ CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);\r
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);\r
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ //\r
+ // Start dumping the String data (Note: It is in a String PACK)\r
+ //\r
+ if (PackageInstance->StringSize > 0) {\r
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
+\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ for (; TempValue != 0;) {\r
+ DataTable->NumberOfLanguages++;\r
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
+ } else {\r
+ DataTable->StringDataOffset = 0;\r
+ }\r
+ } else {\r
+ //\r
+ // No IFR? No variable information. If Offset is 0, means there is none. (Hmm - this might be prunable - no strings to export if no IFR - we always have a stub)\r
+ //\r
+ DataTable->VariableDataOffset = 0;\r
+ DataTable->IfrDataOffset = 0;\r
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ //\r
+ // Start dumping the String data - NOTE: It is in String Pack form\r
+ //\r
+ if (PackageInstance->StringSize > 0) {\r
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
+\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ for (; TempValue != 0;) {\r
+ DataTable->NumberOfLanguages++;\r
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
+ } else {\r
+ DataTable->StringDataOffset = 0;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Match the numeric value with the database entry - if matched, extract PackageInstance\r
+ //\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;\r
+ DataTable->HiiHandle = PackageInstance->Handle;\r
+ CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));\r
+\r
+ //\r
+ // Start Dumping DevicePath\r
+ //\r
+ ExtractDevicePathData (DataTable, RawData, &ExportBuffer);\r
+ DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ if (PackageInstance->IfrSize > 0) {\r
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
+\r
+ RawData = (UINT8 *) FormPack;\r
+ TempValue = 0;\r
+\r
+ //\r
+ // Start dumping the Variable Data\r
+ //\r
+ ExtractVariableData (DataTable, RawData, &ExportBuffer);\r
+ DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {\r
+ DataTable->VariableDataOffset = 0;\r
+ }\r
+ //\r
+ // Start dumping the IFR data\r
+ //\r
+ CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);\r
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);\r
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ //\r
+ // Start dumping the String data - NOTE: It is in String Pack form\r
+ //\r
+ if (PackageInstance->StringSize > 0) {\r
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
+\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ for (; TempValue != 0;) {\r
+ DataTable->NumberOfLanguages++;\r
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
+ } else {\r
+ DataTable->StringDataOffset = 0;\r
+ }\r
+ } else {\r
+ //\r
+ // No IFR? No variable information. If Offset is 0, means there is none.\r
+ //\r
+ DataTable->VariableDataOffset = 0;\r
+ DataTable->IfrDataOffset = 0;\r
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));\r
+\r
+ //\r
+ // Start dumping the String data - Note: It is in String Pack form\r
+ //\r
+ if (PackageInstance->StringSize > 0) {\r
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);\r
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);\r
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);\r
+\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ for (; TempValue != 0;) {\r
+ DataTable->NumberOfLanguages++;\r
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;\r
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);\r
+ } else {\r
+ DataTable->StringDataOffset = 0;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetForms (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_FORM_ID FormId,\r
+ IN OUT UINTN *BufferLengthTemp,\r
+ OUT UINT8 *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function allows a program to extract a form or form package that has \r
+ previously been registered with the EFI HII database.\r
+\r
+Arguments:\r
+ This - A pointer to the EFI_HII_PROTOCOL instance.\r
+ \r
+ Handle - Handle on which the form resides. Type EFI_HII_HANDLE is defined in \r
+ EFI_HII_PROTOCOL.NewPack() in the Packages section.\r
+ \r
+ FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.\r
+ Type EFI_FORM_ID is defined in "Related Definitions" below.\r
+ \r
+ BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if\r
+ the length was sufficient and, if it was not, the length that is required to fit the\r
+ requested form(s).\r
+ \r
+ Buffer - The buffer designed to receive the form(s).\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - Buffer filled with the requested forms. BufferLength\r
+ was updated.\r
+ \r
+ EFI_INVALID_PARAMETER - The handle is unknown.\r
+ \r
+ EFI_NOT_FOUND - A form on the requested handle cannot be found with the\r
+ requested FormId.\r
+ \r
+ EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.\r
+\r
+--*/\r
+{\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_IFR_PACK *FormPack;\r
+ EFI_IFR_FORM *Form;\r
+ EFI_IFR_OP_HEADER *Location;\r
+ UINT16 *BufferLength = (UINT16 *) BufferLengthTemp;\r
+ UINTN FormLength;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+\r
+ HandleDatabase = HiiData->DatabaseHead;\r
+\r
+ PackageInstance = NULL;\r
+\r
+ FormLength = 0;\r
+\r
+ //\r
+ // Check numeric value against the head of the database\r
+ //\r
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
+ //\r
+ // Match the numeric value with the database entry - if matched, extract PackageInstance\r
+ //\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // No handle was found - error condition\r
+ //\r
+ if (PackageInstance == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Based on if there is IFR data in this package instance, determine\r
+ // what the location is of the beginning of the string data.\r
+ //\r
+ if (PackageInstance->IfrSize > 0) {\r
+ FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);\r
+ } else {\r
+ //\r
+ // If there is no IFR data return an error\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // If requesting the entire Form Package\r
+ //\r
+ if (FormId == 0) {\r
+ //\r
+ // Return an error if buffer is too small\r
+ //\r
+ if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {\r
+ *BufferLength = (UINT16) PackageInstance->IfrSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ CopyMem (Buffer, FormPack, PackageInstance->IfrSize);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
+ Location = (EFI_IFR_OP_HEADER *) FormPack;\r
+\r
+ //\r
+ // Look for the FormId requested\r
+ //\r
+ for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
+ switch (Location->OpCode) {\r
+ case EFI_IFR_FORM_OP:\r
+ Form = (EFI_IFR_FORM *) Location;\r
+\r
+ //\r
+ // If we found a Form Op-code and it is of the correct Id, copy it and return\r
+ //\r
+ if (Form->FormId == FormId) {\r
+ //\r
+ // Calculate the total size of form\r
+ //\r
+ for (FormLength = 0; Location->OpCode != EFI_IFR_END_FORM_OP; ) {\r
+ FormLength += Location->Length;\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ }\r
+ FormLength += Location->Length;\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+\r
+ if ((Buffer == NULL) || (FormLength > *BufferLength)) {\r
+ *BufferLengthTemp = FormLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ \r
+ //\r
+ // Rewind to start offset of the found Form\r
+ //\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *)Location - FormLength);\r
+ CopyMem (Buffer, Location, FormLength);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ default:\r
+ break;\r
+ }\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+//\r
+// Helper functions to HiiGetDefaultImage()\r
+//\r
+\r
+STATIC\r
+UINT8*\r
+HiiGetDefaultImageInitPack (\r
+ IN OUT EFI_HII_VARIABLE_PACK_LIST *VariablePackItem,\r
+ IN EFI_IFR_VARSTORE *VarStore\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+\r
+ Initialize the EFI_HII_VARIABLE_PACK_LIST structure and\r
+ prepare it ready to be used by HiiGetDefaultImagePopulateMap ().\r
+ \r
+ Arguments:\r
+\r
+ VariablePackItem - Variable Package List.\r
+ VarStore - IFR variable storage.\r
+ \r
+ Returns: \r
+\r
+ Return the pointer to the Map space.\r
+ \r
+--*/\r
+{\r
+ CHAR16 *Name16;\r
+ CHAR8 *Name8;\r
+ CHAR8 *Map;\r
+ EFI_HII_VARIABLE_PACK *VariablePack;\r
+\r
+ //\r
+ // Set pointer the pack right after the node\r
+ //\r
+ VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1);\r
+ VariablePack = VariablePackItem->VariablePack;\r
+\r
+ //\r
+ // Copy the var name to VariablePackItem from VarStore\r
+ // Needs ASCII->Unicode conversion.\r
+ //\r
+ ASSERT (VarStore->Header.Length > sizeof (*VarStore));\r
+ Name8 = (CHAR8 *) (VarStore + 1);\r
+ Name16 = (CHAR16 *) (VariablePack + 1);\r
+ Ascii2Unicode (Name16, Name8);\r
+\r
+ //\r
+ // Compute the other fields of the VariablePackItem\r
+ //\r
+ VariablePack->VariableId = VarStore->VarId;\r
+ CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID));\r
+ VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2);\r
+ VariablePack->Header.Length = sizeof (*VariablePack) \r
+ + VariablePack->VariableNameLength\r
+ + VarStore->Size;\r
+ //\r
+ // Return the pointer to the Map space.\r
+ //\r
+ Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength;\r
+\r
+ return (UINT8 *)Map;\r
+}\r
+\r
+STATIC\r
+VOID\r
+HiiGetDefaultImagePopulateMap (\r
+ IN OUT UINT8 *Map, \r
+ IN EFI_IFR_OP_HEADER *FormSet,\r
+ IN EFI_IFR_VARSTORE *VarStore,\r
+ IN UINTN DefaultMask\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+\r
+ Fill the Map with all the default values either from NV or Hii database.\r
+ \r
+ Arguments:\r
+\r
+ Map - Memory pointer to hold the default values.\r
+ FormSet - The starting EFI_IFR_OP_HEADER to begin retriving default values.\r
+ VarStore - IFR variable storage.\r
+ DefaultMask - The mask used to get the default variable.\r
+ \r
+ Returns: \r
+\r
+ VOID\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IFR_OP_HEADER *IfrItem;\r
+ UINT16 VarId;\r
+ EFI_IFR_VARSTORE_SELECT *VarSelect;\r
+ EFI_IFR_ONE_OF_OPTION *OneOfOpt;\r
+ EFI_IFR_CHECKBOX *CheckBox;\r
+ EFI_IFR_NUMERIC *Numeric;\r
+ UINTN Size;\r
+ UINTN SizeTmp;\r
+ EFI_IFR_NV_DATA *IfrNvData;\r
+ EFI_GUID Guid;\r
+ CHAR16 *Name16;\r
+ CHAR8 *Name8; \r
+ EFI_HANDLE CallbackHandle;\r
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProt;\r
+\r
+ //\r
+ // Get the Map's Name/Guid/Szie from the Varstore.\r
+ // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode.\r
+ //\r
+ ASSERT (VarStore->Header.Length >= sizeof (*VarStore));\r
+ Name8 = (CHAR8 *) (VarStore + 1);\r
+ Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16));\r
+ Ascii2Unicode (Name16, Name8);\r
+ CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID));\r
+ Size = VarStore->Size;\r
+\r
+ //\r
+ // First, check if the map exists in the NV. If so, get it from NV and exit.\r
+ //\r
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
+ //\r
+ // Check if Manufaturing Defaults exist in the NV.\r
+ //\r
+ Status = EfiLibHiiVariableOverrideBySuffix (\r
+ HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE,\r
+ Name16,\r
+ &Guid,\r
+ Size,\r
+ Map\r
+ );\r
+ } else {\r
+ //\r
+ // All other cases default to Defaults. Check if Defaults exist in the NV.\r
+ //\r
+ Status = EfiLibHiiVariableOverrideBySuffix (\r
+ HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE,\r
+ Name16,\r
+ &Guid,\r
+ Size,\r
+ Map\r
+ );\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Either Defaults/Manufacturing variable exists and appears to be valid. \r
+ // The map is read, exit w/ success now.\r
+ //\r
+ FreePool (Name16);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // First, prime the map with what already is in the NV.\r
+ // This is needed to cover a situation where the IFR does not contain all the \r
+ // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default.\r
+ // Ignore status. Either it gets read or not. \r
+ // \r
+ FormCallbackProt = NULL;\r
+ CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle));\r
+ if (CallbackHandle != NULL) {\r
+ Status = gBS->HandleProtocol (\r
+ (EFI_HANDLE) (UINTN) CallbackHandle,\r
+ &gEfiFormCallbackProtocolGuid,\r
+ (VOID *) &FormCallbackProt\r
+ );\r
+ }\r
+ if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) {\r
+ //\r
+ // Attempt to read using NvRead() callback. Probe first for existence and correct variable size.\r
+ //\r
+ SizeTmp = 0;\r
+ Status = FormCallbackProt->NvRead (\r
+ FormCallbackProt,\r
+ Name16,\r
+ &Guid,\r
+ 0,\r
+ &SizeTmp,\r
+ NULL\r
+ );\r
+ if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) {\r
+ Status = FormCallbackProt->NvRead (\r
+ FormCallbackProt,\r
+ Name16,\r
+ &Guid,\r
+ 0,\r
+ &SizeTmp,\r
+ Map\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (SizeTmp == Size);\r
+ }\r
+ } else {\r
+ //\r
+ // No callback available for this formset, read straight from NV. Deliberately ignore the Status. \r
+ // The buffer will only be written if variable exists nd has correct size.\r
+ //\r
+ Status = EfiLibHiiVariableRetrieveFromNv (\r
+ Name16,\r
+ &Guid,\r
+ Size,\r
+ (VOID **) &Map\r
+ );\r
+ }\r
+\r
+ //\r
+ // Iterate all IFR statements and for applicable, retrieve the default into the Map.\r
+ //\r
+ for (IfrItem = FormSet, VarId = 0; \r
+ IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP; \r
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length)\r
+ ) {\r
+\r
+ //\r
+ // Observe VarStore switch.\r
+ //\r
+ if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) {\r
+ VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem;\r
+ VarId = VarSelect->VarId;\r
+ continue;\r
+ }\r
+\r
+\r
+ //\r
+ // Skip opcodes that reference other VarStore than that specific to current map.\r
+ // \r
+ if (VarId != VarStore->VarId) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Extract the default value from this opcode if applicable, and apply it to the map.\r
+ //\r
+ IfrNvData = (EFI_IFR_NV_DATA *) IfrItem;\r
+ switch (IfrItem->OpCode) {\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
+ //\r
+ // Get to the first EFI_IFR_ONE_OF_OPTION_OP\r
+ //\r
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length); \r
+ ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode);\r
+\r
+ OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
+ //\r
+ // In the worst case, the first will be the default.\r
+ //\r
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
+\r
+ while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) {\r
+\r
+ OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;\r
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
+ if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
+ //\r
+ // In the worst case, the first will be the default.\r
+ //\r
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
+ break;\r
+ }\r
+ } else {\r
+ if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) {\r
+ //\r
+ // In the worst case, the first will be the default.\r
+ //\r
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);\r
+ break;\r
+ }\r
+ }\r
+\r
+ IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length);\r
+ }\r
+ continue;\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
+ CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem; \r
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {\r
+ if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) {\r
+ *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
+ }\r
+ } else {\r
+ if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) {\r
+ *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);\r
+ Numeric = (EFI_IFR_NUMERIC *) IfrItem;\r
+ CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth);\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // No support for default value for these opcodes.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (Name16);\r
+\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetDefaultImage (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN UINTN DefaultMask,\r
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList\r
+ )\r
+/*++\r
+ \r
+ Routine Description:\r
+\r
+ This function allows a program to extract the NV Image \r
+ that represents the default storage image\r
+ \r
+ Arguments:\r
+ This - A pointer to the EFI_HII_PROTOCOL instance.\r
+ Handle - The HII handle from which will have default data retrieved.\r
+ UINTN - Mask used to retrieve the default image.\r
+ VariablePackList - Callee allocated, tightly-packed, link list data \r
+ structure that contain all default varaible packs\r
+ from the Hii Database.\r
+ \r
+ Returns: \r
+ EFI_NOT_FOUND - If Hii database does not contain any default images.\r
+ EFI_INVALID_PARAMETER - Invalid input parameter.\r
+ EFI_SUCCESS - Operation successful.\r
+ \r
+--*/\r
+{\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_IFR_OP_HEADER *FormSet;\r
+ EFI_IFR_OP_HEADER *IfrItem;\r
+ EFI_IFR_VARSTORE *VarStore;\r
+ EFI_IFR_VARSTORE *VarStoreDefault;\r
+ UINTN SetupMapNameSize;\r
+ UINTN SizeOfMaps;\r
+ EFI_HII_VARIABLE_PACK_LIST *PackList;\r
+ EFI_HII_VARIABLE_PACK_LIST *PackListNext; \r
+ EFI_HII_VARIABLE_PACK_LIST *PackListLast;\r
+ UINT8 *Map;\r
+\r
+\r
+ //\r
+ // Find the IFR pack from the handle. Then get the formset from the pack.\r
+ //\r
+ PackageInstance = NULL;\r
+ HandleDatabase = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead;\r
+ for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ break;\r
+ }\r
+ }\r
+ if (PackageInstance == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK));\r
+\r
+ //\r
+ // Get the sizes of all the VARSTOREs in this VFR.\r
+ // Then allocate enough space for all of them plus all maps\r
+ //\r
+ SizeOfMaps = 0;\r
+ IfrItem = FormSet;\r
+ while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
+\r
+ if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
+ VarStore = (EFI_IFR_VARSTORE *) IfrItem;\r
+ //\r
+ // Size of the map\r
+ //\r
+ SizeOfMaps += VarStore->Size; \r
+ //\r
+ // add the size of the string, in Unicode\r
+ //\r
+ SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2; \r
+ //\r
+ // Space for node\r
+ //\r
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
+ //\r
+ // Space for linked list node \r
+ //\r
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
+ }\r
+\r
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
+ }\r
+\r
+ //\r
+ // If the FormSet OpCode has a non-zero NvDataSize. There is a default \r
+ // NvMap with ID=0, GUID that of the formset itself and "Setup" as name.\r
+ //\r
+ SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1;\r
+ VarStoreDefault = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
+\r
+ if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) {\r
+\r
+ VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP;\r
+ VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize);\r
+ Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME);\r
+ CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID));\r
+ VarStoreDefault->VarId = 0;\r
+ VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize;\r
+\r
+ //\r
+ // Size of the map\r
+ //\r
+ SizeOfMaps += VarStoreDefault->Size; \r
+ //\r
+ // add the size of the string\r
+ //\r
+ SizeOfMaps += sizeof (SETUP_MAP_NAME); \r
+ //\r
+ // Space for node\r
+ //\r
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); \r
+ //\r
+ // Space for linked list node \r
+ //\r
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); \r
+ }\r
+\r
+ if (0 == SizeOfMaps) {\r
+ //\r
+ // The IFR does not have any explicit or default map(s).\r
+ //\r
+ return EFI_NOT_FOUND; \r
+ }\r
+\r
+ //\r
+ // Allocate the return buffer\r
+ //\r
+ PackList = AllocateZeroPool (SizeOfMaps);\r
+ ASSERT (NULL != PackList); \r
+\r
+ PackListNext = PackList;\r
+ PackListLast = PackList;\r
+\r
+ //\r
+ // Handle the default map first, if any.\r
+ //\r
+ if (0 != VarStoreDefault->Size) {\r
+\r
+ Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault);\r
+\r
+ HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask);\r
+\r
+ PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
+ PackListLast = PackListNext;\r
+ PackListNext = PackListNext->NextVariablePack;\r
+ }\r
+\r
+\r
+ //\r
+ // Handle the explicit varstore(s)\r
+ //\r
+ IfrItem = FormSet;\r
+ while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {\r
+\r
+ if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {\r
+\r
+ Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem);\r
+\r
+ HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask);\r
+\r
+ PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);\r
+ PackListLast = PackListNext;\r
+ PackListNext = PackListNext->NextVariablePack;\r
+ }\r
+\r
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);\r
+ }\r
+\r
+ PackListLast->NextVariablePack = NULL;\r
+ *VariablePackList = PackList;\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiUpdateForm (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_FORM_LABEL Label,\r
+ IN BOOLEAN AddData,\r
+ IN EFI_HII_UPDATE_DATA *Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This function allows the caller to update a form that has \r
+ previously been registered with the EFI HII database.\r
+\r
+Arguments:\r
+ Handle - Hii Handle associated with the Formset to modify\r
+ Label - Update information starting immediately after this label in the IFR\r
+ AddData - If TRUE, add data. If FALSE, remove data\r
+ Data - If adding data, this is the pointer to the data to add\r
+\r
+Returns: \r
+ EFI_SUCCESS - Update success.\r
+ Other - Update fail.\r
+\r
+--*/\r
+{\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_IFR_PACK *FormPack;\r
+ EFI_IFR_OP_HEADER *Location;\r
+ EFI_IFR_OP_HEADER *DataLocation;\r
+ UINT8 *OtherBuffer;\r
+ UINT8 *TempBuffer;\r
+ UINT8 *OrigTempBuffer;\r
+ UINTN TempBufferSize;\r
+ UINTN Index;\r
+\r
+ OtherBuffer = NULL;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+\r
+ HandleDatabase = HiiData->DatabaseHead;\r
+\r
+ PackageInstance = NULL;\r
+\r
+ //\r
+ // Check numeric value against the head of the database\r
+ //\r
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {\r
+ //\r
+ // Match the numeric value with the database entry - if matched, extract PackageInstance\r
+ //\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // No handle was found - error condition\r
+ //\r
+ if (PackageInstance == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Calculate and allocate space for retrieval of IFR data\r
+ //\r
+ DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
+ TempBufferSize = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance);\r
+\r
+ for (Index = 0; Index < Data->DataCount; Index++) {\r
+ TempBufferSize += DataLocation->Length;\r
+ DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
+ }\r
+\r
+ TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize;\r
+\r
+ TempBuffer = AllocateZeroPool (TempBufferSize);\r
+ ASSERT (TempBuffer != NULL);\r
+\r
+ OrigTempBuffer = TempBuffer;\r
+\r
+ //\r
+ // We update only packages with IFR information in it\r
+ //\r
+ if (PackageInstance->IfrSize == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (\r
+ TempBuffer,\r
+ PackageInstance,\r
+ ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance))\r
+ );\r
+\r
+ TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance));\r
+\r
+ //\r
+ // Based on if there is IFR data in this package instance, determine\r
+ // what the location is of the beginning of the string data.\r
+ //\r
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));\r
+ Location = (EFI_IFR_OP_HEADER *) FormPack;\r
+\r
+ //\r
+ // Look for the FormId requested\r
+ //\r
+ for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {\r
+ switch (Location->OpCode) {\r
+ case EFI_IFR_FORM_SET_OP:\r
+ //\r
+ // If the FormSet has an update pending, pay attention.\r
+ //\r
+ if (Data->FormSetUpdate) {\r
+ ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle;\r
+ }\r
+\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+ break;\r
+\r
+ case EFI_IFR_FORM_OP:\r
+ //\r
+ // If the Form has an update pending, pay attention.\r
+ //\r
+ if (Data->FormUpdate) {\r
+ ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle;\r
+ }\r
+\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+ break;\r
+\r
+ case EFI_IFR_LABEL_OP:\r
+ //\r
+ // If the label does not match the requested update point, ignore it\r
+ //\r
+ if (((EFI_IFR_LABEL *) Location)->LabelId != Label) {\r
+ //\r
+ // Copy the label\r
+ //\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ continue;\r
+ }\r
+\r
+ if (AddData) {\r
+ //\r
+ // Copy the label\r
+ //\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+\r
+ //\r
+ // Add the DataCount amount of opcodes to TempBuffer\r
+ //\r
+ DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;\r
+ for (Index = 0; Index < Data->DataCount; Index++) {\r
+ CopyMem (TempBuffer, DataLocation, DataLocation->Length);\r
+ ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length;\r
+ OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
+ CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
+ TempBuffer = TempBuffer + DataLocation->Length;\r
+ DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);\r
+ }\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ continue;\r
+ } else {\r
+ //\r
+ // Copy the label\r
+ //\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+\r
+ //\r
+ // Remove the DataCount amount of opcodes unless we run into an end of form or a label\r
+ //\r
+ for (Index = 0; Index < Data->DataCount; Index++) {\r
+ //\r
+ // If we are about to skip an end form - bail out, since that is illegal\r
+ //\r
+ if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) {\r
+ break;\r
+ }\r
+ //\r
+ // By skipping Location entries, we are in effect not copying what was previously there\r
+ //\r
+ ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length;\r
+ OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));\r
+ CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ }\r
+ }\r
+\r
+ default:\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+ TempBuffer = TempBuffer + Location->Length;\r
+ break;\r
+ }\r
+ //\r
+ // Go to the next Op-Code\r
+ //\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ }\r
+ //\r
+ // Copy the last op-code left behind from the for loop\r
+ //\r
+ CopyMem (TempBuffer, Location, Location->Length);\r
+\r
+ //\r
+ // Advance to beginning of strings and copy them\r
+ //\r
+ TempBuffer = TempBuffer + Location->Length;\r
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);\r
+ CopyMem (TempBuffer, Location, PackageInstance->StringSize);\r
+\r
+ //\r
+ // Free the old buffer, and assign into our database the latest buffer\r
+ //\r
+ FreePool (HandleDatabase->Buffer);\r
+ HandleDatabase->Buffer = OrigTempBuffer;\r
+\r
+ return EFI_SUCCESS;\r
+}\r