summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc9
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/CommonHeader.h42
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.c598
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.dxs31
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.h64
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.inf111
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.msa101
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/Inventory.vfr128
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/InventoryStrings.unibin0 -> 8302 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/NVDataStruc.h67
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/Vfr.vfr627
-rw-r--r--IntelFrameworkModulePkg/Universal/DriverSampleDxe/VfrStrings.unibin0 -> 35590 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/CommonHeader.h41
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Fonts.c271
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Forms.c1582
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.c412
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.dxs30
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.h307
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.inf116
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.msa87
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Keyboard.c48
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c678
-rw-r--r--IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Strings.c1276
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Boolean.c1372
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Colors.h59
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/CommonHeader.h44
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/InputHandler.c1575
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Presentation.c1490
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.c298
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.h44
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c1692
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.c2224
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.h508
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.inf108
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa102
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.unibin0 -> 10432 bytes
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.c3155
-rw-r--r--IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.h440
38 files changed, 19737 insertions, 0 deletions
diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
index 1853aa66b2..1382f9da88 100644
--- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
+++ b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
@@ -77,8 +77,11 @@
DxeServicesTableLib|${WORKSPACE}/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
FvbServiceLib|${WORKSPACE}/MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf
ReportStatusCodeLib|${WORKSPACE}/IntelFrameworkPkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+ HiiLibFramework|$(WORKSPACE)/IntelFrameworkPkg/Library/HiiLibFramework/HiiLib.inf
+ IfrSupportLibFramework|$(WORKSPACE)/IntelFrameworkPkg/Library/IfrSupportLibFramework/IfrSupportLib.inf
PciIncompatibleDeviceSupportLib|${WORKSPACE}/IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.inf
+
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|${WORKSPACE}/MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|${WORKSPACE}/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
@@ -91,6 +94,8 @@
UefiRuntimeLib|${WORKSPACE}/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
UefiRuntimeServicesTableLib|${WORKSPACE}/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
ReportStatusCodeLib|${WORKSPACE}/IntelFrameworkPkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+ HiiLibFramework|$(WORKSPACE)/IntelFrameworkPkg/Library/HiiLibFramework/HiiLib.inf
+ IfrSupportLibFramework|$(WORKSPACE)/IntelFrameworkPkg/Library/IfrSupportLibFramework/IfrSupportLib.inf
################################################################################
#
@@ -159,3 +164,7 @@
$(WORKSPACE)\IntelFrameworkModulePkg\Universal\DataHub\DataHubStdErr\Dxe\DataHubStdErr.inf
$(WORKSPACE)\IntelFrameworkModulePkg\Universal\StatusCode\Dxe\DxeStatusCode.inf
$(WORKSPACE)\IntelFrameworkModulePkg\Universal\StatusCode\Pei\PeiStatusCode.inf
+ $(WORKSPACE)\IntelFrameworkModulePkg\Universal\HiiDataBaseDxe\HiiDatabase.inf
+ # $(WORKSPACE)\IntelFrameworkModulePkg\Universal\UserInterface\SetupBrowser\Dxe\SetupBrowser.inf
+# $(WORKSPACE)\IntelFrameworkModulePkg\Universal\DriverSampleDxe\DriverSample.inf
+
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/CommonHeader.h b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/CommonHeader.h
new file mode 100644
index 0000000000..da9f608fac
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/CommonHeader.h
@@ -0,0 +1,42 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/FormCallback.h>
+#include <Protocol/FrameworkHii.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/IfrSupportLibFramework.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLibFramework.h>
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.c b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.c
new file mode 100644
index 0000000000..74156430af
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.c
@@ -0,0 +1,598 @@
+/*++
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ DriverSample.c
+
+Abstract:
+
+ This is an example of how a driver might export data to the HII protocol to be
+ later utilized by the Setup Protocol
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "DriverSample.h"
+
+#define DISPLAY_ONLY_MY_ITEM 0x0001
+
+#define STRING_PACK_GUID \
+ { \
+ 0x8160a85f, 0x934d, 0x468b, { 0xa2, 0x35, 0x72, 0x89, 0x59, 0x14, 0xf6, 0xfc } \
+ }
+
+EFI_GUID mFormSetGuid = FORMSET_GUID;
+EFI_GUID mStringPackGuid = STRING_PACK_GUID;
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN EFI_FORM_CALLBACK_PROTOCOL *This,
+ IN UINT16 KeyValue,
+ IN EFI_IFR_DATA_ARRAY *Data,
+ OUT EFI_HII_CALLBACK_PACKET **Packet
+ )
+/*++
+
+Routine Description:
+
+ This is the function that is called to provide results data to the driver. This data
+ consists of a unique key which is used to identify what data is either being passed back
+ or being asked for.
+
+Arguments:
+
+ KeyValue - A unique value which is sent to the original exporting driver so that it
+ can identify the type of data to expect. The format of the data tends to
+ vary based on the op-code that geerated the callback.
+
+ Data - A pointer to the data being sent to the original exporting driver.
+
+Returns:
+
+--*/
+{
+ EFI_CALLBACK_INFO *Private;
+ EFI_HII_UPDATE_DATA *UpdateData;
+ UINT8 *Location;
+ EFI_HII_CALLBACK_PACKET *DataPacket;
+ UINT16 Value;
+ CHAR16 VariableName[40];
+ STATIC UINT16 QuestionId = 0;
+ IFR_OPTION *OptionList;
+ UINTN Index;
+ MyIfrNVData NVStruc;
+
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);
+
+ //
+ // This should tell me the first offset AFTER the end of the compiled NV map
+ // If op-code results are not going to be saved to NV locations ensure the QuestionId
+ // is beyond the end of the NVRAM mapping.
+ //
+ if (QuestionId == 0) {
+ QuestionId = sizeof (MyIfrNVData);
+ }
+
+ ZeroMem (VariableName, (sizeof (CHAR16) * 40));
+
+ switch (KeyValue) {
+ case 0x0001:
+ //
+ // Create a small boot order list
+ //
+ QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc));
+
+ //
+ // Need some memory for OptionList. Allow for up to 8 options.
+ //
+ OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8);
+ ASSERT (OptionList != NULL);
+
+ //
+ // Allocate space for creation of Buffer
+ //
+ UpdateData = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData != NULL);
+
+ //
+ // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
+ // so we don't have to keep track of how many op-codes we added or subtracted. The rules for removal
+ // of op-codes are simply that the removal will always stop as soon as a label or the end of a form is
+ // encountered. Therefore, giving a large obnoxious count such as below takes care of other complexities.
+ //
+ UpdateData->DataCount = 0xFF;
+
+ //
+ // Delete set of op-codes
+ //
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x2222,
+ FALSE, // If we aren't adding, we are deleting
+ UpdateData
+ );
+
+ //
+ // Create 3 options
+ //
+ for (Index = 0; Index < 3; Index++) {
+ OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index);
+ OptionList[Index].Value = (UINT16) (Index + 1);
+ OptionList[Index].Flags = RESET_REQUIRED;
+ }
+
+ CreateOrderedListOpCode (
+ QuestionId, // Question ID
+ 8, // Max Entries
+ (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt
+ (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help
+ OptionList,
+ 3,
+ &UpdateData->Data // Buffer location to place op-codes
+ );
+
+ //
+ // For one-of/ordered lists commands, they really consist of 2 op-codes (a header and a footer)
+ // Each option within a one-of/ordered list is also an op-code
+ // So this example has 5 op-codes it is adding since we have a one-of header + 3 options + one-of footer
+ //
+ UpdateData->DataCount = 0x5;
+
+ //
+ // Add one op-code
+ //
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x2222,
+ TRUE,
+ UpdateData
+ );
+
+ FreePool (UpdateData);
+ FreePool (OptionList);
+ break;
+
+ case 0x0002:
+ //
+ // Create a large boot order list
+ //
+ QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc));
+
+ //
+ // Need some memory for OptionList. Allow for up to 8 options.
+ //
+ OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8);
+ ASSERT (OptionList != NULL);
+
+ //
+ // Allocate space for creation of Buffer
+ //
+ UpdateData = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData != NULL);
+
+ //
+ // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience
+ // so we don't have to keep track of how many op-codes we added or subtracted
+ //
+ UpdateData->DataCount = 0xFF;
+
+ //
+ // Delete one op-code
+ //
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x2222,
+ FALSE,
+ UpdateData
+ );
+
+ //
+ // Create 4 options
+ //
+ for (Index = 0; Index < 4; Index++) {
+ OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index);
+ OptionList[Index].Value = (UINT16) (Index + 1);
+ OptionList[Index].Flags = RESET_REQUIRED;
+ }
+
+ CreateOrderedListOpCode (
+ QuestionId, // Question ID
+ 8, // Max Entries
+ (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt
+ (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help
+ OptionList,
+ 4,
+ &UpdateData->Data // Buffer location to place op-codes
+ );
+
+ //
+ // For one-of commands, they really consist of 2 op-codes (a header and a footer)
+ // Each option within a one-of is also an op-code
+ // So this example has 6 op-codes it is adding since we have a one-of header + 4 options + one-of footer
+ //
+ UpdateData->DataCount = 0x6;
+
+ //
+ // Add one op-code
+ //
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x2222,
+ TRUE,
+ UpdateData
+ );
+
+ FreePool (UpdateData);
+ FreePool (OptionList);
+ break;
+
+ case 0x1234:
+ //
+ // Allocate space for creation of Buffer
+ //
+ QuestionId = (UINT16) ((UINTN) (&NVStruc.DynamicCheck) - (UINTN) (&NVStruc));
+ UpdateData = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData != NULL);
+
+ Location = (UINT8 *) &UpdateData->Data;
+
+ UpdateData->FormSetUpdate = TRUE;
+ UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->CallbackHandle;
+ UpdateData->FormUpdate = FALSE;
+ UpdateData->FormTitle = 0;
+ UpdateData->DataCount = 2;
+
+ CreateGotoOpCode (
+ 1,
+ STR_GOTO_FORM1, // Token value for the Prompt
+ 0, // Goto Help
+ 0, // Flags
+ 0, // Key
+ &UpdateData->Data // Buffer location to place op-codes
+ );
+
+ Location = Location + ((EFI_IFR_OP_HEADER *) &UpdateData->Data)->Length;
+
+ CreateCheckBoxOpCode (
+ QuestionId, // Question ID
+ 1, // Data width (BOOLEAN = 1)
+ (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_PROMPT), // Token value for the Prompt
+ (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_HELP), // Token value for the Help
+ EFI_IFR_FLAG_INTERACTIVE, // Flags
+ 0x1236, // Key
+ Location // Buffer location to place op-codes
+ );
+
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x1234,
+ TRUE,
+ UpdateData
+ );
+
+ FreePool (UpdateData);
+ QuestionId++;
+ break;
+
+ case 0x1235:
+ //
+ // Allocate space for creation of Buffer
+ //
+ UpdateData = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData != NULL);
+
+ //
+ // Initialize DataPacket with information intended to remove all
+ // previously created op-codes in the dynamic page
+ //
+ UpdateData->FormSetUpdate = FALSE;
+ UpdateData->FormCallbackHandle = 0;
+ UpdateData->FormUpdate = FALSE;
+ UpdateData->FormTitle = 0;
+ //
+ // Unlikely to be more than 0xff op-codes in the dynamic page to remove
+ //
+ UpdateData->DataCount = 0xff;
+ UpdateData->Data = NULL;
+
+ //
+ // Remove all op-codes from dynamic page
+ //
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x1234, // Label 0x1234
+ FALSE, // Remove Op-codes (will never remove form/endform)
+ UpdateData // Significant value is UpdateData->DataCount
+ );
+
+ UpdateData->FormSetUpdate = FALSE;
+ UpdateData->FormCallbackHandle = 0;
+ UpdateData->FormUpdate = FALSE;
+ UpdateData->FormTitle = 0;
+ UpdateData->DataCount = 1;
+
+ CreateGotoOpCode (
+ 1,
+ STR_GOTO_FORM1, // Token value for the Prompt
+ 0, // Goto Help
+ 0, // Flags
+ 0, // Key
+ &UpdateData->Data // Buffer location to place op-codes
+ );
+
+ Private->Hii->UpdateForm (
+ Private->Hii,
+ Private->RegisteredHandle,
+ (EFI_FORM_LABEL) 0x1234,
+ TRUE,
+ UpdateData
+ );
+
+ FreePool (UpdateData);
+ break;
+
+ case 0x1236:
+ //
+ // If I hit the checkbox, I enter this case statement...
+ //
+ //
+ // Since I am returning an error (for test purposes) I need to pass in the string for the error
+ // I will allocate space for the return value. If an error occurs (which is the case) I can simply return
+ // an error and fill in the string parameter, otherwise, I will return information in the DataArray structure.
+ // The browser will free this packet structure
+ //
+ *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + sizeof (SAMPLE_STRING) + 2);
+ ASSERT (*Packet != NULL);
+
+ //
+ // Assign the buffer address to DataPacket
+ //
+ DataPacket = *Packet;
+
+ StrCpy (DataPacket->String, (CHAR16 *) SAMPLE_STRING);
+ return EFI_DEVICE_ERROR;
+
+ case 0x1237:
+
+ *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);
+ ASSERT (*Packet != NULL);
+
+ //
+ // Assign the buffer address to DataPacket
+ //
+ DataPacket = *Packet;
+
+ DataPacket->DataArray.EntryCount = 1;
+ DataPacket->DataArray.NvRamMap = NULL;
+ ((EFI_IFR_DATA_ENTRY *) (&DataPacket->DataArray + 1))->Flags = EXIT_REQUIRED;
+ break;
+
+ case 0x1555:
+ Value = 0x0001;
+ UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
+
+ gRT->SetVariable (
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 2,
+ (VOID *) &Value
+ );
+ break;
+
+ case 0x1556:
+ Value = 0x1000;
+ UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
+
+ gRT->SetVariable (
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 2,
+ (VOID *) &Value
+ );
+ break;
+
+ case 0x1557:
+ Value = 0x0000;
+ UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME);
+
+ gRT->SetVariable (
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 2,
+ (VOID *) &Value
+ );
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DriverSampleInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PROTOCOL *Hii;
+ //
+ // EFI_FORM_BROWSER_PROTOCOL *FormConfig;
+ //
+ EFI_HII_PACKAGES *PackageList;
+ EFI_HII_HANDLE HiiHandle;
+ STRING_REF TokenToUpdate;
+ STRING_REF TokenToUpdate2;
+ STRING_REF TokenToUpdate3;
+ CHAR16 *NewString;
+ EFI_HII_UPDATE_DATA *UpdateData;
+ EFI_CALLBACK_INFO *CallbackInfo;
+ EFI_HANDLE Handle;
+ EFI_SCREEN_DESCRIPTOR Screen;
+
+ ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
+
+ //
+ // Remove 3 characters from top and bottom
+ //
+ Screen.TopRow = 3;
+ Screen.BottomRow = Screen.BottomRow - 3;
+
+ //
+ // There should only be one HII protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &Hii
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;;
+ }
+
+ CallbackInfo = AllocatePool (sizeof (EFI_CALLBACK_INFO));
+ if (CallbackInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;
+ CallbackInfo->Hii = Hii;
+
+ //
+ // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
+ //
+ CallbackInfo->DriverCallback.NvRead = NULL;
+ CallbackInfo->DriverCallback.NvWrite = NULL;
+ CallbackInfo->DriverCallback.Callback = DriverCallback;
+
+ //
+ // Install protocol interface
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiFormCallbackProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &CallbackInfo->DriverCallback
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ CallbackInfo->CallbackHandle = Handle;
+
+ PackageList = PreparePackages (1, &mStringPackGuid, DriverSampleStrings);
+ Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
+ FreePool (PackageList);
+
+ PackageList = PreparePackages (1, &mStringPackGuid, InventoryBin);
+ Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
+ FreePool (PackageList);
+
+ PackageList = PreparePackages (1, &mStringPackGuid, VfrBin);
+ Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
+ FreePool (PackageList);
+
+ CallbackInfo->RegisteredHandle = HiiHandle;
+
+ //
+ // Very simple example of how one would update a string that is already
+ // in the HII database
+ //
+ TokenToUpdate = (STRING_REF) STR_CPU_STRING2;
+ NewString = (CHAR16 *) L"700 Mhz";
+
+ Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, NewString);
+
+ //
+ // Add a string - if 0 will be updated with new Token number
+ //
+ TokenToUpdate = (STRING_REF) 0;
+
+ //
+ // Add a string - if 0 will be updated with new Token number
+ //
+ TokenToUpdate2 = (STRING_REF) 0;
+
+ //
+ // Add a string - if 0 will be updated with new Token number
+ //
+ TokenToUpdate3 = (STRING_REF) 0;
+
+ Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, (CHAR16 *) L"Desired Speed");
+ Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate2, (CHAR16 *) L"5 Thz");
+ Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate3, (CHAR16 *) L"This is next year's desired speed - right?");
+
+ //
+ // Allocate space for creation of Buffer
+ //
+ UpdateData = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData != NULL);
+
+ //
+ // Flag update pending in FormSet
+ //
+ UpdateData->FormSetUpdate = TRUE;
+ //
+ // Register CallbackHandle data for FormSet
+ //
+ UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;
+ UpdateData->FormUpdate = FALSE;
+ UpdateData->FormTitle = 0;
+ UpdateData->DataCount = 1;
+
+ CreateTextOpCode (TokenToUpdate, TokenToUpdate2, TokenToUpdate3, 0, 0, &UpdateData->Data);
+
+ Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 100, TRUE, UpdateData);
+
+ FreePool (UpdateData);
+
+ //
+ // Example of how to display only the item we sent to HII
+ //
+ if (DISPLAY_ONLY_MY_ITEM == 0x0001) {
+ //
+ // Have the browser pull out our copy of the data, and only display our data
+ //
+ // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);
+ //
+ } else {
+ //
+ // Have the browser pull out all the data in the HII Database and display it.
+ //
+ // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);
+ //
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.dxs b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.dxs
new file mode 100644
index 0000000000..d88f5682d3
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.dxs
@@ -0,0 +1,31 @@
+/*++
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DriverSample.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <DxeDepex.h>
+
+DEPENDENCY_START
+ EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.h b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.h
new file mode 100644
index 0000000000..ba3a50d9b2
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.h
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DriverSample.h
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#ifndef _DRIVER_SAMPLE_H
+#define _DRIVER_SAMPLE_H
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "NVDataStruc.h"
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+extern UINT8 VfrBin[];
+//
+// extern UINT8 VfrStringsStr[];
+//
+extern UINT8 InventoryBin[];
+//
+// extern UINT8 InventoryStringsStr[];
+//
+extern UINT8 DriverSampleStrings[];
+
+#define SAMPLE_STRING L"This is an error!"
+
+#define EFI_CALLBACK_INFO_SIGNATURE EFI_SIGNATURE_32 ('C', 'l', 'b', 'k')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE CallbackHandle;
+ EFI_FORM_CALLBACK_PROTOCOL DriverCallback;
+ UINT16 *KeyList;
+ VOID *FormBuffer;
+ EFI_HII_HANDLE RegisteredHandle;
+ EFI_HII_PROTOCOL *Hii;
+} EFI_CALLBACK_INFO;
+
+#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, DriverCallback, EFI_CALLBACK_INFO_SIGNATURE)
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.inf b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.inf
new file mode 100644
index 0000000000..ea26648664
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.inf
@@ -0,0 +1,111 @@
+#/** @file
+# Component description file for DriverSample module.
+#
+# This is an example driver to introduce how to export data to the HII protocol to be later utilized by the Setup Protocol.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DriverSample
+ FILE_GUID = FE3542FE-C1D3-4EF8-657C-8048606FF670
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = DriverSampleInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ DriverSample.dxs
+ DriverSample.h
+ NVDataStruc.h
+ DriverSample.c
+ Vfr.vfr
+ VfrStrings.uni
+ Inventory.vfr
+ InventoryStrings.uni
+ CommonHeader.h
+
+
+################################################################################
+#
+# Includes Section - list of Include locations that are required for
+# this module.
+#
+################################################################################
+
+[Includes]
+ $(WORKSPACE)/IntelFrameworkPkg/Include/Library
+ $(WORKSPACE)/MdePkg/Include/Library
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ HiiLibFramework
+ MemoryAllocationLib
+ BaseMemoryLib
+ IfrSupportLibFramework
+ PrintLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiFormCallbackProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiHiiProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.msa b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.msa
new file mode 100644
index 0000000000..4c96b5eedb
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/DriverSample.msa
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+ <MsaHeader>
+ <ModuleName>DriverSample</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>FE3542FE-C1D3-4EF8-657C-8048606FF670</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for DriverSample module.</Abstract>
+ <Description>This is an example driver to introduce how to export data to the HII protocol to be later utilized by the Setup Protocol. </Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>DriverSample</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED" RecommendedInstanceGuid="bda39d3a-451b-4350-8266-81ab10fa0523">
+ <Keyword>DebugLib</Keyword>
+ <HelpText>Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg.</HelpText>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED" RecommendedInstanceGuid="a86fbfca-0183-4eeb-aa8a-762e3b7da1f3">
+ <Keyword>PrintLib</Keyword>
+ <HelpText>Recommended libary Instance is BasePrintLib instance in MdePkg.</HelpText>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkIfrSupportLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HiiLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>InventoryStrings.uni</Filename>
+ <Filename>Inventory.vfr</Filename>
+ <Filename>VfrStrings.uni</Filename>
+ <Filename>Vfr.vfr</Filename>
+ <Filename>DriverSample.c</Filename>
+ <Filename>NVDataStruc.h</Filename>
+ <Filename>DriverSample.h</Filename>
+ <Filename>DriverSample.dxs</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiFormCallbackProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <HiiPackages>
+ <HiiPackage Usage="ALWAYS_PRODUCED">
+ <HiiCName>DriverSampleStrings</HiiCName>
+ <HelpText>EFI_HII_STRING type string package from UNI file.</HelpText>
+ </HiiPackage>
+ <HiiPackage Usage="ALWAYS_PRODUCED">
+ <HiiCName>InventoryBin</HiiCName>
+ <HelpText>EFI_HII_IFR type form package from VFR file.</HelpText>
+ </HiiPackage>
+ <HiiPackage Usage="ALWAYS_PRODUCED">
+ <HiiCName>VfrBin</HiiCName>
+ <HelpText>EFI_HII_IFR type form package from VFR file.</HelpText>
+ </HiiPackage>
+ </HiiPackages>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>DriverSampleInit</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Inventory.vfr b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Inventory.vfr
new file mode 100644
index 0000000000..434da17fcd
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Inventory.vfr
@@ -0,0 +1,128 @@
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+// *++
+//
+// Copyright (c) 2006, Intel Corporation
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// Inventory.vfr
+//
+// Abstract:
+//
+// Sample Inventory Data.
+//
+// Revision History:
+//
+// --*/
+
+#include "DriverSampleStrDefs.h"
+
+#define INVENTORY_GUID { 0xb3f56470, 0x6141, 0x4621, { 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 } }
+
+formset
+ guid = INVENTORY_GUID,
+ title = STRING_TOKEN(STR_INV_FORM_SET_TITLE),
+ help = STRING_TOKEN(STR_INV_FORM_SET_HELP),
+ class = 0x04,
+ subclass = 0x03,
+
+ form formid = 1,
+ title = STRING_TOKEN(STR_INV_FORM1_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
+
+ text
+ help = STRING_TOKEN(STR_INV_VERSION_HELP),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT2),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT3),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT4),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT5),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT6),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT7),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT8),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT9),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT10),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT11),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);
+
+ subtitle text = STRING_TOKEN(STR_INV_VERSION_TEXT12);
+
+ endform;
+
+endformset;
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/InventoryStrings.uni b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/InventoryStrings.uni
new file mode 100644
index 0000000000..4946b4ae61
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/InventoryStrings.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/NVDataStruc.h b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
new file mode 100644
index 0000000000..5b51e946e1
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
@@ -0,0 +1,67 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ NVDataStruc.h
+
+Abstract:
+
+ NVData structure used by the sample driver
+
+Revision History:
+
+--*/
+
+#ifndef _NVDATASTRUC_H
+#define _NVDATASTRUC_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#define FORMSET_GUID \
+ { \
+ 0xA04A27f4, 0xDF00, 0x4D42, { 0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D } \
+ }
+
+#define INVENTORY_GUID \
+ { \
+ 0xb3f56470, 0x6141, 0x4621, { 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 } \
+ }
+
+#define VAR_EQ_TEST_NAME 0x100
+
+#pragma pack(1)
+typedef struct {
+ UINT16 WhatIsThePassword[20];
+ UINT16 WhatIsThePassword2[20];
+ UINT16 MyStringData[20];
+ UINT16 SomethingHiddenForHtml;
+ UINT8 HowOldAreYouInYearsManual;
+ UINT16 HowTallAreYouManual;
+ UINT8 HowOldAreYouInYears;
+ UINT16 HowTallAreYou;
+ UINT8 MyFavoriteNumber;
+ UINT8 TestLateCheck;
+ UINT8 TestLateCheck2;
+ UINT8 QuestionAboutTreeHugging;
+ UINT8 ChooseToActivateNuclearWeaponry;
+ UINT8 SuppressGrayOutSomething;
+ UINT8 OrderedList[8];
+ UINT8 BootOrder[8];
+ UINT8 BootOrderLarge;
+ UINT8 DynamicCheck;
+} MyIfrNVData;
+#pragma pack()
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Vfr.vfr b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Vfr.vfr
new file mode 100644
index 0000000000..ee8df0488c
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/Vfr.vfr
@@ -0,0 +1,627 @@
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+// *++
+//
+// Copyright (c) 2006, Intel Corporation
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// Vfr.vfr
+//
+// Abstract:
+//
+// Sample Setup formset
+//
+// Revision History:
+//
+// --*/
+
+
+#include "DriverSampleStrDefs.h"
+
+#include "NVDataStruc.h"
+
+
+typedef struct {
+ UINT8 Field8;
+ UINT16 Field16;
+ UINT8 OrderedList[3];
+} MyIfrNVData2;
+
+typedef struct {
+ UINT8 Field8;
+ UINT16 Field16;
+ UINT8 OrderedList[3];
+} MyIfrNVData3;
+
+#define MY_TEXT_KEY 0x100
+
+#define LABEL_1_VALUE 0x01
+#define LABEL_2_VALUE 0x1000
+#define LABEL_UPDATE_BBS 0x2222
+#define LABEL_END_UPDATE_BBS 0x2223
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_SET_TITLE),
+ help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),
+ class = 0x10,
+ subclass = 0,
+
+ varstore MyIfrNVData2, key = 0x1234, name = MY_DATA2, guid = FORMSET_GUID;
+
+
+ varstore MyIfrNVData3, key = 0x4321, name = MY_DATA3, guid = FORMSET_GUID;
+
+ form formid = 1,
+ title = STRING_TOKEN(STR_FORM1_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
+
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT);
+
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2);
+
+ banner
+ title = STRING_TOKEN(STR_BANNER_TITLE),
+ line 1,
+ align center;
+
+ banner
+ title = STRING_TOKEN(STR_BANNER_TITLE),
+ line 2,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_BANNER_TITLE),
+ line 2,
+ align right;
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_CPU_STRING),
+ text = STRING_TOKEN(STR_CPU_STRING2),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_EXIT_TEXT),
+ text = STRING_TOKEN(STR_EXIT_TEXT),
+ text = STRING_TOKEN(STR_EXIT_TEXT),
+ flags = INTERACTIVE,
+ key = 0x1237;
+
+ oneof varid = MyIfrNVData.SuppressGrayOutSomething,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT;
+ endoneof;
+
+ oneof varid = MyIfrNVData.BootOrderLarge,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_BOOT_ORDER1), value = 0x0, flags = INTERACTIVE, key = 1;
+ option text = STRING_TOKEN(STR_BOOT_ORDER2), value = 0x1, flags = INTERACTIVE | DEFAULT, key = 2;
+ endoneof;
+
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;
+ label 0;
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),
+ flags = 1, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off
+ key = 0,
+ endcheckbox;
+ endif;
+
+
+ //
+ // Ordered list:
+ // sizeof(MyIfrNVData) storage must be UINT8 array, and
+ // size written for the variable must be size of the entire
+ // variable.
+ //
+ //
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;
+ label LABEL_UPDATE_BBS;
+ orderedlist
+ varid = MyIfrNVData.BootOrder,
+ prompt = STRING_TOKEN(STR_BOOT_OPTIONS),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = RESET_REQUIRED;
+ endlist;
+ label LABEL_END_UPDATE_BBS;
+ endif;
+
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2;
+ orderedlist
+ varid = MyIfrNVData.OrderedList,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 4, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 3, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 2, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_TEXT_HELP), value = 1, flags = RESET_REQUIRED;
+ endlist;
+ endif;
+
+ label 100;
+
+ goto 0x1234,
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC),
+ help = STRING_TOKEN(STR_GOTO_HELP),
+ flags = INTERACTIVE,
+ key = 0x1234;
+
+ goto 0x1234,
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC2),
+ help = STRING_TOKEN(STR_GOTO_HELP),
+ flags = INTERACTIVE,
+ key = 0x1235;
+
+ //
+ // VARSTORE tests
+ //
+ // Till now, been using variable NvData (must be reserved)
+ // now we do a varselect for variable NvData3
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqid MyIfrNVData3.Field16 == MyIfrNVData3.Field16
+ endif;
+ // now we do a varselect_pair for variable NvData2 and NvData3
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqid MyIfrNVData2.Field16 == MyIfrNVData3.Field16
+ endif;
+
+
+ // now we do a varselect_pair for variable NvData and NvData2
+// inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+// ideqid MyIfrNVData2.Field16 == MyIfrNVData.TestLateCheck
+// endif;
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqid MyIfrNVData.TestLateCheck == MyIfrNVData.TestLateCheck2
+ endif;
+
+ oneof varid = MyIfrNVData.TestLateCheck,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = LATE_CHECK | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = LATE_CHECK | DEFAULT | RESET_REQUIRED;
+ endoneof;
+
+ oneof varid = MyIfrNVData.TestLateCheck2,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE2),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = LATE_CHECK | DEFAULT | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = LATE_CHECK | RESET_REQUIRED;
+
+ endoneof;
+
+ oneof varid = MyIfrNVData.QuestionAboutTreeHugging,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 0x03, flags = RESET_REQUIRED;
+
+ endoneof;
+
+ string varid = MyIfrNVData.MyStringData,
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT2),
+ help = STRING_TOKEN(STR_MY_STRING_HELP2),
+ flags = INTERACTIVE,
+ key = 0x1234,
+ minsize = 6,
+ maxsize = 0x14,
+ endstring;
+
+ text
+ help = STRING_TOKEN(STR_GRAYOUT_TEST),
+ text = STRING_TOKEN(STR_GRAYOUT_TEST),
+ text = STRING_TOKEN(STR_GRAYOUT_TEST),
+ flags = INTERACTIVE,
+ key = 0x1555;
+
+ text
+ help = STRING_TOKEN(STR_SUPPRESS_TEST),
+ text = STRING_TOKEN(STR_SUPPRESS_TEST),
+ text = STRING_TOKEN(STR_SUPPRESS_TEST),
+ flags = INTERACTIVE,
+ key = 0x1556;
+
+ text
+ help = STRING_TOKEN(STR_CLEAR_TEST),
+ text = STRING_TOKEN(STR_CLEAR_TEST),
+ text = STRING_TOKEN(STR_CLEAR_TEST),
+ flags = INTERACTIVE,
+ key = 0x1557;
+
+ grayoutif vareqval var(VAR_EQ_TEST_NAME) == 0x1;
+ suppressif vareqval var(VAR_EQ_TEST_NAME) == 0x1000;
+ label 30;
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),
+ flags = 1,
+ key = 0,
+ endcheckbox;
+ endif;
+
+
+ numeric varid = MyIfrNVData.HowOldAreYouInYearsManual,
+ prompt = STRING_TOKEN(STR_NUMERIC_MANUAL_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP0),
+ minimum = 0,
+ maximum = 0xf0, // 0xf0 = 240 in decimal
+ step = 0, // Stepping of 0 equates to a manual entering
+ // of a value, otherwise it will auto-increment
+ // with a left/right arrow
+ default = 21,
+
+ endnumeric;
+
+ numeric varid = MyIfrNVData.HowTallAreYouManual,
+ prompt = STRING_TOKEN(STR_TALL_MANUAL_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP1),
+ minimum = 0,
+ maximum = 300,
+ step = 0, // Stepping of 0 equates to a manual entering
+ // of a value, otherwise it will auto-increment
+ // with a left/right arrow
+ default = 175,
+
+ endnumeric;
+
+ inventory
+ help = STRING_TOKEN(STR_INVENTORY_HELP),
+ text = STRING_TOKEN(STR_INVENTORY_TEXT1),
+ text = STRING_TOKEN(STR_INVENTORY_TEXT2);
+
+
+ restore defaults,
+ formid = 4,
+ prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT),
+ help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP),
+ flags = 0,
+ key = 0;
+
+ save defaults,
+ formid = 4,
+ prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+ help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
+ flags = 0,
+ key = 0;
+
+ //
+ // Case with no flags or key
+ //
+ save defaults,
+ formid = 4,
+ prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+ help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP);
+ //
+ // Case with no key
+ //
+ save defaults,
+ formid = 4,
+ prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+ help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
+ flags = 0;
+ //
+ // Case with no flags
+ //
+ save defaults,
+ formid = 4,
+ prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT),
+ help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP),
+ key = 0;
+
+ label LABEL_2_VALUE;
+
+ grayoutif ideqval MyIfrNVData.HowOldAreYouInYearsManual == 23 AND ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ numeric varid = MyIfrNVData.HowOldAreYouInYears,
+ prompt = STRING_TOKEN(STR_NUMERIC_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP2),
+ minimum = 0,
+ maximum = 243,
+ step = 3,
+ default = 18,
+
+ endnumeric;
+
+ label LABEL_1_VALUE;
+
+ //
+ // Numeric with no step or default specified
+ //
+ numeric varid = MyIfrNVData.HowTallAreYou,
+ prompt = STRING_TOKEN(STR_NUMERIC_PROMPT1),
+ help = STRING_TOKEN(STR_NUMERIC_HELP3),
+ minimum = 0,
+ maximum = 190,
+ // step = 1, // Stepping of 1 if not specified
+ // default = minimum; // if not specified
+ endnumeric;
+ endif;
+
+ string varid = MyIfrNVData.MyStringData,
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT),
+ help = STRING_TOKEN(STR_MY_STRING_HELP),
+ minsize = 6,
+ maxsize = 0x14,
+ endstring;
+
+ password varid = MyIfrNVData.WhatIsThePassword,
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ minsize = 6,
+ maxsize = 20, // new opcode
+ encoding = 1,
+ endpassword;
+ password varid = MyIfrNVData.WhatIsThePassword2,
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ minsize = 6,
+ maxsize = 20, // new opcode
+ encoding = 1,
+ endpassword;
+ //
+ // Test with flags and key fields
+ //
+ password varid = MyIfrNVData.WhatIsThePassword,
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ flags = INTERACTIVE,
+ key = 0x2000,
+ minsize = 6,
+ maxsize = 20, // new opcode
+ encoding = 1,
+ endpassword;
+
+ goto 2,
+ prompt = STRING_TOKEN(STR_GOTO_FORM2), //SecondSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ goto 3,
+ prompt = STRING_TOKEN(STR_GOTO_FORM3), //ThirdSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ endform;
+
+ form formid = 2, // SecondSetupPage,
+ title = STRING_TOKEN(STR_FORM2_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
+
+
+ date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_YEAR_HELP),
+ minimum = 1998,
+ maximum = 2099,
+ step = 1,
+ default = 2004,
+
+ month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_MONTH_HELP),
+ minimum = 1,
+ maximum = 12,
+ step = 1,
+ default = 1,
+
+ day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_DAY_HELP),
+ minimum = 1,
+ maximum = 31,
+ step = 0x1,
+ default = 1,
+
+ enddate;
+
+ time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_HOUR_HELP),
+ minimum = 0,
+ maximum = 23,
+ step = 1,
+ default = 0,
+
+ minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_MINUTE_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_SECOND_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ endtime;
+
+ date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_YEAR_HELP),
+ minimum = 1939,
+ maximum = 2101,
+ step = 1,
+ default = 1964,
+
+ month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_MONTH_HELP),
+ minimum = 1,
+ maximum = 12,
+ step = 1,
+ default = 1,
+
+ day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_DAY_HELP),
+ minimum = 1,
+ maximum = 31,
+ step = 0x1,
+ default = 1,
+
+ enddate;
+
+ time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_HOUR_HELP),
+ minimum = 0,
+ maximum = 23,
+ step = 1,
+ default = 0,
+
+ minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_MINUTE_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_SECOND_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ endtime;
+
+ grayoutif
+ ideqval Date.Day == 21
+ AND
+ ideqval Date.Month == 8;
+
+ hidden value = 32, key = 0x7777;
+
+ endif; // grayoutif
+
+ suppressif
+ ideqval Date.Day == 8
+ AND
+ ideqval Date.Month == 21;
+
+ hidden value = 32, key = 0x7777;
+
+ endif; // suppressif
+
+
+ hidden value = 32, key = 0x1234;
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval MyIfrNVData.HowOldAreYouInYearsManual == 4
+ endif;
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqvallist MyIfrNVData.HowOldAreYouInYearsManual == 1 2 3 4
+ endif;
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqid MyIfrNVData.HowOldAreYouInYearsManual == MyIfrNVData.MyFavoriteNumber
+ endif;
+
+// grayoutif
+//
+// If the day is 31 AND months is any of the following 2, 4, 6, 9, 11
+//
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 31
+ AND
+ ideqvallist Date.Month == 2 4 6 9 11
+ endif;
+
+//
+// If the day is 30 AND month is 2
+//
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 30
+ AND
+ ideqval Date.Month == 2
+ endif;
+
+//
+// If the day is 29 AND month is 2 AND it year is NOT a leapyear
+//
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 0x1D
+ AND
+ ideqval Date.Month == 2
+ AND
+ NOT
+ ideqvallist Date.Year == 2004 2008 20012 20016 2020 2024 2028 2032 2036
+ endif;
+
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),
+ flags = 1,
+ key = 0,
+ endcheckbox;
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1),
+ text = STRING_TOKEN(STR_TEXT_TEXT_2),
+ flags = 0,
+ key = MY_TEXT_KEY;
+
+ goto 1,
+ prompt = STRING_TOKEN(STR_GOTO_FORM1), //MainSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ endform;
+
+ form formid = 3, title = STRING_TOKEN(STR_FORM3_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
+
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);
+
+ endif; //end grayoutif
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);
+
+ endform;
+
+ form formid = 4, title = STRING_TOKEN(STR_FORM3_TITLE);
+
+ endform;
+
+ form formid = 0x1234, // Dynamically created page,
+ title = STRING_TOKEN(STR_DYNAMIC_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
+
+ label 0x1234;
+
+ endform;
+
+endformset;
diff --git a/IntelFrameworkModulePkg/Universal/DriverSampleDxe/VfrStrings.uni b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
new file mode 100644
index 0000000000..9e9dbf5454
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/CommonHeader.h b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/CommonHeader.h
new file mode 100644
index 0000000000..2506b805ac
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/CommonHeader.h
@@ -0,0 +1,41 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <FrameworkDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Guid/GlobalVariable.h>
+#include <Protocol/FormCallback.h>
+#include <Protocol/FrameworkHii.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/IfrSupportLibFramework.h>
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Fonts.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Fonts.c
new file mode 100644
index 0000000000..2c3980da63
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Fonts.c
@@ -0,0 +1,271 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Fonts.c
+
+Abstract:
+
+ This file contains the Glyph/Font processing code to the HII database.
+
+--*/
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+//
+// We only need to define a wide glyph, since we will seed the narrow glyph with EFI_NARROW_GLYPH size of
+// this data structure
+//
+UINT8 mUnknownGlyph[38] = {
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xAA,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xAA
+};
+
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus
+ )
+/*++
+
+Routine Description:
+ Translates a Unicode character into the corresponding font glyph.
+ If the Source was pointing to a non-spacing character, the next Source[*Index]
+ character will be parsed and OR'd to the GlyphBuffer until a spacing character
+ is found in the Source. Since non-spacing characters are considered to be the
+ same pixel width as a regular character their BitWidth will be reflected correctly
+ however due to their special attribute, they are considered to be zero advancing width.
+ This basically means that the cursor would not advance, thus the character that follows
+ it would overlay the non-spacing character. The Index is modified to reflect both the
+ incoming array entry into the Source string but also the outgoing array entry after having
+ parsed the equivalent of a single Glyph's worth of data.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_GLOBAL_DATA *GlobalData;
+ EFI_HII_DATA *HiiData;
+ UINTN Count;
+ BOOLEAN Narrow;
+ UINTN Location;
+ UINTN SearchLocation;
+ UINTN Value;
+ CHAR16 Character;
+ UINTN Attributes;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ GlobalData = HiiData->GlobalData;
+ Count = sizeof (GlobalData->NarrowGlyphs->GlyphCol1);
+
+ Location = *Index;
+ SearchLocation = *Index;
+ Narrow = TRUE;
+
+ if (Source[Location] == NARROW_CHAR || Source[Location] == WIDE_CHAR) {
+ *InternalStatus = 0;
+ }
+ //
+ // We don't know what glyph database to look in - let's figure it out
+ //
+ if (*InternalStatus == 0) {
+ //
+ // Determine if we are looking for narrow or wide glyph data
+ //
+ do {
+ if (Source[SearchLocation] == NARROW_CHAR || Source[SearchLocation] == WIDE_CHAR) {
+ //
+ // We found something that identifies what glyph database to look in
+ //
+ if (Source[SearchLocation] == WIDE_CHAR) {
+ Narrow = FALSE;
+ *BitWidth = WIDE_WIDTH;
+ *InternalStatus = WIDE_CHAR;
+ Location++;
+ break;
+ } else {
+ Narrow = TRUE;
+ *BitWidth = NARROW_WIDTH;
+ *InternalStatus = NARROW_CHAR;
+ Location++;
+ break;
+ }
+ }
+ } while (SearchLocation-- > 0);
+ }
+
+ if (*InternalStatus == NARROW_CHAR) {
+ Narrow = TRUE;
+ *BitWidth = NARROW_WIDTH;
+ } else if (*InternalStatus == WIDE_CHAR) {
+ Narrow = FALSE;
+ *BitWidth = WIDE_WIDTH;
+ } else {
+ //
+ // Without otherwise knowing what the width is narrow (e.g. someone passed in a string with index of 0
+ // we wouldn't be able to determine the width of the data.)
+ // BUGBUG - do we go to wide database and if exist, ignore narrow? Check Unicode spec....
+ //
+ Narrow = TRUE;
+ *BitWidth = NARROW_WIDTH;
+ }
+
+ Character = Source[Location];
+
+ if (Narrow) {
+ if (GlobalData->NarrowGlyphs[Character].UnicodeWeight != 0x0000) {
+ *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]);
+ Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING;
+ } else {
+ //
+ // Glyph is uninitialized - return an error, but hand back the glyph
+ //
+ *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]);
+ *Index = (UINT16) (Location + 1);
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // Wide character
+ //
+ if (GlobalData->WideGlyphs[Character].UnicodeWeight != 0x0000) {
+ *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]);
+ Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING;
+ } else {
+ //
+ // Glyph is uninitialized - return an error, but hand back the glyph
+ //
+ *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]);
+ *Index = (UINT16) (Location + 1);
+ return EFI_NOT_FOUND;
+ }
+ }
+ //
+ // This is a non-spacing character. It will be followed by either more non-spacing
+ // characters or a regular character. We need to OR together the data associated with each.
+ //
+ for (; Attributes != 0; Location++) {
+ //
+ // Character is the Unicode value which is the index into the Glyph array.
+ //
+ Character = Source[Location];
+
+ if (Narrow) {
+ for (Value = 0; Value != Count; Value++) {
+ *GlyphBuffer[Location + Value] = (UINT8) (*GlyphBuffer[Location + Value] |
+ GlobalData->NarrowGlyphs[Character].GlyphCol1[Value]);
+ }
+
+ Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING;
+ } else {
+ for (Value = 0; Value != Count; Value++) {
+ *GlyphBuffer[Location + Value] = (UINT8) (*GlyphBuffer[Location + Value] |
+ GlobalData->WideGlyphs[Character].GlyphCol1[Value]);
+ *GlyphBuffer[Location + Value + Count] = (UINT8) (*GlyphBuffer[Location + Value + Count] |
+ GlobalData->WideGlyphs[Character].GlyphCol2[Value]);
+ }
+
+ Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING;
+ }
+ }
+ //
+ // Source[*Index] should point to the next character to process
+ //
+ *Index = (UINT16) (Location + 1);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiGlyphToBlt (
+ IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN Count,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+{
+ UINTN X;
+ UINTN Y;
+
+ //
+ // Convert Monochrome bitmap of the Glyph to BltBuffer structure
+ //
+ for (Y = 0; Y < Height; Y++) {
+ for (X = 0; X < Width; X++) {
+ if ((((EFI_NARROW_GLYPH *) GlyphBuffer)->GlyphCol1[Y] & (1 << X)) != 0) {
+ BltBuffer[Y * Width * Count + (Width - X - 1)] = Foreground;
+ } else {
+ BltBuffer[Y * Width * Count + (Width - X - 1)] = Background;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Forms.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Forms.c
new file mode 100644
index 0000000000..c9a8d9aaf4
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Forms.c
@@ -0,0 +1,1582 @@
+/**@file
+ This file contains the form processing code to the HII database.
+
+Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+STATIC
+CHAR16*
+Ascii2Unicode (
+ OUT CHAR16 *UnicodeStr,
+ IN CHAR8 *AsciiStr
+ )
+/*++
+
+ Routine Description:
+
+ This function converts ASCII string to Unicode string.
+
+ Arguments:
+
+ UnicodeStr - NULL terminated Unicode output string.
+ AsciieStr - NULL terminated ASCII input string.
+
+ Returns:
+
+ Start of the Unicode ouput string.
+
+--*/
+
+{
+ CHAR16 *Str = UnicodeStr;
+ while (TRUE) {
+ *(UnicodeStr++) = (CHAR16) *AsciiStr;
+ if (*(AsciiStr++) == '\0') {
+ return Str;
+ }
+ }
+}
+
+STATIC
+CHAR8*
+Unicode2Ascii (
+ OUT CHAR8 *AsciiStr,
+ IN CHAR16 *UnicodeStr
+ )
+/*++
+
+ Routine Description:
+
+ This function converts Unicode string to ASCII string.
+
+ Arguments:
+
+ AsciieStr - NULL terminated ASCII output string.
+ UnicodeStr - NULL terminated Unicode input string.
+
+ Returns:
+
+ Start of the ASCII ouput string.
+
+--*/
+
+{
+ CHAR8 *Str = AsciiStr;
+ while (TRUE) {
+ *(AsciiStr++) = (CHAR8) *UnicodeStr;
+ if (*(UnicodeStr++) == '\0') {
+ return Str;
+ }
+ }
+}
+
+STATIC
+VOID
+ExtractDevicePathData (
+ IN EFI_HII_DATA_TABLE *DataTable,
+ IN UINT8 *IfrData,
+ IN OUT UINT8 **ExportBufferPtr
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINT8 *ExportBuffer;
+
+ ExportBuffer = *ExportBufferPtr;
+
+ //
+ // BUGBUG - don't have devicepath data yet, setting dummy value
+ //
+ DataTable++;
+ ExportBuffer = (UINT8 *) DataTable;
+ ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH;
+ ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ //
+ // BUGBUG - part of hack - skip the Device Path Pack.....place some data
+ //
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK);
+
+ ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type = EFI_END_ENTIRE_DEVICE_PATH;
+ ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+
+ //
+ // BUGBUG - still part of hack....
+ //
+ ExportBuffer = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ *ExportBufferPtr = ExportBuffer;
+}
+
+STATIC
+VOID
+ExtractVariableData (
+ IN OUT EFI_HII_DATA_TABLE *DataTable,
+ IN UINT8 *IfrData,
+ IN OUT UINT8 **ExportBufferPtr
+ )
+/*++
+
+Routine Description:
+
+ This function extract the EFI_HII_VARIABLE_PACK portion from the
+ each of the EFI_HII_PACKAGE_INSTANCE in HII handle database.
+
+Arguments:
+
+ DataTable - On input, this parameter point to the EFI_HII_DATA_TABLE structure
+ of the final data buffer for the EFI_HII_EXPORT interface. This function
+ update the NumberOfVariableData attribute.
+ IfrData - It points to a staring address of a EFI_HII_IFR_PACK structure.
+ ExportBufferPtr - On input, it points the starting address of the data buffer to
+ host the variable pack. On output, it is the starting address
+ of data buffer for the next extraction operation.
+Returns:
+
+ VOID
+
+--*/
+{
+ EFI_HII_VARIABLE_PACK *VariableContents;
+ UINT8 *ExportBuffer;
+ UINTN Index;
+ UINTN Index2;
+ UINTN TempValue;
+ UINTN TempValue2;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_PHYSICAL_ADDRESS CallbackHandle;
+ EFI_STATUS Status;
+ CHAR16 *String;
+
+ FormCallback = NULL;
+ CallbackHandle = 0;
+ ExportBuffer = *ExportBufferPtr;
+
+ for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;
+
+ switch (IfrData[Index]) {
+ case EFI_IFR_FORM_SET_OP:
+ TempValue = EFI_HII_VARIABLE;
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
+ CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));
+
+ //
+ // If the variable has 0 size, do not process it
+ //
+ if (TempValue == 0) {
+ break;
+ }
+ //
+ // Add the size of the variable pack overhead. Later, will also add the size of the
+ // name of the variable.
+ //
+ TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);
+
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
+ CopyMem (
+ &CallbackHandle,
+ &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle,
+ sizeof (EFI_PHYSICAL_ADDRESS)
+ );
+ if (CallbackHandle != 0) {
+ Status = gBS->HandleProtocol (
+ (EFI_HANDLE) (UINTN) CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID *) &FormCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // Since we have a "Setup" variable that wasn't specified by a variable op-code
+ // it will have a VariableId of 0. All other variable op-codes will have a designation
+ // of VariableId 1+
+ //
+ TempValue = 0;
+ CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16));
+ CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID));
+ TempValue = sizeof (SETUP_MAP_NAME);
+ CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));
+
+ //
+ // Add the size of the name to the Header Length
+ //
+ TempValue2 = 0;
+ CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));
+ TempValue2 = TempValue + TempValue2;
+ CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
+ CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME));
+ ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME);
+
+ CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));
+
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
+ Status = FormCallback->NvRead (
+ FormCallback,
+ (CHAR16 *) SETUP_MAP_NAME,
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
+ NULL,
+ &TempValue,
+ ExportBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = gRT->GetVariable (
+ (CHAR16 *) SETUP_MAP_NAME,
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
+ NULL,
+ &TempValue,
+ ExportBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);
+ DataTable->NumberOfVariableData++;
+ break;
+
+ case EFI_IFR_VARSTORE_OP:
+ TempValue = EFI_HII_VARIABLE;
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
+ CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));
+
+ //
+ // If the variable has 0 size, do not process it
+ //
+ if (TempValue == 0) {
+ break;
+ }
+ //
+ // Add the size of the variable pack overhead. Later, will also add the size of the
+ // name of the variable.
+ //
+ TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);
+
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
+ CopyMem (&VariableContents->VariableId, &((EFI_IFR_VARSTORE *) &IfrData[Index])->VarId, sizeof (UINT16));
+ CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Guid, sizeof (EFI_GUID));
+ TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &IfrData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);
+ TempValue = TempValue * 2;
+ CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));
+
+ //
+ // Add the size of the name to the Header Length
+ //
+ TempValue2 = 0;
+ CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));
+ TempValue2 = TempValue + TempValue2;
+ CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
+ String = (CHAR16 *) ExportBuffer;
+ for (Index2 = 0; Index2 < TempValue / 2; Index2++) {
+ ExportBuffer[Index2 * 2] = IfrData[Index + sizeof (EFI_IFR_VARSTORE) + Index2];
+ ExportBuffer[Index2 * 2 + 1] = 0;
+ }
+
+ ExportBuffer = ExportBuffer + TempValue;
+
+ CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));
+
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
+ Status = FormCallback->NvRead (
+ FormCallback,
+ String,
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
+ NULL,
+ &TempValue,
+ ExportBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = gRT->GetVariable (
+ String,
+ (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
+ NULL,
+ &TempValue,
+ ExportBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);
+ DataTable->NumberOfVariableData++;
+ break;
+ }
+
+ Index = IfrData[Index + 1] + Index;
+ }
+ //
+ // If we have added a variable pack, add a dummy empty one to signify the end
+ //
+ if (ExportBuffer != *ExportBufferPtr) {
+ VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;
+ TempValue = EFI_HII_VARIABLE;
+ CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
+ TempValue = sizeof (EFI_HII_VARIABLE_PACK);
+ CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
+ }
+
+ *ExportBufferPtr = ExportBuffer;
+}
+
+EFI_STATUS
+EFIAPI
+HiiExportDatabase (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function allows a program to extract a form or form package that has
+ previously been registered with the EFI HII database.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_IFR_PACK *FormPack;
+ UINT8 *RawData;
+ UINT8 *ExportBuffer;
+ EFI_HII_EXPORT_TABLE *ExportTable;
+ EFI_HII_DATA_TABLE *DataTable;
+ BOOLEAN VariableExist;
+ UINT16 NumberOfHiiDataTables;
+ UINTN SizeNeeded;
+ UINTN Index;
+ UINTN VariableSize;
+ UINTN TempValue;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+
+ FormPack = NULL;
+ RawData = NULL;
+ PackageInstance = NULL;
+ NumberOfHiiDataTables = 0;
+ VariableSize = 0;
+ TempValue = 0;
+ SizeNeeded = sizeof (EFI_HII_EXPORT_TABLE);
+
+ //
+ // How many total tables are there?
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ if ((Handle != 0) && (Handle != HandleDatabase->Handle)) {
+ continue;
+ }
+
+ VariableExist = FALSE;
+ NumberOfHiiDataTables++;
+ PackageInstance = HandleDatabase->Buffer;
+ if (PackageInstance == NULL) {
+ continue;
+ }
+ //
+ // Extract Size of Export Package
+ //
+ SizeNeeded = SizeNeeded + PackageInstance->IfrSize
+ + PackageInstance->StringSize
+ + sizeof (EFI_HII_DATA_TABLE)
+ + sizeof (EFI_HII_DEVICE_PATH_PACK);
+
+ //
+ // BUGBUG We aren't inserting Device path data yet
+ //
+ SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+ //
+ // Extract Size of Variable Data
+ //
+ if (PackageInstance->IfrSize > 0) {
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+ } else {
+ //
+ // No IFR? No variable information
+ //
+ continue;
+ }
+
+ RawData = (UINT8 *) FormPack;
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ switch (RawData[Index]) {
+ case EFI_IFR_FORM_SET_OP:
+ CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16));
+ SizeNeeded = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK);
+ VariableExist = TRUE;
+ break;
+
+ case EFI_IFR_VARSTORE_OP:
+ CopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16));
+ SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK);
+ //
+ // We will be expanding the stored ASCII name to a Unicode string. This will cause some memory overhead
+ // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another
+ // instance of it. Essentially, 2 ASCII strings == 1 Unicode string in size.
+ //
+ TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);
+ SizeNeeded = SizeNeeded + TempValue * 2;
+ VariableExist = TRUE;
+ break;
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+ //
+ // If a variable exists for this handle, add an additional variable pack overhead to
+ // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs
+ //
+ if (VariableExist) {
+ SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK);
+ }
+ }
+
+ if (SizeNeeded > *BufferSize) {
+ *BufferSize = SizeNeeded;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Zero out the incoming buffer
+ //
+ ZeroMem (Buffer, *BufferSize);
+
+ //
+ // Cast the Buffer to EFI_HII_EXPORT_TABLE
+ //
+ ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer;
+
+ //
+ // Set the Revision for the Export Table
+ //
+ CopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID));
+
+ ExportBuffer = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE));
+ HandleDatabase = HiiData->DatabaseHead;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ DataTable = (EFI_HII_DATA_TABLE *) ExportBuffer;
+ PackageInstance = HandleDatabase->Buffer;
+ //
+ // If not asking for a specific handle, export the entire database
+ //
+ if (Handle == 0) {
+ ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;
+ CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));
+ DataTable->HiiHandle = PackageInstance->Handle;
+ DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE));
+
+ //
+ // Start Dumping DevicePath
+ //
+ ExtractDevicePathData (DataTable, RawData, &ExportBuffer);
+
+ if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) {
+ //
+ // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse
+ //
+ DataTable->DevicePathOffset = 0;
+ }
+
+ DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ if (PackageInstance->IfrSize > 0) {
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+
+ RawData = (UINT8 *) FormPack;
+ TempValue = 0;
+
+ //
+ // Start dumping the Variable Data
+ //
+ ExtractVariableData (DataTable, RawData, &ExportBuffer);
+ DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
+ DataTable->VariableDataOffset = 0;
+ }
+ //
+ // Start dumping the IFR data (Note: It is in an IFR PACK)
+ //
+ CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ //
+ // Start dumping the String data (Note: It is in a String PACK)
+ //
+ if (PackageInstance->StringSize > 0) {
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
+
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ for (; TempValue != 0;) {
+ DataTable->NumberOfLanguages++;
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ }
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
+ } else {
+ DataTable->StringDataOffset = 0;
+ }
+ } else {
+ //
+ // 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)
+ //
+ DataTable->VariableDataOffset = 0;
+ DataTable->IfrDataOffset = 0;
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ //
+ // Start dumping the String data - NOTE: It is in String Pack form
+ //
+ if (PackageInstance->StringSize > 0) {
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
+
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ for (; TempValue != 0;) {
+ DataTable->NumberOfLanguages++;
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ }
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
+ } else {
+ DataTable->StringDataOffset = 0;
+ }
+ }
+ } else {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;
+ DataTable->HiiHandle = PackageInstance->Handle;
+ CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));
+
+ //
+ // Start Dumping DevicePath
+ //
+ ExtractDevicePathData (DataTable, RawData, &ExportBuffer);
+ DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ if (PackageInstance->IfrSize > 0) {
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+
+ RawData = (UINT8 *) FormPack;
+ TempValue = 0;
+
+ //
+ // Start dumping the Variable Data
+ //
+ ExtractVariableData (DataTable, RawData, &ExportBuffer);
+ DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
+ DataTable->VariableDataOffset = 0;
+ }
+ //
+ // Start dumping the IFR data
+ //
+ CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
+ ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ //
+ // Start dumping the String data - NOTE: It is in String Pack form
+ //
+ if (PackageInstance->StringSize > 0) {
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
+
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ for (; TempValue != 0;) {
+ DataTable->NumberOfLanguages++;
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ }
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
+ } else {
+ DataTable->StringDataOffset = 0;
+ }
+ } else {
+ //
+ // No IFR? No variable information. If Offset is 0, means there is none.
+ //
+ DataTable->VariableDataOffset = 0;
+ DataTable->IfrDataOffset = 0;
+ DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
+
+ //
+ // Start dumping the String data - Note: It is in String Pack form
+ //
+ if (PackageInstance->StringSize > 0) {
+ RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
+ CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
+ DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
+
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ for (; TempValue != 0;) {
+ DataTable->NumberOfLanguages++;
+ ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
+ CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
+ }
+
+ ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
+ } else {
+ DataTable->StringDataOffset = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiGetForms (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLengthTemp,
+ OUT UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function allows a program to extract a form or form package that has
+ previously been registered with the EFI HII database.
+
+Arguments:
+ This - A pointer to the EFI_HII_PROTOCOL instance.
+
+ Handle - Handle on which the form resides. Type EFI_HII_HANDLE is defined in
+ EFI_HII_PROTOCOL.NewPack() in the Packages section.
+
+ FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.
+ Type EFI_FORM_ID is defined in "Related Definitions" below.
+
+ BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
+ the length was sufficient and, if it was not, the length that is required to fit the
+ requested form(s).
+
+ Buffer - The buffer designed to receive the form(s).
+
+Returns:
+
+ EFI_SUCCESS - Buffer filled with the requested forms. BufferLength
+ was updated.
+
+ EFI_INVALID_PARAMETER - The handle is unknown.
+
+ EFI_NOT_FOUND - A form on the requested handle cannot be found with the
+ requested FormId.
+
+ EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_IFR_PACK *FormPack;
+ EFI_IFR_FORM *Form;
+ EFI_IFR_OP_HEADER *Location;
+ UINT16 *BufferLength = (UINT16 *) BufferLengthTemp;
+ UINTN FormLength;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+
+ PackageInstance = NULL;
+
+ FormLength = 0;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ break;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (PackageInstance->IfrSize > 0) {
+ FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);
+ } else {
+ //
+ // If there is no IFR data return an error
+ //
+ return EFI_NOT_FOUND;
+ }
+ //
+ // If requesting the entire Form Package
+ //
+ if (FormId == 0) {
+ //
+ // Return an error if buffer is too small
+ //
+ if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {
+ *BufferLength = (UINT16) PackageInstance->IfrSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem (Buffer, FormPack, PackageInstance->IfrSize);
+ return EFI_SUCCESS;
+ } else {
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+ Location = (EFI_IFR_OP_HEADER *) FormPack;
+
+ //
+ // Look for the FormId requested
+ //
+ for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {
+ switch (Location->OpCode) {
+ case EFI_IFR_FORM_OP:
+ Form = (EFI_IFR_FORM *) Location;
+
+ //
+ // If we found a Form Op-code and it is of the correct Id, copy it and return
+ //
+ if (Form->FormId == FormId) {
+ //
+ // Calculate the total size of form
+ //
+ for (FormLength = 0; Location->OpCode != EFI_IFR_END_FORM_OP; ) {
+ FormLength += Location->Length;
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ }
+ FormLength += Location->Length;
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+
+ if ((Buffer == NULL) || (FormLength > *BufferLength)) {
+ *BufferLengthTemp = FormLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Rewind to start offset of the found Form
+ //
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *)Location - FormLength);
+ CopyMem (Buffer, Location, FormLength);
+ return EFI_SUCCESS;
+ }
+
+ default:
+ break;
+ }
+ //
+ // Go to the next Op-Code
+ //
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+//
+// Helper functions to HiiGetDefaultImage()
+//
+
+STATIC
+UINT8*
+HiiGetDefaultImageInitPack (
+ IN OUT EFI_HII_VARIABLE_PACK_LIST *VariablePackItem,
+ IN EFI_IFR_VARSTORE *VarStore
+ )
+/*++
+
+ Routine Description:
+
+ Initialize the EFI_HII_VARIABLE_PACK_LIST structure and
+ prepare it ready to be used by HiiGetDefaultImagePopulateMap ().
+
+ Arguments:
+
+ VariablePackItem - Variable Package List.
+ VarStore - IFR variable storage.
+
+ Returns:
+
+ Return the pointer to the Map space.
+
+--*/
+{
+ CHAR16 *Name16;
+ CHAR8 *Name8;
+ CHAR8 *Map;
+ EFI_HII_VARIABLE_PACK *VariablePack;
+
+ //
+ // Set pointer the pack right after the node
+ //
+ VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1);
+ VariablePack = VariablePackItem->VariablePack;
+
+ //
+ // Copy the var name to VariablePackItem from VarStore
+ // Needs ASCII->Unicode conversion.
+ //
+ ASSERT (VarStore->Header.Length > sizeof (*VarStore));
+ Name8 = (CHAR8 *) (VarStore + 1);
+ Name16 = (CHAR16 *) (VariablePack + 1);
+ Ascii2Unicode (Name16, Name8);
+
+ //
+ // Compute the other fields of the VariablePackItem
+ //
+ VariablePack->VariableId = VarStore->VarId;
+ CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID));
+ VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2);
+ VariablePack->Header.Length = sizeof (*VariablePack)
+ + VariablePack->VariableNameLength
+ + VarStore->Size;
+ //
+ // Return the pointer to the Map space.
+ //
+ Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength;
+
+ return (UINT8 *)Map;
+}
+
+STATIC
+VOID
+HiiGetDefaultImagePopulateMap (
+ IN OUT UINT8 *Map,
+ IN EFI_IFR_OP_HEADER *FormSet,
+ IN EFI_IFR_VARSTORE *VarStore,
+ IN UINTN DefaultMask
+ )
+/*++
+
+ Routine Description:
+
+ Fill the Map with all the default values either from NV or Hii database.
+
+ Arguments:
+
+ Map - Memory pointer to hold the default values.
+ FormSet - The starting EFI_IFR_OP_HEADER to begin retriving default values.
+ VarStore - IFR variable storage.
+ DefaultMask - The mask used to get the default variable.
+
+ Returns:
+
+ VOID
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_OP_HEADER *IfrItem;
+ UINT16 VarId;
+ EFI_IFR_VARSTORE_SELECT *VarSelect;
+ EFI_IFR_ONE_OF_OPTION *OneOfOpt;
+ EFI_IFR_CHECKBOX *CheckBox;
+ EFI_IFR_NUMERIC *Numeric;
+ UINTN Size;
+ UINTN SizeTmp;
+ EFI_IFR_NV_DATA *IfrNvData;
+ EFI_GUID Guid;
+ CHAR16 *Name16;
+ CHAR8 *Name8;
+ EFI_HANDLE CallbackHandle;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProt;
+
+ //
+ // Get the Map's Name/Guid/Szie from the Varstore.
+ // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode.
+ //
+ ASSERT (VarStore->Header.Length >= sizeof (*VarStore));
+ Name8 = (CHAR8 *) (VarStore + 1);
+ Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16));
+ Ascii2Unicode (Name16, Name8);
+ CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID));
+ Size = VarStore->Size;
+
+ //
+ // First, check if the map exists in the NV. If so, get it from NV and exit.
+ //
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
+ //
+ // Check if Manufaturing Defaults exist in the NV.
+ //
+ Status = EfiLibHiiVariableOverrideBySuffix (
+ HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE,
+ Name16,
+ &Guid,
+ Size,
+ Map
+ );
+ } else {
+ //
+ // All other cases default to Defaults. Check if Defaults exist in the NV.
+ //
+ Status = EfiLibHiiVariableOverrideBySuffix (
+ HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE,
+ Name16,
+ &Guid,
+ Size,
+ Map
+ );
+ }
+ if (!EFI_ERROR (Status)) {
+ //
+ // Either Defaults/Manufacturing variable exists and appears to be valid.
+ // The map is read, exit w/ success now.
+ //
+ FreePool (Name16);
+ return;
+ }
+
+ //
+ // First, prime the map with what already is in the NV.
+ // This is needed to cover a situation where the IFR does not contain all the
+ // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default.
+ // Ignore status. Either it gets read or not.
+ //
+ FormCallbackProt = NULL;
+ CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle));
+ if (CallbackHandle != NULL) {
+ Status = gBS->HandleProtocol (
+ (EFI_HANDLE) (UINTN) CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID *) &FormCallbackProt
+ );
+ }
+ if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) {
+ //
+ // Attempt to read using NvRead() callback. Probe first for existence and correct variable size.
+ //
+ SizeTmp = 0;
+ Status = FormCallbackProt->NvRead (
+ FormCallbackProt,
+ Name16,
+ &Guid,
+ 0,
+ &SizeTmp,
+ NULL
+ );
+ if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) {
+ Status = FormCallbackProt->NvRead (
+ FormCallbackProt,
+ Name16,
+ &Guid,
+ 0,
+ &SizeTmp,
+ Map
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (SizeTmp == Size);
+ }
+ } else {
+ //
+ // No callback available for this formset, read straight from NV. Deliberately ignore the Status.
+ // The buffer will only be written if variable exists nd has correct size.
+ //
+ Status = EfiLibHiiVariableRetrieveFromNv (
+ Name16,
+ &Guid,
+ Size,
+ (VOID **) &Map
+ );
+ }
+
+ //
+ // Iterate all IFR statements and for applicable, retrieve the default into the Map.
+ //
+ for (IfrItem = FormSet, VarId = 0;
+ IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP;
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length)
+ ) {
+
+ //
+ // Observe VarStore switch.
+ //
+ if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) {
+ VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem;
+ VarId = VarSelect->VarId;
+ continue;
+ }
+
+
+ //
+ // Skip opcodes that reference other VarStore than that specific to current map.
+ //
+ if (VarId != VarStore->VarId) {
+ continue;
+ }
+
+ //
+ // Extract the default value from this opcode if applicable, and apply it to the map.
+ //
+ IfrNvData = (EFI_IFR_NV_DATA *) IfrItem;
+ switch (IfrItem->OpCode) {
+
+ case EFI_IFR_ONE_OF_OP:
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
+ //
+ // Get to the first EFI_IFR_ONE_OF_OPTION_OP
+ //
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length);
+ ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode);
+
+ OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;
+ //
+ // In the worst case, the first will be the default.
+ //
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
+
+ while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) {
+
+ OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
+ if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) {
+ //
+ // In the worst case, the first will be the default.
+ //
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
+ break;
+ }
+ } else {
+ if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) {
+ //
+ // In the worst case, the first will be the default.
+ //
+ CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
+ break;
+ }
+ }
+
+ IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length);
+ }
+ continue;
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
+ CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem;
+ if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
+ if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) {
+ *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;
+ }
+ } else {
+ if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) {
+ *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;
+ }
+ }
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
+ Numeric = (EFI_IFR_NUMERIC *) IfrItem;
+ CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth);
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ //
+ // No support for default value for these opcodes.
+ //
+ break;
+ }
+ }
+
+ FreePool (Name16);
+
+}
+
+
+EFI_STATUS
+EFIAPI
+HiiGetDefaultImage (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ )
+/*++
+
+ Routine Description:
+
+ This function allows a program to extract the NV Image
+ that represents the default storage image
+
+ Arguments:
+ This - A pointer to the EFI_HII_PROTOCOL instance.
+ Handle - The HII handle from which will have default data retrieved.
+ UINTN - Mask used to retrieve the default image.
+ VariablePackList - Callee allocated, tightly-packed, link list data
+ structure that contain all default varaible packs
+ from the Hii Database.
+
+ Returns:
+ EFI_NOT_FOUND - If Hii database does not contain any default images.
+ EFI_INVALID_PARAMETER - Invalid input parameter.
+ EFI_SUCCESS - Operation successful.
+
+--*/
+{
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_IFR_OP_HEADER *FormSet;
+ EFI_IFR_OP_HEADER *IfrItem;
+ EFI_IFR_VARSTORE *VarStore;
+ EFI_IFR_VARSTORE *VarStoreDefault;
+ UINTN SetupMapNameSize;
+ UINTN SizeOfMaps;
+ EFI_HII_VARIABLE_PACK_LIST *PackList;
+ EFI_HII_VARIABLE_PACK_LIST *PackListNext;
+ EFI_HII_VARIABLE_PACK_LIST *PackListLast;
+ UINT8 *Map;
+
+
+ //
+ // Find the IFR pack from the handle. Then get the formset from the pack.
+ //
+ PackageInstance = NULL;
+ HandleDatabase = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead;
+ for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ break;
+ }
+ }
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK));
+
+ //
+ // Get the sizes of all the VARSTOREs in this VFR.
+ // Then allocate enough space for all of them plus all maps
+ //
+ SizeOfMaps = 0;
+ IfrItem = FormSet;
+ while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {
+
+ if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {
+ VarStore = (EFI_IFR_VARSTORE *) IfrItem;
+ //
+ // Size of the map
+ //
+ SizeOfMaps += VarStore->Size;
+ //
+ // add the size of the string, in Unicode
+ //
+ SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2;
+ //
+ // Space for node
+ //
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK);
+ //
+ // Space for linked list node
+ //
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST);
+ }
+
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);
+ }
+
+ //
+ // If the FormSet OpCode has a non-zero NvDataSize. There is a default
+ // NvMap with ID=0, GUID that of the formset itself and "Setup" as name.
+ //
+ SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1;
+ VarStoreDefault = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize);
+
+ if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) {
+
+ VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP;
+ VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize);
+ Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME);
+ CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID));
+ VarStoreDefault->VarId = 0;
+ VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize;
+
+ //
+ // Size of the map
+ //
+ SizeOfMaps += VarStoreDefault->Size;
+ //
+ // add the size of the string
+ //
+ SizeOfMaps += sizeof (SETUP_MAP_NAME);
+ //
+ // Space for node
+ //
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK);
+ //
+ // Space for linked list node
+ //
+ SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST);
+ }
+
+ if (0 == SizeOfMaps) {
+ //
+ // The IFR does not have any explicit or default map(s).
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate the return buffer
+ //
+ PackList = AllocateZeroPool (SizeOfMaps);
+ ASSERT (NULL != PackList);
+
+ PackListNext = PackList;
+ PackListLast = PackList;
+
+ //
+ // Handle the default map first, if any.
+ //
+ if (0 != VarStoreDefault->Size) {
+
+ Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault);
+
+ HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask);
+
+ PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);
+ PackListLast = PackListNext;
+ PackListNext = PackListNext->NextVariablePack;
+ }
+
+
+ //
+ // Handle the explicit varstore(s)
+ //
+ IfrItem = FormSet;
+ while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {
+
+ if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {
+
+ Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem);
+
+ HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask);
+
+ PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);
+ PackListLast = PackListNext;
+ PackListNext = PackListNext->NextVariablePack;
+ }
+
+ IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);
+ }
+
+ PackListLast->NextVariablePack = NULL;
+ *VariablePackList = PackList;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+HiiUpdateForm (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN EFI_HII_UPDATE_DATA *Data
+ )
+/*++
+
+Routine Description:
+ This function allows the caller to update a form that has
+ previously been registered with the EFI HII database.
+
+Arguments:
+ Handle - Hii Handle associated with the Formset to modify
+ Label - Update information starting immediately after this label in the IFR
+ AddData - If TRUE, add data. If FALSE, remove data
+ Data - If adding data, this is the pointer to the data to add
+
+Returns:
+ EFI_SUCCESS - Update success.
+ Other - Update fail.
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_IFR_PACK *FormPack;
+ EFI_IFR_OP_HEADER *Location;
+ EFI_IFR_OP_HEADER *DataLocation;
+ UINT8 *OtherBuffer;
+ UINT8 *TempBuffer;
+ UINT8 *OrigTempBuffer;
+ UINTN TempBufferSize;
+ UINTN Index;
+
+ OtherBuffer = NULL;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+
+ PackageInstance = NULL;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ break;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Calculate and allocate space for retrieval of IFR data
+ //
+ DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;
+ TempBufferSize = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance);
+
+ for (Index = 0; Index < Data->DataCount; Index++) {
+ TempBufferSize += DataLocation->Length;
+ DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);
+ }
+
+ TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize;
+
+ TempBuffer = AllocateZeroPool (TempBufferSize);
+ ASSERT (TempBuffer != NULL);
+
+ OrigTempBuffer = TempBuffer;
+
+ //
+ // We update only packages with IFR information in it
+ //
+ if (PackageInstance->IfrSize == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (
+ TempBuffer,
+ PackageInstance,
+ ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance))
+ );
+
+ TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance));
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+ Location = (EFI_IFR_OP_HEADER *) FormPack;
+
+ //
+ // Look for the FormId requested
+ //
+ for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {
+ switch (Location->OpCode) {
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // If the FormSet has an update pending, pay attention.
+ //
+ if (Data->FormSetUpdate) {
+ ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle;
+ }
+
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ //
+ // If the Form has an update pending, pay attention.
+ //
+ if (Data->FormUpdate) {
+ ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle;
+ }
+
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+ break;
+
+ case EFI_IFR_LABEL_OP:
+ //
+ // If the label does not match the requested update point, ignore it
+ //
+ if (((EFI_IFR_LABEL *) Location)->LabelId != Label) {
+ //
+ // Copy the label
+ //
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+
+ //
+ // Go to the next Op-Code
+ //
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ continue;
+ }
+
+ if (AddData) {
+ //
+ // Copy the label
+ //
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+
+ //
+ // Add the DataCount amount of opcodes to TempBuffer
+ //
+ DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;
+ for (Index = 0; Index < Data->DataCount; Index++) {
+ CopyMem (TempBuffer, DataLocation, DataLocation->Length);
+ ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length;
+ OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));
+ CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);
+ TempBuffer = TempBuffer + DataLocation->Length;
+ DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);
+ }
+ //
+ // Go to the next Op-Code
+ //
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ continue;
+ } else {
+ //
+ // Copy the label
+ //
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+
+ //
+ // Remove the DataCount amount of opcodes unless we run into an end of form or a label
+ //
+ for (Index = 0; Index < Data->DataCount; Index++) {
+ //
+ // If we are about to skip an end form - bail out, since that is illegal
+ //
+ if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) {
+ break;
+ }
+ //
+ // By skipping Location entries, we are in effect not copying what was previously there
+ //
+ ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length;
+ OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));
+ CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ }
+ }
+
+ default:
+ CopyMem (TempBuffer, Location, Location->Length);
+ TempBuffer = TempBuffer + Location->Length;
+ break;
+ }
+ //
+ // Go to the next Op-Code
+ //
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ }
+ //
+ // Copy the last op-code left behind from the for loop
+ //
+ CopyMem (TempBuffer, Location, Location->Length);
+
+ //
+ // Advance to beginning of strings and copy them
+ //
+ TempBuffer = TempBuffer + Location->Length;
+ Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
+ CopyMem (TempBuffer, Location, PackageInstance->StringSize);
+
+ //
+ // Free the old buffer, and assign into our database the latest buffer
+ //
+ FreePool (HandleDatabase->Buffer);
+ HandleDatabase->Buffer = OrigTempBuffer;
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.c
new file mode 100644
index 0000000000..cac37e58ca
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.c
@@ -0,0 +1,412 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ HiiDatabase.c
+
+Abstract:
+
+ This file contains the entry code to the HII database.
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initialize HII Database
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_SUCCESS - Setup loaded.
+ other - Setup Error
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_GLOBAL_DATA *GlobalData;
+ EFI_HANDLE *HandleBuffer;
+ EFI_HANDLE Handle;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // There will be only one HII Database in the system
+ // If there is another out there, someone is trying to install us
+ // again. Fail that scenario.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiHiiProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ //
+ // If there was no error, assume there is an installation and fail to load
+ //
+ if (!EFI_ERROR (Status)) {
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ HiiData = AllocatePool (sizeof (EFI_HII_DATA));
+
+ ASSERT (HiiData);
+
+ GlobalData = AllocateZeroPool (sizeof (EFI_HII_GLOBAL_DATA));
+
+ ASSERT (GlobalData);
+
+ //
+ // Seed the Font Database with a known non-character glyph
+ //
+ for (Index = 0; Index <= MAX_GLYPH_COUNT; Index++) {
+ //
+ // Seeding the UnicodeWeight with 0 signifies that it is uninitialized
+ //
+ GlobalData->NarrowGlyphs[Index].UnicodeWeight = 0;
+ GlobalData->WideGlyphs[Index].UnicodeWeight = 0;
+ GlobalData->NarrowGlyphs[Index].Attributes = 0;
+ GlobalData->WideGlyphs[Index].Attributes = 0;
+ CopyMem (GlobalData->NarrowGlyphs[Index].GlyphCol1, &mUnknownGlyph, NARROW_GLYPH_ARRAY_SIZE);
+ CopyMem (GlobalData->WideGlyphs[Index].GlyphCol1, &mUnknownGlyph, WIDE_GLYPH_ARRAY_SIZE);
+ }
+ //
+ // Fill in HII data
+ //
+ HiiData->Signature = EFI_HII_DATA_SIGNATURE;
+ HiiData->GlobalData = GlobalData;
+ HiiData->GlobalData->SystemKeyboardUpdate = FALSE;
+ HiiData->DatabaseHead = NULL;
+ HiiData->Hii.NewPack = HiiNewPack;
+ HiiData->Hii.RemovePack = HiiRemovePack;
+ HiiData->Hii.FindHandles = HiiFindHandles;
+ HiiData->Hii.ExportDatabase = HiiExportDatabase;
+ HiiData->Hii.GetGlyph = HiiGetGlyph;
+ HiiData->Hii.GetPrimaryLanguages = HiiGetPrimaryLanguages;
+ HiiData->Hii.GetSecondaryLanguages = HiiGetSecondaryLanguages;
+ HiiData->Hii.NewString = HiiNewString;
+ HiiData->Hii.GetString = HiiGetString;
+ HiiData->Hii.ResetStrings = HiiResetStrings;
+ HiiData->Hii.TestString = HiiTestString;
+ HiiData->Hii.GetLine = HiiGetLine;
+ HiiData->Hii.GetForms = HiiGetForms;
+ HiiData->Hii.GetDefaultImage = HiiGetDefaultImage;
+ HiiData->Hii.UpdateForm = HiiUpdateForm;
+ HiiData->Hii.GetKeyboardLayout = HiiGetKeyboardLayout;
+ HiiData->Hii.GlyphToBlt = HiiGlyphToBlt;
+
+ //
+ // Install protocol interface
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiHiiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HiiData->Hii
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+HiiFindHandles (
+ IN EFI_HII_PROTOCOL *This,
+ IN OUT UINT16 *HandleBufferLength,
+ OUT EFI_HII_HANDLE Handle[1]
+ )
+/*++
+
+Routine Description:
+ Determines the handles that are currently active in the database.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_HANDLE_DATABASE *Database;
+ EFI_HII_DATA *HiiData;
+ UINTN HandleCount;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ Database = HiiData->DatabaseHead;
+
+ if (Database == NULL) {
+ *HandleBufferLength = 0;
+ return EFI_NOT_FOUND;
+ }
+
+ for (HandleCount = 0; Database != NULL; HandleCount++) {
+ Database = Database->NextHandleDatabase;
+ }
+ //
+ // Is there a sufficient buffer for the data being passed back?
+ //
+ if (*HandleBufferLength >= (sizeof (EFI_HII_HANDLE) * HandleCount)) {
+ Database = HiiData->DatabaseHead;
+
+ //
+ // Copy the Head information
+ //
+ if (Database->Handle != 0) {
+ CopyMem (&Handle[0], &Database->Handle, sizeof (EFI_HII_HANDLE));
+ Database = Database->NextHandleDatabase;
+ }
+ //
+ // Copy more data if appropriate
+ //
+ for (HandleCount = 1; Database != NULL; HandleCount++) {
+ CopyMem (&Handle[HandleCount], &Database->Handle, sizeof (EFI_HII_HANDLE));
+ Database = Database->NextHandleDatabase;
+ }
+
+ *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Insufficient buffer length
+ //
+ *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+}
+
+EFI_STATUS
+EFIAPI
+HiiGetPrimaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString
+ )
+/*++
+
+Routine Description:
+
+ This function allows a program to determine what the primary languages that are supported on a given handle.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Count;
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_STRING_PACK *StringPack;
+ EFI_HII_STRING_PACK *Location;
+ UINT32 Length;
+ RELOFST Token;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ PackageInstance = NULL;
+ //
+ // Find matching handle in the handle database. Then get the package instance.
+ //
+ for (HandleDatabase = HiiData->DatabaseHead;
+ HandleDatabase != NULL;
+ HandleDatabase = HandleDatabase->NextHandleDatabase
+ ) {
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (StringPackageInstance->IfrSize > 0) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);
+ } else {
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
+ }
+
+ Location = StringPack;
+ //
+ // Remember that the string packages are formed into contiguous blocks of language data.
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (Count = 0; Length != 0; Count = Count + 3) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ }
+
+ *LanguageString = AllocateZeroPool (2 * (Count + 1));
+
+ ASSERT (*LanguageString);
+
+ StringPack = (EFI_HII_STRING_PACK *) Location;
+
+ //
+ // Copy the 6 bytes to LanguageString - keep concatenating it. Shouldn't we just store uint8's since the ISO
+ // standard defines the lettering as all US English characters anyway? Save a few bytes.
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (Count = 0; Length != 0; Count = Count + 3) {
+ CopyMem (&Token, &StringPack->LanguageNameString, sizeof (RELOFST));
+ CopyMem (*LanguageString + Count, (VOID *) ((CHAR8 *) (StringPack) + Token), 6);
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString
+ )
+/*++
+
+Routine Description:
+
+ This function allows a program to determine which secondary languages are supported
+ on a given handle for a given primary language.
+
+ Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Count;
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_STRING_PACK *StringPack;
+ RELOFST Token;
+ UINT32 Length;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+ //
+ // Check numeric value against the head of the database
+ //
+ PackageInstance = NULL;
+ for (HandleDatabase = HiiData->DatabaseHead;
+ HandleDatabase != NULL;
+ HandleDatabase = HandleDatabase->NextHandleDatabase
+ ) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (StringPackageInstance->IfrSize > 0) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);
+ } else {
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
+ }
+
+ //
+ // Remember that the string packages are formed into contiguous blocks of language data.
+ //
+ for (; StringPack->Header.Length != 0;) {
+ //
+ // Find the PrimaryLanguage being requested
+ //
+ Token = StringPack->LanguageNameString;
+ if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + Token), PrimaryLanguage, 3) == 0) {
+ //
+ // Now that we found the primary, the secondary languages will follow immediately
+ // or the next character is a NULL if there are no secondary languages. We determine
+ // the number by getting the stringsize based on the StringPack origination + the LanguageNameString
+ // offset + 6 (which is the size of the first 3 letter ISO primary language name). If we get 2, there
+ // are no secondary languages (2 = null-terminator).
+ //
+ Count = StrSize ((VOID *) ((CHAR8 *) (StringPack) + Token + 6));
+
+ *LanguageString = AllocateZeroPool (2 * (Count + 1));
+
+ ASSERT (*LanguageString);
+
+ CopyMem (*LanguageString, (VOID *) ((CHAR8 *) (StringPack) + Token + 6), Count);
+ break;
+ }
+
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.dxs b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.dxs
new file mode 100644
index 0000000000..3e1fa13af6
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.dxs
@@ -0,0 +1,30 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ HiiDatabase.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include <DxeDepex.h>
+
+DEPENDENCY_START
+ TRUE
+DEPENDENCY_END
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.h b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.h
new file mode 100644
index 0000000000..adfc31c0c8
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.h
@@ -0,0 +1,307 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ HiiDatabase.h
+
+Abstract:
+
+ This file contains global defines and prototype definitions
+ for the HII database.
+
+--*/
+
+#ifndef _HIIDATABASE_H
+#define _HIIDATABASE_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// HII Database Global data
+//
+#define EFI_HII_DATA_SIGNATURE EFI_SIGNATURE_32 ('H', 'i', 'i', 'P')
+
+#define MAX_GLYPH_COUNT 65535
+#define NARROW_GLYPH_ARRAY_SIZE 19
+#define WIDE_GLYPH_ARRAY_SIZE 38
+
+#define SETUP_MAP_NAME L"Setup"
+#define HII_VARIABLE_SUFFIX_USER_DATA L"UserSavedData"
+#define HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE L"DefaultOverride"
+#define HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE L"ManufacturingOverride"
+
+typedef struct _EFI_HII_HANDLE_DATABASE {
+ VOID *Buffer; // Actual buffer pointer
+ EFI_HII_HANDLE Handle; // Monotonically increasing value to signify the value returned to caller
+ UINT32 NumberOfTokens; // The initial number of tokens when first registered
+ struct _EFI_HII_HANDLE_DATABASE *NextHandleDatabase;
+} EFI_HII_HANDLE_DATABASE;
+
+typedef struct {
+ EFI_NARROW_GLYPH NarrowGlyphs[MAX_GLYPH_COUNT];
+ EFI_WIDE_GLYPH WideGlyphs[MAX_GLYPH_COUNT];
+ EFI_KEY_DESCRIPTOR SystemKeyboardLayout[106];
+ EFI_KEY_DESCRIPTOR OverrideKeyboardLayout[106];
+ BOOLEAN SystemKeyboardUpdate; // Has the SystemKeyboard been updated?
+} EFI_HII_GLOBAL_DATA;
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HII_GLOBAL_DATA *GlobalData;
+ EFI_HII_HANDLE_DATABASE *DatabaseHead; // Head of the Null-terminated singly-linked list of handles.
+ EFI_HII_PROTOCOL Hii;
+} EFI_HII_DATA;
+
+typedef struct {
+ EFI_HII_HANDLE Handle;
+ EFI_GUID Guid;
+ EFI_HII_HANDLE_PACK HandlePack;
+ UINTN IfrSize;
+ UINTN StringSize;
+ EFI_HII_IFR_PACK *IfrData; // All the IFR data stored here
+ EFI_HII_STRING_PACK *StringData; // All the String data stored at &IfrData + IfrSize (StringData is just a label - never referenced)
+} EFI_HII_PACKAGE_INSTANCE;
+
+typedef struct {
+ EFI_HII_PACK_HEADER Header;
+ EFI_IFR_FORM_SET FormSet;
+ EFI_IFR_END_FORM_SET EndFormSet;
+} EFI_FORM_SET_STUB;
+
+#define EFI_HII_DATA_FROM_THIS(a) CR (a, EFI_HII_DATA, Hii, EFI_HII_DATA_SIGNATURE)
+
+#define NARROW_WIDTH 8
+#define WIDE_WIDTH 16
+
+extern UINT8 mUnknownGlyph[38];
+
+//
+// Prototypes
+//
+EFI_STATUS
+GetPackSize (
+ IN VOID *Pack,
+ OUT UINTN *PackSize,
+ OUT UINT32 *NumberOfTokens
+ )
+;
+
+EFI_STATUS
+ValidatePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGE_INSTANCE *PackageInstance,
+ OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance,
+ OUT UINT32 *TotalStringCount
+ )
+;
+
+//
+// Public Interface Prototypes
+//
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiNewPack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *PackageList,
+ OUT EFI_HII_HANDLE *Handle
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiRemovePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiFindHandles (
+ IN EFI_HII_PROTOCOL *This,
+ IN OUT UINT16 *HandleBufferLength,
+ OUT EFI_HII_HANDLE *Handle
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiExportDatabase (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGlyphToBlt (
+ IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN Count,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLength,
+ OUT EFI_STRING StringBuffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiResetStrings (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiTestString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetPrimaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetLine (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN OUT UINT16 *Index,
+ IN UINT16 LineWidth,
+ IN CHAR16 *LanguageString,
+ IN OUT UINT16 *BufferLength,
+ OUT EFI_STRING StringBuffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetForms (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLength,
+ OUT UINT8 *Buffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetDefaultImage (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiUpdateForm (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN EFI_HII_UPDATE_DATA *Data
+ )
+;
+
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT EFI_KEY_DESCRIPTOR *Descriptor
+ )
+;
+
+EFI_STATUS
+HiiCompareLanguage (
+ IN CHAR16 *LanguageStringLocation,
+ IN CHAR16 *Language
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.inf b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.inf
new file mode 100644
index 0000000000..216a47a055
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.inf
@@ -0,0 +1,116 @@
+#/** @file
+# Component description file for HiiDatabase module.
+#
+# This module inits HII database and installs HII protocol.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HiiDatabase
+ FILE_GUID = FCD337AB-B1D3-4EF8-957C-8048606FF670
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeHiiDatabase
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ HiiDatabase.dxs
+ Keyboard.c
+ Fonts.c
+ Package.c
+ Strings.c
+ Forms.c
+ HiiDatabase.h
+ HiiDatabase.c
+ CommonHeader.h
+
+
+################################################################################
+#
+# Includes Section - list of Include locations that are required for
+# this module.
+#
+################################################################################
+
+[Includes]
+ $(WORKSPACE)/MdePkg/Include/Library
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ IfrSupportLibFramework
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ DebugLib
+ BaseLib
+
+
+################################################################################
+#
+# Guid C Name Section - list of Guids that this module uses or produces.
+#
+################################################################################
+
+[Guids]
+ gEfiGlobalVariableGuid # SOMETIMES_CONSUMED L"Lang"
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiFormCallbackProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiHiiProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.msa b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.msa
new file mode 100644
index 0000000000..f91338d925
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/HiiDatabase.msa
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0">
+ <MsaHeader>
+ <ModuleName>HiiDatabase</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>FCD337AB-B1D3-4EF8-957C-8048606FF670</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for HiiDatabase module.</Abstract>
+ <Description>This module inits HII database and installs HII protocol.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>HiiDatabase</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED" RecommendedInstanceGuid="bda39d3a-451b-4350-8266-81ab10fa0523">
+ <Keyword>DebugLib</Keyword>
+ <HelpText>Recommended libary Instance is PeiDxeDebugLibReportStatusCode instance in MdePkg.</HelpText>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkIfrSupportLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>HiiDatabase.c</Filename>
+ <Filename>HiiDatabase.h</Filename>
+ <Filename>Forms.c</Filename>
+ <Filename>Strings.c</Filename>
+ <Filename>Package.c</Filename>
+ <Filename>Fonts.c</Filename>
+ <Filename>Keyboard.c</Filename>
+ <Filename>HiiDatabase.dxs</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="SOMETIMES_CONSUMED">
+ <ProtocolCName>gEfiFormCallbackProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Variables>
+ <Variable Usage="SOMETIMES_CONSUMED">
+ <VariableName>0x004C 0x0061 0x006E 0x0067</VariableName>
+ <GuidC_Name>gEfiGlobalVariableGuid</GuidC_Name>
+ <HelpText>L"Lang" global variable is used as system default language.</HelpText>
+ </Variable>
+ </Variables>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeHiiDatabase</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Keyboard.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Keyboard.c
new file mode 100644
index 0000000000..be91d40129
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Keyboard.c
@@ -0,0 +1,48 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Keyboard.c
+
+Abstract:
+
+ This file contains the keyboard processing code to the HII database.
+
+--*/
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT EFI_KEY_DESCRIPTOR *Descriptor
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c
new file mode 100644
index 0000000000..91f5a3a3db
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c
@@ -0,0 +1,678 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Package.c
+
+Abstract:
+
+ This file contains the package processing code to the HII database.
+
+--*/
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+EFI_STATUS
+GetPackSize (
+ IN VOID *Pack,
+ OUT UINTN *PackSize,
+ OUT UINT32 *NumberOfTokens
+ )
+/*++
+
+Routine Description:
+ Determines the passed in Pack's size and returns the value.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_STRING_PACK *StringPack;
+ UINT16 Type;
+ UINT32 Length;
+
+ *PackSize = 0;
+
+ Type = EFI_HII_IFR;
+ if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) {
+ //
+ // The header contains the full IFR length
+ //
+ CopyMem (&Length, &((EFI_HII_PACK_HEADER *) Pack)->Length, sizeof (Length));
+ *PackSize = (UINTN) Length;
+ return EFI_SUCCESS;
+ }
+
+ Type = EFI_HII_STRING;
+ if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) {
+ //
+ // The header contains the STRING package length
+ // The assumption is that the strings for all languages
+ // are a contiguous block of data and there is a series of
+ // these package instances which will terminate with a NULL package
+ // instance.
+ //
+ StringPack = (EFI_HII_STRING_PACK *) Pack;
+
+ //
+ // There may be multiple instances packed together of strings
+ // so we must walk the self describing structures until we encounter
+ // the NULL structure to determine the full size.
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (Length));
+ if (NumberOfTokens != NULL) {
+ CopyMem (NumberOfTokens, &StringPack->NumStringPointers, sizeof (UINT32));
+ }
+
+ while (Length != 0) {
+ *PackSize = *PackSize + Length;
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) StringPack + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (Length));
+ }
+ //
+ // Encountered a length of 0, so let's add the space for the NULL terminator
+ // pack's length and call it done.
+ //
+ *PackSize = *PackSize + sizeof (EFI_HII_STRING_PACK);
+ return EFI_SUCCESS;
+ }
+ //
+ // We only determine the size of the non-global Package types.
+ // If neither IFR or STRING data were found, return an error
+ //
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+ValidatePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGE_INSTANCE *PackageInstance,
+ OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance,
+ OUT UINT32 *TotalStringCount
+ )
+/*++
+
+Routine Description:
+ Verifies that the package instance is using the correct handle for string operations.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_PACKAGE_INSTANCE *HandlePackageInstance;
+ UINT8 *RawData;
+ EFI_GUID Guid;
+ EFI_HII_IFR_PACK *FormPack;
+ UINTN Index;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+ ZeroMem (&Guid, sizeof (EFI_GUID));
+
+ *StringPackageInstance = PackageInstance;
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (PackageInstance->IfrSize > 0) {
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+ } else {
+ //
+ // If there is no IFR data assume the caller knows what they are doing.
+ //
+ return EFI_SUCCESS;
+ }
+
+ RawData = (UINT8 *) FormPack;
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
+ //
+ // Cache the guid for this formset
+ //
+ CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
+ break;
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+ //
+ // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are
+ // different, we should return the correct handle for the caller to use for strings.
+ //
+ if ((PackageInstance->StringSize == 0) && (!CompareGuid (&Guid, &PackageInstance->Guid))) {
+ //
+ // Search the database for a handle that matches the PackageInstance->Guid
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Get Ifrdata and extract the Guid for it
+ //
+ HandlePackageInstance = HandleDatabase->Buffer;
+
+ ASSERT (HandlePackageInstance->IfrSize != 0);
+
+ FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&HandlePackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
+ RawData = (UINT8 *) FormPack;
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
+ //
+ // Cache the guid for this formset
+ //
+ CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
+ break;
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+ //
+ // If the Guid from the new handle matches the original Guid referenced in the original package data
+ // return the appropriate package instance data to use.
+ //
+ if (CompareGuid (&Guid, &PackageInstance->Guid)) {
+ if (TotalStringCount != NULL) {
+ *TotalStringCount = HandleDatabase->NumberOfTokens;
+ }
+
+ *StringPackageInstance = HandlePackageInstance;
+ }
+ }
+ //
+ // end for
+ //
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiNewPack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *Packages,
+ OUT EFI_HII_HANDLE *Handle
+ )
+/*++
+
+Routine Description:
+
+ Extracts the various packs from a package list.
+
+Arguments:
+
+ This - Pointer of HII protocol.
+ Packages - Pointer of HII packages.
+ Handle - Handle value to be returned.
+
+Returns:
+
+ EFI_SUCCESS - Pacakges has added to HII database successfully.
+ EFI_INVALID_PARAMETER - Invalid parameter.
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_HANDLE_DATABASE *Database;
+ EFI_HII_PACK_HEADER *PackageHeader;
+ EFI_HII_GLOBAL_DATA *GlobalData;
+ EFI_HII_IFR_PACK *IfrPack;
+ EFI_HII_STRING_PACK *StringPack;
+ EFI_HII_FONT_PACK *FontPack;
+ EFI_HII_KEYBOARD_PACK *KeyboardPack;
+ EFI_STATUS Status;
+ UINTN IfrSize;
+ UINTN StringSize;
+ UINTN TotalStringSize;
+ UINTN InstanceSize;
+ UINTN Count;
+ UINTN Index;
+ UINT16 Member;
+ EFI_GUID Guid;
+ EFI_FORM_SET_STUB FormSetStub;
+ UINT8 *Location;
+ UINT16 Unicode;
+ UINT16 NumWideGlyphs;
+ UINT16 NumNarrowGlyphs;
+ UINT32 NumberOfTokens;
+ UINT32 TotalTokenNumber;
+ UINT8 *Local;
+ EFI_NARROW_GLYPH *NarrowGlyph;
+
+ if (Packages->NumberOfPackages == 0 || This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ GlobalData = HiiData->GlobalData;
+
+ Database = HiiData->DatabaseHead;
+
+ PackageInstance = NULL;
+ IfrPack = NULL;
+ StringPack = NULL;
+ InstanceSize = 0;
+ IfrSize = 0;
+ StringSize = 0;
+ TotalStringSize = 0;
+ NumberOfTokens = 0;
+ TotalTokenNumber = 0;
+
+ //
+ // Search through the passed in Packages for the IfrPack and any StringPack.
+ //
+ for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
+
+ PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *));
+
+ switch (PackageHeader->Type) {
+ case EFI_HII_IFR:
+ //
+ // There shoule be only one Ifr package.
+ //
+ ASSERT (IfrPack == NULL);
+ IfrPack = (EFI_HII_IFR_PACK *) PackageHeader;
+ break;
+
+ case EFI_HII_STRING:
+ StringPack = (EFI_HII_STRING_PACK *) PackageHeader;
+ //
+ // Sending me a String Package. Get its size.
+ //
+ Status = GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens);
+ ASSERT (!EFI_ERROR (Status));
+
+ //
+ // The size which GetPackSize() returns include the null terminator. So if multiple
+ // string packages are passed in, merge all these packages, and only pad one null terminator.
+ //
+ if (TotalStringSize > 0) {
+ TotalStringSize -= sizeof (EFI_HII_STRING_PACK);
+ }
+
+ TotalStringSize += StringSize;
+ TotalTokenNumber += NumberOfTokens;
+ break;
+ }
+ }
+ //
+ // If sending a StringPack without an IfrPack, you must include a GuidId
+ //
+ if ((StringPack != NULL) && (IfrPack == NULL)) {
+ if (Packages->GuidId == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // If passing in an IfrPack and a GuidId is provided, ensure they are the same value.
+ //
+ if ((IfrPack != NULL) && (Packages->GuidId != NULL)) {
+ Location = ((UINT8 *) IfrPack);
+ Location = (UINT8 *) (((UINTN) Location) + sizeof (EFI_HII_PACK_HEADER));
+
+ //
+ // Advance to the Form Set Op-code
+ //
+ for (Count = 0; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) {
+ Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length;
+ }
+ //
+ // Copy to local variable
+ //
+ CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID));
+
+ //
+ // Check to see if IfrPack->Guid != GuidId
+ //
+ if (!CompareGuid (&Guid, Packages->GuidId)) {
+ //
+ // If a string package is present, the GUIDs should have agreed. Return an error
+ //
+ if (StringPack != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+ //
+ // If someone is passing in a string only, create a dummy IfrPack with a Guid
+ // to enable future searching of this data.
+ //
+ if ((IfrPack == NULL) && (StringPack != NULL)) {
+ ZeroMem (&FormSetStub, sizeof (FormSetStub));
+
+ FormSetStub.Header.Type = EFI_HII_IFR;
+ FormSetStub.Header.Length = sizeof (EFI_FORM_SET_STUB);
+
+ FormSetStub.FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP;
+ FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET);
+ //
+ // Dummy string
+ //
+ FormSetStub.FormSet.FormSetTitle = 0x02;
+ CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID));
+
+ FormSetStub.EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP;
+ FormSetStub.EndFormSet.Header.Length = (UINT8) sizeof (EFI_IFR_END_FORM_SET);
+ IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub;
+ }
+
+ if (IfrPack != NULL) {
+ //
+ // Sending me an IFR Package. Get its size.
+ //
+ Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL);
+ ASSERT (!EFI_ERROR (Status));
+ }
+ //
+ // Prepare the internal package instace buffer to store package data.
+ //
+ InstanceSize = IfrSize + TotalStringSize;
+
+ if (InstanceSize != 0) {
+ PackageInstance = AllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE));
+
+ ASSERT (PackageInstance);
+
+ //
+ // If there is no DatabaseHead allocated - allocate one
+ //
+ if (HiiData->DatabaseHead == NULL) {
+ HiiData->DatabaseHead = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));
+ ASSERT (HiiData->DatabaseHead);
+ }
+ //
+ // If the head is being used (Handle is non-zero), allocate next Database and
+ // add it to the linked-list
+ //
+ if (HiiData->DatabaseHead->Handle != 0) {
+ HandleDatabase = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));
+
+ ASSERT (HandleDatabase);
+
+ for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase)
+ ;
+
+ //
+ // We are sitting on the Database entry which contains the null Next pointer. Fix it.
+ //
+ Database->NextHandleDatabase = HandleDatabase;
+
+ }
+
+ Database = HiiData->DatabaseHead;
+
+ //
+ // Initialize this instance data
+ //
+ for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) {
+ //
+ // Since the first Database instance will have a passed back handle of 1, we will continue
+ // down the linked list of entries until we encounter the end of the linked list. Each time
+ // we go down one level deeper, increment the handle value that will be passed back.
+ //
+ if (Database->Handle >= *Handle) {
+ *Handle = (EFI_HII_HANDLE) (Database->Handle + 1);
+ }
+ }
+
+ PackageInstance->Handle = *Handle;
+ PackageInstance->IfrSize = IfrSize;
+ PackageInstance->StringSize = TotalStringSize;
+ if (Packages->GuidId != NULL) {
+ CopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID));
+ }
+
+ Database->Buffer = PackageInstance;
+ Database->Handle = PackageInstance->Handle;
+ Database->NumberOfTokens = TotalTokenNumber;
+ Database->NextHandleDatabase = NULL;
+ }
+ //
+ // Copy the Ifr package data into package instance.
+ //
+ if (IfrSize > 0) {
+ CopyMem (&PackageInstance->IfrData, IfrPack, IfrSize);
+ }
+ //
+ // Main loop to store package data into HII database.
+ //
+ StringSize = 0;
+ TotalStringSize = 0;
+
+ for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
+
+ PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *));
+
+ switch (PackageHeader->Type) {
+ case EFI_HII_STRING:
+ StringPack = (EFI_HII_STRING_PACK *) PackageHeader;
+ //
+ // The size which GetPackSize() returns include the null terminator. So if multiple
+ // string packages are passed in, merge all these packages, and only pad one null terminator.
+ //
+ if (TotalStringSize > 0) {
+ TotalStringSize -= sizeof (EFI_HII_STRING_PACK);
+ }
+
+ GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens);
+ CopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize);
+
+ TotalStringSize += StringSize;
+ break;
+
+ case EFI_HII_HANDLES:
+ CopyMem (&PackageInstance->HandlePack, PackageHeader, sizeof (EFI_HII_HANDLE_PACK));
+ break;
+
+ case EFI_HII_FONT:
+ FontPack = (EFI_HII_FONT_PACK *) PackageHeader;
+ //
+ // Add whatever narrow glyphs were passed to us if undefined
+ //
+ CopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16));
+ for (Count = 0; Count <= NumNarrowGlyphs; Count++) {
+ Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count;
+ NarrowGlyph = (EFI_NARROW_GLYPH *) Local;
+ CopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16));
+ //
+ // If the glyph is already defined, do not overwrite it. It is what it is.
+ //
+ CopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16));
+ if (Unicode == 0) {
+ CopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH));
+ }
+ }
+ //
+ // Add whatever wide glyphs were passed to us if undefined
+ //
+ CopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16));
+ for (Count = 0; Count <= NumWideGlyphs; Count++) {
+ Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) +
+ (sizeof (EFI_NARROW_GLYPH)) *
+ NumNarrowGlyphs;
+ CopyMem (
+ &Member,
+ (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
+ sizeof (UINT16)
+ );
+ //
+ // If the glyph is already defined, do not overwrite it. It is what it is.
+ //
+ CopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16));
+ if (Unicode == 0) {
+ Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs;
+ CopyMem (
+ &GlobalData->WideGlyphs[Member],
+ (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
+ sizeof (EFI_WIDE_GLYPH)
+ );
+ }
+ }
+ break;
+
+ case EFI_HII_KEYBOARD:
+ KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader;
+ //
+ // Sending me a Keyboard Package
+ //
+ if (KeyboardPack->DescriptorCount > 105) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If someone updates the Descriptors with a count of 0, blow aware the overrides.
+ //
+ if (KeyboardPack->DescriptorCount == 0) {
+ ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
+ }
+
+ if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) {
+ //
+ // If SystemKeyboard was updated already, then steer changes to the override database
+ //
+ if (GlobalData->SystemKeyboardUpdate) {
+ ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
+ for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
+ CopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16));
+ CopyMem (
+ &GlobalData->OverrideKeyboardLayout[Member],
+ &KeyboardPack->Descriptor[Count],
+ sizeof (EFI_KEY_DESCRIPTOR)
+ );
+ }
+ } else {
+ //
+ // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
+ //
+ ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
+ for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
+ CopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16));
+ CopyMem (
+ &GlobalData->SystemKeyboardLayout[Member],
+ &KeyboardPack->Descriptor[Count],
+ sizeof (EFI_KEY_DESCRIPTOR)
+ );
+ }
+ //
+ // Just updated the system keyboard database, reflect that in the global flag.
+ //
+ GlobalData->SystemKeyboardUpdate = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiRemovePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+ Removes the various packs from a Handle
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_HANDLE_DATABASE *PreviousHandleDatabase;
+
+ if (This == NULL || Handle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+ PackageInstance = NULL;
+
+ //
+ // Initialize the Previous with the Head of the Database
+ //
+ PreviousHandleDatabase = HandleDatabase;
+
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Match the numeric value with the database entry - if matched,
+ // free the package instance and apply fix-up to database linked list
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+
+ //
+ // Free the Package Instance
+ //
+ FreePool (PackageInstance);
+
+ //
+ // If this was the only Handle in the database
+ //
+ if (HiiData->DatabaseHead == HandleDatabase) {
+ HiiData->DatabaseHead = NULL;
+ }
+ //
+ // Make the parent->Next point to the current->Next
+ //
+ PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase;
+ FreePool (HandleDatabase);
+ return EFI_SUCCESS;
+ }
+ //
+ // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
+ //
+ PreviousHandleDatabase = HandleDatabase;
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Strings.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Strings.c
new file mode 100644
index 0000000000..a8b04c0884
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Strings.c
@@ -0,0 +1,1276 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Strings.c
+
+Abstract:
+
+ This file contains the string processing code to the HII database.
+
+--*/
+
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "HiiDatabase.h"
+
+STATIC
+VOID
+AsciiToUnicode (
+ IN UINT8 *Lang,
+ IN UINT16 *Language
+ )
+{
+ UINT8 Count;
+
+ //
+ // Convert the ASCII Lang variable to a Unicode Language variable
+ //
+ for (Count = 0; Count < 3; Count++) {
+ Language[Count] = (CHAR16) Lang[Count];
+ }
+}
+
+EFI_STATUS
+EFIAPI
+HiiTestString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize
+ )
+/*++
+
+Routine Description:
+ Test if all of the characters in a string have corresponding font characters.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_HII_GLOBAL_DATA *GlobalData;
+ EFI_HII_DATA *HiiData;
+ BOOLEAN WideChar;
+ INT32 Location;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+ GlobalData = HiiData->GlobalData;
+
+
+ //
+ // Rewind through the string looking for a glyph width identifier
+ // If no width identifier exists, we assume string has narrow width identifier
+ //
+ for (WideChar = FALSE, Location = (INT32) *FirstMissing; Location >= 0; Location--) {
+ if ((StringToTest[Location] == NARROW_CHAR) || (StringToTest[Location] == WIDE_CHAR)) {
+ //
+ // We found something that identifies what glyph database to look in
+ //
+ WideChar = (BOOLEAN) (StringToTest[Location] == WIDE_CHAR);
+ break;
+ }
+ }
+
+ //
+ // Walk through the string until you hit the null terminator
+ //
+ for (*GlyphBufferSize = 0; StringToTest[*FirstMissing] != CHAR_NULL; (*FirstMissing)++) {
+ //
+ // We found something that identifies what glyph database to look in
+ //
+ if ((StringToTest[*FirstMissing] == NARROW_CHAR) || (StringToTest[*FirstMissing] == WIDE_CHAR)) {
+ WideChar = (BOOLEAN) (StringToTest[*FirstMissing] == WIDE_CHAR);
+ continue;
+ }
+
+ if (!WideChar) {
+ if (CompareMem (
+ GlobalData->NarrowGlyphs[StringToTest[*FirstMissing]].GlyphCol1,
+ &mUnknownGlyph,
+ NARROW_GLYPH_ARRAY_SIZE
+ ) == 0
+ ) {
+ //
+ // Break since this glyph isn't defined
+ //
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
+ //
+ if (CompareMem (
+ GlobalData->WideGlyphs[StringToTest[*FirstMissing]].GlyphCol1,
+ &mUnknownGlyph,
+ WIDE_GLYPH_ARRAY_SIZE
+ ) == 0
+ ) {
+ //
+ // Break since this glyph isn't defined
+ //
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ *GlyphBufferSize += (WideChar ? sizeof (EFI_WIDE_GLYPH) : sizeof (EFI_NARROW_GLYPH));
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+HiiNewString2 (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString,
+ IN BOOLEAN ResetStrings
+ )
+/*++
+
+Routine Description:
+
+ This function allows a new String to be added to an already existing String Package.
+ We will make a buffer the size of the package + EfiStrSize of the new string. We will
+ copy the string package that first gets changed and the following language packages until
+ we encounter the NULL string package. All this time we will ensure that the offsets have
+ been adjusted.
+
+Arguments:
+
+ This - Pointer to the HII protocol.
+ Language - Pointer to buffer which contains the language code of this NewString.
+ Handle - Handle of the package instance to be processed.
+ Reference - The token number for the string. If 0, new string token to be returned through this parameter.
+ NewString - Buffer pointer for the new string.
+ ResetStrings - Indicate if we are resetting a string.
+
+Returns:
+
+ EFI_SUCCESS - The string has been added or reset to Hii database.
+ EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_STRING_PACK *StringPack;
+ EFI_HII_STRING_PACK *NewStringPack;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_PACKAGE_INSTANCE *NewBuffer;
+ UINT8 *Location;
+ UINT8 *StringLocation;
+ RELOFST *StringPointer;
+ UINTN Count;
+ UINTN Size;
+ UINTN Index;
+ UINTN SecondIndex;
+ BOOLEAN AddString;
+ EFI_STATUS Status;
+ UINTN Increment;
+ UINTN StringCount;
+ UINT32 TotalStringCount;
+ UINT32 OriginalStringCount;
+ RELOFST StringSize;
+ UINT32 Length;
+ RELOFST Offset;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+ PackageInstance = NULL;
+ AddString = FALSE;
+ Increment = 0;
+ StringCount = 0;
+ TotalStringCount = 0;
+ OriginalStringCount = 0;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ if (ResetStrings) {
+ TotalStringCount = HandleDatabase->NumberOfTokens;
+ }
+ break;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ValidatePack (This, PackageInstance, &StringPackageInstance, &TotalStringCount);
+
+ //
+ // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
+ //
+ Count = StringPackageInstance->IfrSize;
+
+ //
+ // This is the size of the complete series of string packs
+ //
+ Size = StringPackageInstance->StringSize;
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (StringPackageInstance->IfrSize > 0) {
+ Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;
+ } else {
+ Location = (UINT8 *) (&StringPackageInstance->IfrData);
+ }
+ //
+ // We allocate a buffer which is big enough for both adding and resetting string.
+ // The size is slightly larger than the real size of the packages when we are resetting a string.
+ //
+ NewBuffer = AllocateZeroPool (
+ sizeof (EFI_HII_PACKAGE_INSTANCE) -
+ 2 * sizeof (VOID *) +
+ StringPackageInstance->IfrSize +
+ StringPackageInstance->StringSize +
+ sizeof (RELOFST) +
+ StrSize (NewString)
+ );
+ ASSERT (NewBuffer);
+
+ //
+ // Copy data to new buffer
+ //
+ NewBuffer->Handle = StringPackageInstance->Handle;
+ NewBuffer->IfrSize = StringPackageInstance->IfrSize;
+
+ //
+ // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
+ // package to begin with.
+ //
+ NewBuffer->StringSize = StringPackageInstance->StringSize + StrSize (NewString) + sizeof (EFI_HII_STRING_PACK);
+
+ if (StringPackageInstance->IfrSize > 0) {
+ CopyMem (&NewBuffer->IfrData, &StringPackageInstance->IfrData, StringPackageInstance->IfrSize);
+ }
+
+ StringPack = (EFI_HII_STRING_PACK *) Location;
+
+ //
+ // There may be multiple instances packed together of strings
+ // so we must walk the self describing structures until we encounter
+ // what we are looking for. In the meantime, copy everything we encounter
+ // to the new buffer.
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (; Length != 0;) {
+ //
+ // If passed in Language ISO value is in this string pack's language string
+ // then we are dealing with the strings we want.
+ //
+ CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST));
+ Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language);
+
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);
+
+ Count = Count + Length;
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ }
+ //
+ // Found the language pack to update on a particular handle
+ // We need to Copy the Contents of this pack and adjust the offset values associated
+ // with adding/changing a string. This is a particular piece of code that screams for
+ // it being prone to programming error.
+ //
+ //
+ // Copy the string package up to the string data
+ //
+ StringPointer = (RELOFST *) (StringPack + 1);
+ CopyMem (
+ ((CHAR8 *) (&NewBuffer->IfrData) + Count),
+ StringPack,
+ (UINTN) ((UINTN) (StringPointer) - (UINTN) (StringPack))
+ );
+
+ //
+ // Determine the number of StringPointers
+ //
+ if (!ResetStrings) {
+ CopyMem (&TotalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));
+ } else {
+ //
+ // If we are resetting the strings, use the original value when exported
+ //
+ CopyMem (&OriginalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString -=
+ (
+ (RELOFST) (OriginalStringCount - TotalStringCount) *
+ sizeof (RELOFST)
+ );
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName -=
+ (
+ (RELOFST) (OriginalStringCount - TotalStringCount) *
+ sizeof (RELOFST)
+ );
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers = TotalStringCount;
+ *Reference = (STRING_REF) (TotalStringCount);
+ }
+ //
+ // If the token value is not valid, error out
+ //
+ if ((*Reference >= TotalStringCount) && !ResetStrings) {
+ FreePool (NewBuffer);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
+ //
+ if (*Reference == 0) {
+ *Reference = (STRING_REF) (TotalStringCount);
+ AddString = TRUE;
+ }
+
+ if (AddString) {
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString += sizeof (RELOFST);
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName += sizeof (RELOFST);
+ ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers++;
+ }
+ //
+ // Increment offset by amount of copied data
+ //
+ Count = Count + ((UINTN) (StringPointer) - (UINTN) StringPack);
+
+ for (Index = 0; Index < TotalStringCount; Index++) {
+ //
+ // If we are pointing to the size of the changing string value
+ // then cache the old string value so you know what the difference is
+ //
+ if (Index == *Reference) {
+ CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
+
+ StringLocation = ((UINT8 *) (StringPack) + Offset);
+ for (SecondIndex = 0;
+ (StringLocation[SecondIndex] != 0) || (StringLocation[SecondIndex + 1] != 0);
+ SecondIndex = SecondIndex + 2
+ )
+ ;
+ SecondIndex = SecondIndex + 2;
+
+ Size = SecondIndex;
+
+ //
+ // NewString is a passed in local string which is assumed to be aligned
+ //
+ Size = StrSize (NewString) - Size;
+ }
+ //
+ // If we are about to copy the offset of the string that follows the changed string make
+ // sure that the offsets are adjusted accordingly
+ //
+ if ((Index > *Reference) && !ResetStrings) {
+ CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
+ Offset = (RELOFST) (Offset + Size);
+ CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));
+ }
+ //
+ // If we are adding a string that means we will have an extra string pointer that will affect all string offsets
+ //
+ if (AddString) {
+ CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
+ Offset = (UINT32) (Offset + sizeof (RELOFST));
+ CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));
+ }
+ //
+ // If resetting the strings, we need to reduce the offset by the difference in the strings
+ //
+ if (ResetStrings) {
+ CopyMem (&Length, &StringPointer[Index], sizeof (RELOFST));
+ Length = Length - ((RELOFST) (OriginalStringCount - TotalStringCount) * sizeof (RELOFST));
+ CopyMem (&StringPointer[Index], &Length, sizeof (RELOFST));
+ }
+ //
+ // Notice that if the string was being added as a new token, we don't have to worry about the
+ // offsets changing in the other indexes
+ //
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringPointer[Index], sizeof (RELOFST));
+ Count = Count + sizeof (RELOFST);
+ StringCount++;
+ }
+ //
+ // If we are adding a new string the above for loop did not copy the offset for us
+ //
+ if (AddString) {
+ //
+ // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous
+ // offset's string and create an offset to our new string.
+ //
+ CopyMem (&Offset, &StringPointer[Index - 1], sizeof (RELOFST));
+ StringLocation = (UINT8 *) StringPack;
+ StringLocation = StringLocation + Offset - sizeof (RELOFST);
+
+ //
+ // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
+ //
+ for (Length = 0;
+ (StringLocation[Length] != 0) || (StringLocation[Length + 1] != 0);
+ Length = (RELOFST) (Length + 2)
+ )
+ ;
+ Length = (RELOFST) (Length + 2);
+
+ StringSize = (RELOFST) (Offset + Length);
+
+ //
+ // Copy the new string offset
+ //
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringSize, sizeof (RELOFST));
+ Count = Count + sizeof (RELOFST);
+
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ Length = Length + sizeof (RELOFST);
+ CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
+ }
+ //
+ // Set Location to the First String
+ //
+ if (ResetStrings) {
+ Index = OriginalStringCount;
+ }
+ //
+ // Set Location to the First String
+ //
+ Location = (UINT8 *) &StringPointer[Index];
+ Index = 0;
+
+ //
+ // Keep copying strings until you run into two CHAR16's in a row that are NULL
+ //
+ do {
+ if ((*Reference == Increment) && !AddString) {
+ StringLocation = ((UINT8 *) (&NewBuffer->IfrData) + Count);
+ CopyMem (StringLocation, NewString, StrSize (NewString));
+
+ //
+ // Advance the destination location by Count number of bytes
+ //
+ Count = Count + StrSize (NewString);
+
+ //
+ // Add the difference between the new string and the old string to the length
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+
+ //
+ // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues
+ //
+ StringLocation = (UINT8 *) &Location[Index];
+ for (Offset = 0;
+ (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
+ Offset = (RELOFST) (Offset + 2)
+ )
+ ;
+ Offset = (RELOFST) (Offset + 2);
+
+ Length = Length + (UINT32) StrSize (NewString) - Offset;
+
+ CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
+ } else {
+ StringLocation = (UINT8 *) &Location[Index];
+ for (Offset = 0;
+ (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
+ Offset = (RELOFST) (Offset + 2)
+ )
+ ;
+ Offset = (RELOFST) (Offset + 2);
+
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringLocation, Offset);
+
+ //
+ // Advance the destination location by Count number of bytes
+ //
+ Count = Count + Offset;
+ }
+ //
+ // Retrieve the number of characters to advance the index - should land at beginning of next string
+ //
+ Index = Index + Offset;
+ Increment++;
+ StringCount--;
+ Offset = 0;
+ } while (StringCount > 0);
+
+ //
+ // If we are adding a new string, then the above do/while will not suffice
+ //
+ if (AddString) {
+ Offset = (RELOFST) StrSize (NewString);
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), NewString, Offset);
+
+ Count = Count + StrSize (NewString);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ Length = Length + (UINT32) StrSize (NewString);
+ CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
+ }
+
+ if (ResetStrings) {
+ //
+ // Skip the remainder of strings in the string package
+ //
+ StringCount = OriginalStringCount - TotalStringCount;
+
+ while (StringCount > 0) {
+ StringLocation = (UINT8 *) &Location[Index];
+ for (Offset = 0;
+ (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0);
+ Offset = (RELOFST) (Offset + 2)
+ )
+ ;
+ Offset = (RELOFST) (Offset + 2);
+ Index = Index + Offset;
+ StringCount--;
+
+ //
+ // Adjust the size of the string pack by the string size we just skipped.
+ // Also reduce the length by the size of a RelativeOffset value since we
+ // obviously would have skipped that as well.
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ Length = Length - Offset - sizeof (RELOFST);
+ CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32));
+ }
+ }
+
+ StringPack = (EFI_HII_STRING_PACK *) &Location[Index];
+
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (; Length != 0;) {
+
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);
+
+ Count = Count + Length;
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ }
+ //
+ // Copy the null terminator to the new buffer
+ //
+ CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, sizeof (EFI_HII_STRING_PACK));
+
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (StringPackageInstance->IfrSize > 0) {
+ Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;
+ StringPack = (EFI_HII_STRING_PACK *) Location;
+ Location = (UINT8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize;
+ NewStringPack = (EFI_HII_STRING_PACK *) Location;
+ } else {
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
+ NewStringPack = (EFI_HII_STRING_PACK *) (&NewBuffer->IfrData);
+ }
+
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (; Length != 0;) {
+ //
+ // Since we updated the old version of the string data as we moved things over
+ // And we had a chicken-egg problem with the data we copied, let's post-fix the new
+ // buffer with accurate length data.
+ //
+ CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));
+ CopyMem (&NewStringPack->Header.Length, &StringPack->Header.Length, sizeof (UINT32));
+ CopyMem (&StringPack->Header.Length, &Count, sizeof (UINT32));
+
+ CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32));
+ NewStringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (NewStringPack) + Count);
+ CopyMem (&Count, &StringPack->Header.Length, sizeof (UINT32));
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Count);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ }
+
+ GetPackSize ((VOID *) ((CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize), &NewBuffer->StringSize, NULL);
+
+ //
+ // Search through the handles until the requested handle is found.
+ //
+ for (HandleDatabase = HiiData->DatabaseHead;
+ HandleDatabase->Handle != 0;
+ HandleDatabase = HandleDatabase->NextHandleDatabase
+ ) {
+ if (HandleDatabase->Handle == StringPackageInstance->Handle) {
+ //
+ // Free the previous buffer associated with this handle, and assign the new buffer to the handle
+ //
+ FreePool (HandleDatabase->Buffer);
+ HandleDatabase->Buffer = NewBuffer;
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString
+ )
+/*++
+
+Routine Description:
+ This function allows a new String to be added to an already existing String Package.
+ We will make a buffer the size of the package + StrSize of the new string. We will
+ copy the string package that first gets changed and the following language packages until
+ we encounter the NULL string package. All this time we will ensure that the offsets have
+ been adjusted.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Index;
+ CHAR16 *LangCodes;
+ CHAR16 Lang[4];
+ STRING_REF OriginalValue;
+ EFI_STATUS Status;
+
+ //
+ // To avoid a warning 4 uninitialized variable warning
+ //
+ Status = EFI_SUCCESS;
+
+ Status = HiiGetPrimaryLanguages (
+ This,
+ Handle,
+ &LangCodes
+ );
+
+ if (!EFI_ERROR (Status)) {
+ OriginalValue = *Reference;
+
+ if (Language == NULL) {
+ for (Index = 0; LangCodes[Index] != 0; Index += 3) {
+ *Reference = OriginalValue;
+ CopyMem (Lang, &LangCodes[Index], 6);
+ Lang[3] = 0;
+ Status = HiiNewString2 (
+ This,
+ Lang,
+ Handle,
+ Reference,
+ NewString,
+ FALSE
+ );
+
+ }
+ } else {
+ Status = HiiNewString2 (
+ This,
+ Language,
+ Handle,
+ Reference,
+ NewString,
+ FALSE
+ );
+ }
+
+ FreePool (LangCodes);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+HiiResetStrings (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ This function removes any new strings that were added after the initial string export for this handle.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Index;
+ CHAR16 *LangCodes;
+ CHAR16 Lang[4];
+ STRING_REF Reference;
+ CHAR16 NewString;
+ EFI_STATUS Status;
+
+ Reference = 1;
+ NewString = 0;
+
+ HiiGetPrimaryLanguages (
+ This,
+ Handle,
+ &LangCodes
+ );
+
+ for (Index = 0; LangCodes[Index] != 0; Index += 3) {
+ CopyMem (Lang, &LangCodes[Index], 6);
+ Lang[3] = 0;
+ Status = HiiNewString2 (
+ This,
+ Lang,
+ Handle,
+ &Reference,
+ &NewString,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ FreePool (LangCodes);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLengthTemp,
+ OUT EFI_STRING StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function extracts a string from a package already registered with the EFI HII database.
+
+Arguments:
+ This - A pointer to the EFI_HII_PROTOCOL instance.
+ Handle - The HII handle on which the string resides.
+ Token - The string token assigned to the string.
+ Raw - If TRUE, the string is returned unedited in the internal storage format described
+ above. If false, the string returned is edited by replacing <cr> with <space>
+ and by removing special characters such as the <wide> prefix.
+ LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language
+ identifier, indicating the language to print. If the LanguageString is empty (starts
+ with a NULL), the default system language will be used to determine the language.
+ BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too
+ small, this parameter is filled with the length of the buffer needed.
+ StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is
+ defined in String.
+
+Returns:
+ EFI_INVALID_PARAMETER - If input parameter is invalid.
+ EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small.
+ EFI_SUCCESS - Operation is successful.
+
+--*/
+{
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_STRING_PACK *StringPack;
+ RELOFST *StringPointer;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ CHAR8 Lang[3];
+ CHAR16 Language[3];
+ UINT32 Length;
+ UINTN Count;
+ RELOFST Offset;
+ UINT16 *Local;
+ UINT16 Zero;
+ UINT16 Narrow;
+ UINT16 Wide;
+ UINT16 NoBreak;
+ BOOLEAN LangFound;
+ UINT16 *BufferLength = (UINT16 *) BufferLengthTemp;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LangFound = TRUE;
+
+ DataSize = sizeof (Lang);
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ PackageInstance = NULL;
+ Zero = 0;
+ Narrow = NARROW_CHAR;
+ Wide = WIDE_CHAR;
+ NoBreak = NON_BREAKING_CHAR;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (HandleDatabase = HiiData->DatabaseHead;
+ HandleDatabase != NULL;
+ HandleDatabase = HandleDatabase->NextHandleDatabase
+ ) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ break;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);
+
+ //
+ // If there is no specified language, assume the system default language
+ //
+ if (LanguageString == NULL) {
+ //
+ // Get system default language
+ //
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ Lang
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // If Lang doesn't exist, just use the first language you find
+ //
+ LangFound = FALSE;
+ goto LangNotFound;
+ }
+ //
+ // Convert the ASCII Lang variable to a Unicode Language variable
+ //
+ AsciiToUnicode ((UINT8 *)Lang, Language);
+ } else {
+ //
+ // Copy input ISO value to Language variable
+ //
+ CopyMem (Language, LanguageString, 6);
+ }
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+LangNotFound:
+ if (StringPackageInstance->IfrSize > 0) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);
+ } else {
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
+ }
+ //
+ // If Token is 0, extract entire string package
+ //
+ if (Token == 0) {
+ //
+ // Compute the entire string pack length, including all languages' and the terminating pack's.
+ //
+ Length = 0;
+ while (0 != StringPack->Header.Length) {
+ Length += StringPack->Header.Length;
+ StringPack = (VOID*)(((UINT8*)StringPack) + StringPack->Header.Length);
+ }
+ //
+ // Back to the start of package.
+ //
+ StringPack = (VOID*)(((UINT8*)StringPack) - Length);
+ //
+ // Terminating zero sub-pack.
+ //
+ Length += sizeof (EFI_HII_STRING_PACK);
+
+ //
+ // If trying to get the entire string package and have insufficient space. Return error.
+ //
+ if (Length > *BufferLength || StringBuffer == NULL) {
+ *BufferLength = (UINT16)Length;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Copy the Pack to the caller's buffer.
+ //
+ *BufferLength = (UINT16)Length;
+ CopyMem (StringBuffer, StringPack, Length);
+
+ return EFI_SUCCESS;
+ }
+ //
+ // There may be multiple instances packed together of strings
+ // so we must walk the self describing structures until we encounter
+ // what we are looking for, and then extract the string we are looking for
+ //
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ for (; Length != 0;) {
+ //
+ // If passed in Language ISO value is in this string pack's language string
+ // then we are dealing with the strings we want.
+ //
+ CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST));
+ Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language);
+
+ //
+ // If we cannot find the lang variable, we skip this check and use the first language available
+ //
+ if (LangFound) {
+ if (EFI_ERROR (Status)) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
+ continue;
+ }
+ }
+
+ StringPointer = (RELOFST *) (StringPack + 1);
+
+ //
+ // We have the right string package - size it, and copy it to the StringBuffer
+ //
+ if (Token >= StringPack->NumStringPointers) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ CopyMem (&Offset, &StringPointer[Token], sizeof (RELOFST));
+ }
+ //
+ // Since StringPack is a packed structure, we need to determine the string's
+ // size safely, thus byte-wise. Post-increment the size to include the null-terminator
+ //
+ Local = (UINT16 *) ((CHAR8 *) (StringPack) + Offset);
+ for (Count = 0; CompareMem (&Local[Count], &Zero, 2); Count++)
+ ;
+ Count++;
+
+ Count = Count * sizeof (CHAR16);;
+
+ if (*BufferLength >= Count && StringBuffer != NULL) {
+ //
+ // Copy the string to the user's buffer
+ //
+ if (Raw) {
+ CopyMem (StringBuffer, Local, Count);
+ } else {
+ for (Count = 0; CompareMem (Local, &Zero, 2); Local++) {
+ //
+ // Skip "Narraw, Wide, NoBreak"
+ //
+ if (CompareMem (Local, &Narrow, 2) &&
+ CompareMem (Local, &Wide, 2) &&
+ CompareMem (Local, &NoBreak, 2)) {
+ CopyMem (&StringBuffer[Count++], Local, 2);
+ }
+ }
+ //
+ // Add "NULL" at the end.
+ //
+ CopyMem (&StringBuffer[Count], &Zero, 2);
+ Count++;
+ Count *= sizeof (CHAR16);
+ }
+
+ *BufferLength = (UINT16) Count;
+ return EFI_SUCCESS;
+ } else {
+ *BufferLength = (UINT16) Count;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ }
+
+ LangFound = FALSE;
+ goto LangNotFound;
+}
+
+EFI_STATUS
+EFIAPI
+HiiGetLine (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN OUT UINT16 *Index,
+ IN UINT16 LineWidth,
+ IN CHAR16 *LanguageString,
+ IN OUT UINT16 *BufferLength,
+ OUT EFI_STRING StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function allows a program to extract a part of a string of not more than a given width.
+ With repeated calls, this allows a calling program to extract "lines" of text that fit inside
+ columns. The effort of measuring the fit of strings inside columns is localized to this call.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Count;
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
+ EFI_HII_DATA *HiiData;
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;
+ EFI_HII_STRING_PACK *StringPack;
+ RELOFST *StringPointer;
+ CHAR16 *Location;
+ EFI_STATUS Status;
+ UINTN DataSize;
+ CHAR8 Lang[3];
+ CHAR16 Language[3];
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HiiData = EFI_HII_DATA_FROM_THIS (This);
+
+ HandleDatabase = HiiData->DatabaseHead;
+
+ PackageInstance = NULL;
+ DataSize = 4;
+
+ //
+ // Check numeric value against the head of the database
+ //
+ for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
+ //
+ // Match the numeric value with the database entry - if matched, extract PackageInstance
+ //
+ if (Handle == HandleDatabase->Handle) {
+ PackageInstance = HandleDatabase->Buffer;
+ }
+ }
+ //
+ // No handle was found - error condition
+ //
+ if (PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);
+
+ //
+ // If there is no specified language, assume the system default language
+ //
+ if (LanguageString == NULL) {
+ //
+ // Get system default language
+ //
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &DataSize,
+ Lang
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Convert the ASCII Lang variable to a Unicode Language variable
+ //
+ AsciiToUnicode ((UINT8 *)Lang, Language);
+ } else {
+ //
+ // Copy input ISO value to Language variable
+ //
+ CopyMem (Language, LanguageString, 6);
+ }
+ //
+ // Based on if there is IFR data in this package instance, determine
+ // what the location is of the beginning of the string data.
+ //
+ if (StringPackageInstance->IfrSize > 0) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);
+ } else {
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);
+ }
+
+ StringPointer = (RELOFST *) (StringPack + 1);
+
+ //
+ // There may be multiple instances packed together of strings
+ // so we must walk the self describing structures until we encounter
+ // what we are looking for, and then extract the string we are looking for
+ //
+ for (; StringPack->Header.Length != 0;) {
+ //
+ // If passed in Language ISO value is in this string pack's language string
+ // then we are dealing with the strings we want.
+ //
+ Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language);
+
+ if (EFI_ERROR (Status)) {
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
+ continue;
+ }
+
+ Location = (CHAR16 *) ((CHAR8 *) (StringPack) + StringPointer[Token] +*Index * 2);
+
+ //
+ // If the size of the remaining string is less than the LineWidth
+ // then copy the entire thing
+ //
+ if (StrSize (Location) <= LineWidth) {
+ if (*BufferLength >= StrSize (Location)) {
+ StrCpy (StringBuffer, Location);
+ return EFI_SUCCESS;
+ } else {
+ *BufferLength = (UINT16) StrSize (Location);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ } else {
+ //
+ // Rewind the string from the maximum size until we see a space the break the line
+ //
+ for (Count = LineWidth; Location[Count] != 0x0020; Count--)
+ ;
+
+ //
+ // Put the index at the next character
+ //
+ *Index = (UINT16) (Count + 1);
+
+ if (*BufferLength >= Count) {
+ StrnCpy (StringBuffer, Location, Count);
+ return EFI_SUCCESS;
+ } else {
+ *BufferLength = (UINT16) Count;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HiiCompareLanguage (
+ IN CHAR16 *LanguageStringLocation,
+ IN CHAR16 *Language
+ )
+{
+ UINT8 *Local;
+ UINTN Index;
+ CHAR16 *InputString;
+ CHAR16 *OriginalInputString;
+
+ //
+ // Allocate a temporary buffer for InputString
+ //
+ InputString = AllocateZeroPool (0x100);
+
+ ASSERT (InputString);
+
+ OriginalInputString = InputString;
+
+ Local = (UINT8 *) LanguageStringLocation;
+
+ //
+ // Determine the size of this packed string safely (e.g. access by byte), post-increment
+ // to include the null-terminator
+ //
+ for (Index = 0; Local[Index] != 0; Index = Index + 2)
+ ;
+ //
+ // MARMAR Index = Index + 2;
+ //
+ // This is a packed structure that this location comes from, so let's make sure
+ // the value is aligned by copying it to a local variable and working on it.
+ //
+ CopyMem (InputString, LanguageStringLocation, Index);
+
+ for (Index = 0; Index < 3; Index++) {
+ InputString[Index] = (CHAR16) (InputString[Index] | 0x20);
+ Language[Index] = (CHAR16) (Language[Index] | 0x20);
+ }
+ //
+ // If the Language is the same return success
+ //
+ if (CompareMem (LanguageStringLocation, Language, 6) == 0) {
+ FreePool (InputString);
+ return EFI_SUCCESS;
+ }
+ //
+ // Skip the first three letters that comprised the primary language,
+ // see if what is being compared against is a secondary language
+ //
+ InputString = InputString + 3;
+
+ //
+ // If the Language is not the same as the Primary language, see if there are any
+ // secondary languages, and if there are see if we have a match. If not, return an error.
+ //
+ for (Index = 0; InputString[Index] != 0; Index = Index + 3) {
+ //
+ // Getting in here means we have a secondary language
+ //
+ if (CompareMem (&InputString[Index], Language, 6) == 0) {
+ FreePool (InputString);
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // If nothing was found, return the error
+ //
+ FreePool (OriginalInputString);
+ return EFI_NOT_FOUND;
+
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Boolean.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Boolean.c
new file mode 100644
index 0000000000..b0af07ecbe
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Boolean.c
@@ -0,0 +1,1372 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Boolean.c
+
+Abstract:
+
+ This routine will evaluate the IFR inconsistency data to determine if
+ something is a valid entry for a particular expression
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+
+//
+// Global stack used to evaluate boolean expresions
+//
+BOOLEAN *mBooleanEvaluationStack = (BOOLEAN) 0;
+BOOLEAN *mBooleanEvaluationStackEnd = (BOOLEAN) 0;
+
+STATIC
+VOID
+GrowBooleanStack (
+ IN OUT BOOLEAN **Stack,
+ IN UINTN StackSizeInBoolean
+ )
+/*++
+
+Routine Description:
+
+ Grow size of the boolean stack
+
+Arguments:
+
+ Stack - Old stack on the way in and new stack on the way out
+
+ StackSizeInBoolean - New size of the stack
+
+Returns:
+
+ NONE
+
+--*/
+{
+ BOOLEAN *NewStack;
+
+ NewStack = AllocatePool (StackSizeInBoolean * sizeof (BOOLEAN));
+ ASSERT (NewStack != NULL);
+
+ if (*Stack != NULL) {
+ //
+ // Copy to Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ mBooleanEvaluationStack,
+ (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN)
+ );
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *Stack = NewStack + (*Stack - mBooleanEvaluationStack);
+
+ //
+ // Free The Old Stack
+ //
+ FreePool (mBooleanEvaluationStack);
+ }
+
+ mBooleanEvaluationStack = NewStack;
+ mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean;
+}
+
+STATIC
+VOID
+InitializeBooleanEvaluator (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate a global stack for boolean processing.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ BOOLEAN *NullStack;
+
+ NullStack = NULL;
+ GrowBooleanStack (&NullStack, 0x1000);
+}
+
+STATIC
+VOID
+PushBool (
+ IN OUT BOOLEAN **Stack,
+ IN BOOLEAN BoolResult
+ )
+/*++
+
+Routine Description:
+
+ Push an element onto the Boolean Stack
+
+Arguments:
+
+ Stack - Current stack location.
+ BoolResult - BOOLEAN to push.
+
+Returns:
+
+ None.
+
+--*/
+{
+ CopyMem (*Stack, &BoolResult, sizeof (BOOLEAN));
+ *Stack += 1;
+
+ if (*Stack >= mBooleanEvaluationStackEnd) {
+ //
+ // If we run out of stack space make a new one that is 2X as big. Copy
+ // the old data into the new stack and update Stack to point to the old
+ // data in the new stack.
+ //
+ GrowBooleanStack (
+ Stack,
+ (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) * 2
+ );
+ }
+}
+
+STATIC
+BOOLEAN
+PopBool (
+ IN OUT BOOLEAN **Stack
+ )
+/*++
+
+Routine Description:
+
+ Pop an element from the Boolean stack.
+
+Arguments:
+
+ Stack - Current stack location
+
+Returns:
+
+ Top of the BOOLEAN stack.
+
+--*/
+{
+ BOOLEAN ReturnValue;
+
+ *Stack -= 1;
+ CopyMem (&ReturnValue, *Stack, sizeof (BOOLEAN));
+ return ReturnValue;
+}
+
+STATIC
+EFI_STATUS
+GrowBooleanExpression (
+ IN EFI_INCONSISTENCY_DATA *InconsistentTags,
+ OUT VOID **BooleanExpression,
+ IN OUT UINTN *BooleanExpressionLength
+ )
+{
+ UINT8 *NewExpression;
+
+ NewExpression = AllocatePool (*BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA));
+ ASSERT (NewExpression != NULL);
+
+ if (*BooleanExpression != NULL) {
+ //
+ // Copy Old buffer to the New buffer
+ //
+ CopyMem (NewExpression, *BooleanExpression, *BooleanExpressionLength);
+
+ CopyMem (&NewExpression[*BooleanExpressionLength], InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
+
+ //
+ // Free The Old buffer
+ //
+ FreePool (*BooleanExpression);
+ } else {
+ //
+ // Copy data into new buffer
+ //
+ CopyMem (NewExpression, InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
+ }
+
+ *BooleanExpressionLength = *BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA);
+ *BooleanExpression = (VOID *) NewExpression;
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+CreateBooleanExpression (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 Value,
+ IN UINT16 Id,
+ IN BOOLEAN Complex,
+ OUT VOID **BooleanExpression,
+ OUT UINTN *BooleanExpressionLength
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINTN Count;
+ EFI_INCONSISTENCY_DATA *InconsistentTags;
+ EFI_INCONSISTENCY_DATA FakeInconsistentTags;
+
+ InconsistentTags = FileFormTags->InconsistentTags;
+
+ //
+ // Did we run into a question that contains the Id we are looking for?
+ //
+ for (Count = 0; InconsistentTags->Operand != 0xFF; Count++) {
+
+ //
+ // Reserve INVALID_OFFSET_VALUE - 1 for TURE and FALSE, because we need to treat them as well
+ // as ideqid etc. but they have no coresponding id, so we reserve this value.
+ //
+ if (InconsistentTags->QuestionId1 == Id ||
+ InconsistentTags->QuestionId1 == INVALID_OFFSET_VALUE - 1) {
+ //
+ // If !Complex - means evaluate a single if/endif expression
+ //
+ if (!Complex) {
+ //
+ // If the ConsistencyId does not match the expression we are looking for
+ // skip to the next consistency database entry
+ //
+ if (InconsistentTags->ConsistencyId != Value) {
+ goto NextEntry;
+ }
+ }
+ //
+ // We need to rewind to the beginning of the Inconsistent expression
+ //
+ for (;
+ (InconsistentTags->Operand != EFI_IFR_INCONSISTENT_IF_OP) &&
+ (InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP) &&
+ (InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP);
+ ) {
+ InconsistentTags = InconsistentTags->Previous;
+ }
+ //
+ // Store the consistency check expression, ensure the next for loop starts at the op-code afterwards
+ //
+ GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
+ InconsistentTags = InconsistentTags->Next;
+
+ //
+ // Keep growing until we hit the End expression op-code or we hit the beginning of another
+ // consistency check like grayout/suppress
+ //
+ for (;
+ InconsistentTags->Operand != EFI_IFR_END_IF_OP &&
+ InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP &&
+ InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP;
+ ) {
+ GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
+ InconsistentTags = InconsistentTags->Next;
+ }
+ //
+ // Store the EndExpression Op-code
+ //
+ GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
+ }
+
+NextEntry:
+ if (InconsistentTags->Next != NULL) {
+ //
+ // Skip to next entry
+ //
+ InconsistentTags = InconsistentTags->Next;
+ }
+ }
+
+ FakeInconsistentTags.Operand = 0;
+
+ //
+ // Add one last expression which will signify we have definitely hit the end
+ //
+ GrowBooleanExpression (&FakeInconsistentTags, BooleanExpression, BooleanExpressionLength);
+}
+
+STATIC
+EFI_STATUS
+BooleanVariableWorker (
+ IN CHAR16 *VariableName,
+ IN EFI_VARIABLE_DEFINITION *VariableDefinition,
+ IN BOOLEAN *StackPtr,
+ IN OUT UINTN *SizeOfVariable,
+ IN OUT VOID **VariableData
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = gRT->GetVariable (
+ VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ SizeOfVariable,
+ *VariableData
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ *VariableData = AllocatePool (*SizeOfVariable);
+ ASSERT (*VariableData != NULL);
+
+ Status = gRT->GetVariable (
+ VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ SizeOfVariable,
+ *VariableData
+ );
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // This is a serious flaw, we must have some standard result if a variable
+ // is not found. Our default behavior must either be return a TRUE or FALSE
+ // since there is nothing else we can really do. Therefore, my crystal ball
+ // says I will return a FALSE
+ //
+ PushBool (&StackPtr, FALSE);
+ }
+ }
+
+ return Status;
+}
+
+STATIC
+UINT8
+PredicateIfrType (
+ IN EFI_INCONSISTENCY_DATA *Iterator
+ )
+/*++
+
+Routine Description:
+ This routine is for the purpose of predicate whether the Ifr is generated by a VfrCompiler greater than or equal to 1.88 or
+ less than 1.88 which is legacy.
+
+Arguments:
+ Iterator - The pointer to inconsistency tags
+
+Returns:
+
+ 0x2 - If IFR is not legacy
+
+ 0x1 - If IFR is legacy
+
+--*/
+{
+ //
+ // legacy Ifr cover the states:
+ // Not ...
+ // Operand Opcode Operand
+ //
+ // while Operand means ideqval, TRUE, or other what can be evaluated to True or False,
+ // and Opcode means AND or OR.
+ //
+ if (Iterator->Operand == EFI_IFR_NOT_OP ||
+ Iterator->Operand == 0) {
+ return 0x1;
+ } else if (Iterator->Operand == EFI_IFR_EQ_VAR_VAL_OP ||
+ Iterator->Operand == EFI_IFR_EQ_ID_VAL_OP ||
+ Iterator->Operand == EFI_IFR_EQ_ID_ID_OP ||
+ Iterator->Operand == EFI_IFR_EQ_ID_LIST_OP) {
+ Iterator++;
+ if (Iterator->Operand == EFI_IFR_AND_OP ||
+ Iterator->Operand == EFI_IFR_OR_OP) {
+ Iterator--;
+ return 0x1;
+ }
+ Iterator--;
+ }
+ return 0x2;
+}
+
+STATIC
+VOID
+PostOrderEvaluate (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 Width,
+ IN OUT EFI_INCONSISTENCY_DATA **PIterator,
+ IN OUT BOOLEAN **StackPtr
+ )
+/*++
+
+Routine Description:
+ PostOrderEvaluate is used for Ifr generated by VfrCompiler greater than or equal to 1.88,
+ which generate Operand Operand Opcode type Ifr.
+ PostOrderEvaluete only evaluate boolean expression part, not suppressif/grayoutif. TRUE,
+ FALSE, >=, >, (, ) are supported.
+
+Arguments:
+
+ FileFormTags - The pointer to the tags of the form
+
+ Width - Width of Operand, recognized every iteration
+
+ PIterator - The pointer to inconsistency tags
+
+ StackPtr - The pointer to the evaluation stack
+
+Returns:
+
+ TRUE - If value is valid
+
+ FALSE - If value is not valid
+
+--*/
+{
+ BOOLEAN Operator;
+ BOOLEAN Operator2;
+ UINT16 *MapBuffer;
+ UINT16 *MapBuffer2;
+ UINT16 MapValue;
+ UINT16 MapValue2;
+ UINTN SizeOfVariable;
+ CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];
+ VOID *VariableData;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN PushValue;
+
+ Operator = FALSE;
+ Operator2 = FALSE;
+ MapBuffer = NULL;
+ MapBuffer2 = NULL;
+ MapValue = 0;
+ MapValue2 = 0;
+ VariableData = NULL;
+
+ while (TRUE) {
+ if ((*PIterator)->Operand == 0) {
+ return;
+ }
+
+ Width = (*PIterator)->Width;
+
+ //
+ // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
+ //
+ if ((*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE &&
+ (*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE - 1) {
+ ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber, Width, (*PIterator)->QuestionId1, (VOID **) &MapBuffer);
+ ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber2, Width, (*PIterator)->QuestionId2, (VOID **) &MapBuffer2);
+ if (MapBuffer != NULL) {
+ if (Width == 2) {
+ MapValue = *MapBuffer;
+ } else {
+ MapValue = (UINT8) *MapBuffer;
+ }
+
+ FreePool (MapBuffer);
+ }
+
+ if (MapBuffer2 != NULL) {
+ if (Width == 2) {
+ MapValue2 = *MapBuffer2;
+ } else {
+ MapValue2 = (UINT8) *MapBuffer2;
+ }
+
+ FreePool (MapBuffer2);
+ }
+ }
+
+ switch ((*PIterator)->Operand) {
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ UnicodeValueToString (
+ VariableName,
+ FALSE,
+ (UINTN) (*PIterator)->QuestionId1,
+ (sizeof (VariableName) / sizeof (VariableName[0])) - 1
+ );
+
+ SizeOfVariable = 0;
+
+ ExtractRequestedNvMap (FileFormTags, (*PIterator)->VariableNumber, &VariableDefinition);
+
+ Status = BooleanVariableWorker (
+ VariableName,
+ VariableDefinition,
+ *StackPtr,
+ &SizeOfVariable,
+ &VariableData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SizeOfVariable == 1) {
+ CopyMem (&MapValue, VariableData, 1);
+ } else {
+ CopyMem (&MapValue, VariableData, 2);
+ }
+
+ //
+ // Do operation after knowing the compare operator.
+ //
+ MapValue2 = (*PIterator)->Value;
+ (*PIterator)++;
+ if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
+ PushValue = (BOOLEAN) (MapValue > MapValue2);
+ } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
+ PushValue = (BOOLEAN) (MapValue >= MapValue2);
+ } else {
+ (*PIterator)--;
+ PushValue = (BOOLEAN) (MapValue == MapValue2);
+ }
+ PushBool (StackPtr, PushValue);
+ }
+
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ //
+ // Do operation after knowing the compare operator.
+ //
+ MapValue2 = (*PIterator)->Value;
+ (*PIterator)++;
+ if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
+ PushValue = (BOOLEAN) (MapValue > MapValue2);
+ } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
+ PushValue = (BOOLEAN) (MapValue >= MapValue2);
+ } else {
+ (*PIterator)--;
+ PushValue = (BOOLEAN) (MapValue == MapValue2);
+ }
+ PushBool (StackPtr, PushValue);
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ //
+ // Do operation after knowing the compare operator.
+ //
+ (*PIterator)++;
+ if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
+ PushValue = (BOOLEAN) (MapValue > MapValue2);
+ } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
+ PushValue = (BOOLEAN) (MapValue >= MapValue2);
+ } else {
+ (*PIterator)--;
+ PushValue = (BOOLEAN) (MapValue == MapValue2);
+ }
+ PushBool (StackPtr, PushValue);
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ for (Index = 0; Index < (*PIterator)->ListLength; Index++) {
+ Operator = (BOOLEAN) (MapValue == (*PIterator)->ValueList[Index]);
+ if (Operator) {
+ break;
+ }
+ }
+
+ PushBool (StackPtr, Operator);
+ break;
+
+ case EFI_IFR_TRUE_OP:
+ PushBool (StackPtr, TRUE);
+ break;
+
+ case EFI_IFR_FALSE_OP:
+ PushBool (StackPtr, FALSE);
+ break;
+
+ case EFI_IFR_AND_OP:
+ Operator = PopBool (StackPtr);
+ Operator2 = PopBool (StackPtr);
+ PushBool (StackPtr, (BOOLEAN) (Operator && Operator2));
+ break;
+ case EFI_IFR_OR_OP:
+ Operator = PopBool (StackPtr);
+ Operator2 = PopBool (StackPtr);
+ PushBool (StackPtr, (BOOLEAN) (Operator || Operator2));
+ break;
+ case EFI_IFR_NOT_OP:
+ Operator = PopBool (StackPtr);
+ PushBool (StackPtr, (BOOLEAN) (!Operator));
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+ case EFI_IFR_GRAYOUT_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ default:
+ //
+ // Return to the previous tag if runs out of boolean expression.
+ //
+ (*PIterator)--;
+ return;
+ }
+ (*PIterator)++;
+ }
+}
+
+BOOLEAN
+ValueIsNotValid (
+ IN BOOLEAN Complex,
+ IN UINT16 Value,
+ IN EFI_TAG *Tag,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN STRING_REF *PopUp
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ TRUE - If value is valid
+
+ FALSE - If value is not valid
+
+--*/
+{
+ BOOLEAN *StackPtr;
+ EFI_INCONSISTENCY_DATA *Iterator;
+ BOOLEAN Operator;
+ BOOLEAN Operator2;
+ UINTN Index;
+ VOID *BooleanExpression;
+ UINTN BooleanExpressionLength;
+ BOOLEAN NotOperator;
+ BOOLEAN OrOperator;
+ BOOLEAN AndOperator;
+ BOOLEAN ArtificialEnd;
+ UINT16 *MapBuffer;
+ UINT16 *MapBuffer2;
+ UINT16 MapValue;
+ UINT16 MapValue2;
+ UINTN SizeOfVariable;
+ CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];
+ VOID *VariableData;
+ EFI_STATUS Status;
+ UINT16 Id;
+ UINT16 Width;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ BOOLEAN CosmeticConsistency;
+ UINT8 IsLegacy;
+
+ VariableData = NULL;
+ BooleanExpressionLength = 0;
+ BooleanExpression = NULL;
+ Operator = FALSE;
+ ArtificialEnd = FALSE;
+ CosmeticConsistency = TRUE;
+ IsLegacy = 0;
+
+ Id = Tag->Id;
+ if (Tag->StorageWidth == 1) {
+ Width = 1;
+ } else {
+ Width = 2;
+ }
+ CreateBooleanExpression (FileFormTags, Value, Id, Complex, &BooleanExpression, &BooleanExpressionLength);
+
+ if (mBooleanEvaluationStack == 0) {
+ InitializeBooleanEvaluator ();
+ }
+
+ if (BooleanExpression == NULL) {
+ return FALSE;
+ }
+
+ StackPtr = mBooleanEvaluationStack;
+ Iterator = BooleanExpression;
+ MapBuffer = NULL;
+ MapBuffer2 = NULL;
+ MapValue = 0;
+ MapValue2 = 0;
+
+ while (TRUE) {
+ NotOperator = FALSE;
+ OrOperator = FALSE;
+ AndOperator = FALSE;
+
+ if (Iterator->Operand == 0) {
+ return Operator;
+ }
+
+ //
+ // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
+ //
+ if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE &&
+ Iterator->QuestionId1 != INVALID_OFFSET_VALUE-1) {
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
+ if (MapBuffer != NULL) {
+ if (Width == 2) {
+ MapValue = *MapBuffer;
+ } else {
+ MapValue = (UINT8) *MapBuffer;
+ }
+
+ FreePool (MapBuffer);
+ }
+
+ if (MapBuffer2 != NULL) {
+ if (Width == 2) {
+ MapValue2 = *MapBuffer2;
+ } else {
+ MapValue2 = (UINT8) *MapBuffer2;
+ }
+
+ FreePool (MapBuffer2);
+ }
+ }
+
+ switch (Iterator->Operand) {
+ case EFI_IFR_SUPPRESS_IF_OP:
+ //
+ // Must have hit a suppress followed by a grayout or vice-versa
+ //
+ if (ArtificialEnd) {
+ ArtificialEnd = FALSE;
+ Operator = PopBool (&StackPtr);
+ if (Operator) {
+ Tag->Suppress = TRUE;
+ }
+
+ return Operator;
+ }
+
+ ArtificialEnd = TRUE;
+ *PopUp = Iterator->Popup;
+ break;
+
+ case EFI_IFR_GRAYOUT_IF_OP:
+ //
+ // Must have hit a suppress followed by a grayout or vice-versa
+ //
+ if (ArtificialEnd) {
+ ArtificialEnd = FALSE;
+ Operator = PopBool (&StackPtr);
+ if (Operator) {
+ Tag->GrayOut = TRUE;
+ }
+
+ return Operator;
+ }
+
+ ArtificialEnd = TRUE;
+ *PopUp = Iterator->Popup;
+ break;
+
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ CosmeticConsistency = FALSE;
+ *PopUp = Iterator->Popup;
+ break;
+
+ //
+ // In the case of external variable values, we must read the variable which is
+ // named by the human readable version of the OpCode->VariableId and the guid of the formset
+ //
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+
+ UnicodeValueToString (
+ VariableName,
+ FALSE,
+ (UINTN) Iterator->QuestionId1,
+ (sizeof (VariableName) / sizeof (VariableName[0])) - 1
+ );
+
+ SizeOfVariable = 0;
+
+ ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
+
+ Status = BooleanVariableWorker (
+ VariableName,
+ VariableDefinition,
+ StackPtr,
+ &SizeOfVariable,
+ &VariableData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SizeOfVariable == 1) {
+ CopyMem (&MapValue, VariableData, 1);
+ } else {
+ CopyMem (&MapValue, VariableData, 2);
+ }
+
+ PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
+ }
+
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+
+ PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+
+ PushBool (&StackPtr, (BOOLEAN) (MapValue == MapValue2));
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+
+ for (Index = 0; Index < Iterator->ListLength; Index++) {
+ Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
+ if (Operator) {
+ break;
+ }
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ case EFI_IFR_AND_OP:
+ Iterator++;
+ if (Iterator->Operand == EFI_IFR_NOT_OP) {
+ NotOperator = TRUE;
+ Iterator++;
+ }
+
+ if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
+ if (MapBuffer != NULL) {
+ if (Width == 2) {
+ MapValue = *MapBuffer;
+ } else {
+ MapValue = (UINT8) *MapBuffer;
+ }
+
+ FreePool (MapBuffer);
+ }
+
+ if (MapBuffer2 != NULL) {
+ if (Width == 2) {
+ MapValue2 = *MapBuffer2;
+ } else {
+ MapValue2 = (UINT8) *MapBuffer2;
+ }
+
+ FreePool (MapBuffer2);
+ }
+ }
+
+ switch (Iterator->Operand) {
+ case EFI_IFR_EQ_ID_VAL_OP:
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == Iterator->Value);
+ } else {
+ Operator = (BOOLEAN) (MapValue == Iterator->Value);
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ //
+ // In the case of external variable values, we must read the variable which is
+ // named by the human readable version of the OpCode->VariableId and the guid of the formset
+ //
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ UnicodeValueToString (
+ VariableName,
+ FALSE,
+ (UINTN) Iterator->QuestionId1,
+ (sizeof (VariableName) / sizeof (VariableName[0])) - 1
+ );
+
+ SizeOfVariable = 0;
+
+ ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
+
+ Status = BooleanVariableWorker (
+ VariableName,
+ VariableDefinition,
+ StackPtr,
+ &SizeOfVariable,
+ &VariableData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SizeOfVariable == 1) {
+ CopyMem (&MapValue, VariableData, 1);
+ } else {
+ CopyMem (&MapValue, VariableData, 2);
+ }
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
+ } else {
+ PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
+ }
+ }
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == MapValue2);
+ } else {
+ Operator = (BOOLEAN) (MapValue == MapValue2);
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ for (Index = 0; Index < Iterator->ListLength; Index++) {
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
+ } else {
+ Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
+ }
+ //
+ // If We are trying to make sure that MapValue != Item[x], keep looking through
+ // the list to make sure we don't equal any other items
+ //
+ if (Operator && NotOperator) {
+ continue;
+ }
+ //
+ // If MapValue == Item, then we have succeeded (first found is good enough)
+ //
+ if (Operator) {
+ break;
+ }
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ Operator = PopBool (&StackPtr);
+ Operator2 = PopBool (&StackPtr);
+ PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
+ break;
+
+ case EFI_IFR_OR_OP:
+ Iterator++;
+ if (Iterator->Operand == EFI_IFR_NOT_OP) {
+ NotOperator = TRUE;
+ Iterator++;
+ }
+
+ if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
+ if (MapBuffer != NULL) {
+ if (Width == 2) {
+ MapValue = *MapBuffer;
+ } else {
+ MapValue = (UINT8) *MapBuffer;
+ }
+
+ FreePool (MapBuffer);
+ }
+
+ if (MapBuffer2 != NULL) {
+ if (Width == 2) {
+ MapValue2 = *MapBuffer2;
+ } else {
+ MapValue2 = (UINT8) *MapBuffer2;
+ }
+
+ FreePool (MapBuffer2);
+ }
+ }
+
+ switch (Iterator->Operand) {
+ case EFI_IFR_EQ_ID_VAL_OP:
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == Iterator->Value);
+ } else {
+ Operator = (BOOLEAN) (MapValue == Iterator->Value);
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ //
+ // In the case of external variable values, we must read the variable which is
+ // named by the human readable version of the OpCode->VariableId and the guid of the formset
+ //
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ UnicodeValueToString (
+ VariableName,
+ FALSE,
+ (UINTN) Iterator->QuestionId1,
+ (sizeof (VariableName) / sizeof (VariableName[0])) - 1
+ );
+
+ SizeOfVariable = 0;
+
+ ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
+
+ Status = BooleanVariableWorker (
+ VariableName,
+ VariableDefinition,
+ StackPtr,
+ &SizeOfVariable,
+ &VariableData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SizeOfVariable == 1) {
+ CopyMem (&MapValue, VariableData, 1);
+ } else {
+ CopyMem (&MapValue, VariableData, 2);
+ }
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
+ } else {
+ PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
+ }
+ }
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == MapValue2);
+ } else {
+ Operator = (BOOLEAN) (MapValue == MapValue2);
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ for (Index = 0; Index < Iterator->ListLength; Index++) {
+ //
+ // If Not - flip the results
+ //
+ if (NotOperator) {
+ Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
+ } else {
+ Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
+ }
+ //
+ // If We are trying to make sure that MapValue != Item[x], keep looking through
+ // the list to make sure we don't equal any other items
+ //
+ if (Operator && NotOperator) {
+ continue;
+ }
+ //
+ // If MapValue == Item, then we have succeeded (first found is good enough)
+ //
+ if (Operator) {
+ break;
+ }
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ Operator = PopBool (&StackPtr);
+ Operator2 = PopBool (&StackPtr);
+ PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
+ break;
+
+ case EFI_IFR_NOT_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+
+ //
+ // I don't need to set the NotOperator (I know that I have to NOT this in this case
+ //
+ Iterator++;
+
+ if (Iterator->Operand == EFI_IFR_OR_OP) {
+ OrOperator = TRUE;
+ Iterator++;
+ }
+
+ if (Iterator->Operand == EFI_IFR_AND_OP) {
+ AndOperator = TRUE;
+ Iterator++;
+ }
+
+ if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
+ ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
+ if (MapBuffer != NULL) {
+ if (Width == 2) {
+ MapValue = *MapBuffer;
+ } else {
+ MapValue = (UINT8) *MapBuffer;
+ }
+
+ FreePool (MapBuffer);
+ }
+
+ if (MapBuffer2 != NULL) {
+ if (Width == 2) {
+ MapValue2 = *MapBuffer2;
+ } else {
+ MapValue2 = (UINT8) *MapBuffer2;
+ }
+
+ FreePool (MapBuffer2);
+ }
+ }
+
+ switch (Iterator->Operand) {
+ case EFI_IFR_EQ_ID_VAL_OP:
+ Operator = (BOOLEAN)!(MapValue == Iterator->Value);
+ PushBool (&StackPtr, Operator);
+ break;
+
+ //
+ // In the case of external variable values, we must read the variable which is
+ // named by the human readable version of the OpCode->VariableId and the guid of the formset
+ //
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ UnicodeValueToString (
+ VariableName,
+ FALSE,
+ (UINTN) Iterator->QuestionId1,
+ (sizeof (VariableName) / sizeof (VariableName[0])) - 1
+ );
+
+ SizeOfVariable = 0;
+
+ ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
+
+ Status = BooleanVariableWorker (
+ VariableName,
+ VariableDefinition,
+ StackPtr,
+ &SizeOfVariable,
+ &VariableData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (SizeOfVariable == 1) {
+ CopyMem (&MapValue, VariableData, 1);
+ } else {
+ CopyMem (&MapValue, VariableData, 2);
+ }
+
+ PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
+ }
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ Operator = (BOOLEAN)!(MapValue == MapValue2);
+ PushBool (&StackPtr, Operator);
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ for (Index = 0; Index < Iterator->ListLength; Index++) {
+ Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
+ if (Operator) {
+ continue;
+ }
+ }
+
+ PushBool (&StackPtr, Operator);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ Operator = PopBool (&StackPtr);
+ Operator2 = PopBool (&StackPtr);
+
+ if (OrOperator) {
+ PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
+ }
+
+ if (AndOperator) {
+ PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
+ }
+
+ if (!OrOperator && !AndOperator) {
+ PushBool (&StackPtr, Operator);
+ }
+ break;
+
+ case EFI_IFR_TRUE_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+ break;
+
+ case EFI_IFR_FALSE_OP:
+ //
+ // To check whether Ifr is legacy. Once every boolean expression.
+ //
+ if (IsLegacy == 0) {
+ IsLegacy = PredicateIfrType (Iterator);
+ }
+ if (IsLegacy == 0x2) {
+ PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
+ break;
+ }
+ break;
+
+ case EFI_IFR_END_IF_OP:
+ Operator = PopBool (&StackPtr);
+ //
+ // If there is an error, return, otherwise keep looking - there might
+ // be another test that causes an error
+ //
+ if (Operator) {
+ if (Complex && CosmeticConsistency) {
+ return EFI_SUCCESS;
+ } else {
+ return Operator;
+ }
+ } else {
+ //
+ // If not doing a global consistency check, the endif is the REAL terminator of this operation
+ // This is used for grayout/suppress operations. InconsistentIf is a global operation so the EndIf is
+ // not the end-all be-all of terminators.
+ //
+ if (!Complex) {
+ return Operator;
+ }
+ break;
+ }
+
+ default:
+ //
+ // Must have hit a non-consistency related op-code after a suppress/grayout
+ //
+ if (ArtificialEnd) {
+ ArtificialEnd = FALSE;
+ Operator = PopBool (&StackPtr);
+ return Operator;
+ }
+
+ goto Done;
+ }
+
+ Iterator++;
+ }
+
+Done:
+ return FALSE;
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Colors.h b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Colors.h
new file mode 100644
index 0000000000..2ad2aa9c17
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Colors.h
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Colors.h
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#ifndef _COLORS_H
+#define _COLORS_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// Screen Color Settings
+//
+#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE
+#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN
+#define TITLE_TEXT EFI_WHITE
+#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE
+#define KEYHELP_TEXT EFI_LIGHTGRAY
+#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK
+#define SUBTITLE_TEXT EFI_BLUE
+#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define BANNER_TEXT EFI_BLUE
+#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT EFI_BLACK
+#define FIELD_TEXT_GRAYED EFI_DARKGRAY
+#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+#define FIELD_TEXT_HIGHLIGHT EFI_LIGHTGRAY
+#define FIELD_BACKGROUND_HIGHLIGHT EFI_BACKGROUND_BLACK
+#define POPUP_TEXT EFI_LIGHTGRAY
+#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE
+#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY
+#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK
+#define HELP_TEXT EFI_BLUE
+#define ERROR_TEXT EFI_RED | EFI_BRIGHT
+#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT
+#define ARROW_TEXT EFI_RED | EFI_BRIGHT
+#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/CommonHeader.h b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/CommonHeader.h
new file mode 100644
index 0000000000..ab5ebc3a68
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/CommonHeader.h
@@ -0,0 +1,44 @@
+/**@file
+ Common header file shared by all source files.
+
+ This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+ Copyright (c) 2006 - 2007, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/FormCallback.h>
+#include <Protocol/FormBrowser.h>
+#include <Protocol/FrameworkHii.h>
+#include <Protocol/Print.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HiiLibFramework.h>
+#include <Library/GraphicsLib.h>
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/InputHandler.c
new file mode 100644
index 0000000000..4c2189c476
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/InputHandler.c
@@ -0,0 +1,1575 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ InputHandler.C
+
+Abstract:
+
+ Implementation for handling user input from the User Interface
+
+Revision History
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+#include "Colors.h"
+
+#define EFI_MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
+
+EFI_STATUS
+ReadString(
+ IN UI_MENU_OPTION *MenuOption,
+ OUT CHAR16 *StringPtr
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ CHAR16 NullCharacter;
+ UINTN ScreenSize;
+ EFI_TAG *Tag;
+ CHAR16 Space[2];
+ CHAR16 KeyPad[2];
+ BOOLEAN SelectionComplete;
+ CHAR16 *TempString;
+ CHAR16 *BufferedString;
+ UINTN Index;
+ UINTN Count;
+ UINTN Start;
+ UINTN Top;
+ CHAR16 *PromptForDataString;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+ BOOLEAN CursorVisible;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ PromptForDataString = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
+
+ NullCharacter = CHAR_NULL;
+ ScreenSize = GetStringWidth (PromptForDataString) / 2;
+ Tag = MenuOption->ThisTag;
+ Space[0] = L' ';
+ Space[1] = CHAR_NULL;
+ SelectionComplete = FALSE;
+
+ TempString = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
+ ASSERT (TempString);
+
+ if (ScreenSize < (Tag->Maximum / (UINTN) 2)) {
+ ScreenSize = Tag->Maximum / 2;
+ }
+
+ if ((ScreenSize + 2) > DimensionsWidth) {
+ ScreenSize = DimensionsWidth - 2;
+ }
+
+ BufferedString = AllocateZeroPool (ScreenSize * 2);
+ ASSERT (BufferedString);
+
+ Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+
+ //
+ // Display prompt for string
+ //
+ CreatePopUp (ScreenSize, 4, &NullCharacter, PromptForDataString, Space, &NullCharacter);
+
+ FreePool (PromptForDataString);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+
+ CursorVisible = gST->ConOut->Mode->CursorVisible;
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+ switch (Key.UnicodeChar) {
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_LEFT:
+ break;
+
+ case SCAN_RIGHT:
+ break;
+
+ case SCAN_ESC:
+ FreePool (TempString);
+ FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ if (GetStringWidth (StringPtr) >= MenuOption->ThisTag->Minimum) {
+ SelectionComplete = TRUE;
+ FreePool (TempString);
+ FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_SUCCESS;
+ } else {
+ ScreenSize = GetStringWidth (gMiniString) / 2;
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
+ //
+ // Simply create a popup to tell the user that they had typed in too few characters.
+ // To save code space, we can then treat this as an error and return back to the menu.
+ //
+ do {
+ Status = WaitForKeyStroke (&Key);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ FreePool (TempString);
+ FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_DEVICE_ERROR;
+ }
+
+ break;
+
+ case CHAR_BACKSPACE:
+ if (StringPtr[0] != CHAR_NULL) {
+ for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
+ TempString[Index] = StringPtr[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString[Index - 1] = CHAR_NULL;
+ StrCpy (StringPtr, TempString);
+ }
+
+ default:
+ //
+ // If it is the beginning of the string, don't worry about checking maximum limits
+ //
+ if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);
+ StrnCpy (TempString, &Key.UnicodeChar, 1);
+ } else if ((GetStringWidth (StringPtr) < MenuOption->ThisTag->Maximum) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ KeyPad[0] = Key.UnicodeChar;
+ KeyPad[1] = CHAR_NULL;
+ StrCat (StringPtr, KeyPad);
+ StrCat (TempString, KeyPad);
+ }
+ //
+ // If the width of the input string is now larger than the screen, we nee to
+ // adjust the index to start printing portions of the string
+ //
+ SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');
+
+ PrintStringAt (Start + 1, Top + 3, BufferedString);
+
+ if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {
+ Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;
+ } else {
+ Index = 0;
+ }
+
+ for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
+ BufferedString[Count] = StringPtr[Index];
+ }
+
+ PrintStringAt (Start + 1, Top + 3, BufferedString);
+ break;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);
+ } while (!SelectionComplete);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return Status;
+}
+
+EFI_STATUS
+ReadPassword (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN PromptForPassword,
+ IN EFI_TAG *Tag,
+ IN EFI_IFR_DATA_ARRAY *PageData,
+ IN BOOLEAN SecondEntry,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ OUT CHAR16 *StringPtr
+ )
+{
+ EFI_STATUS Status;
+ UINTN ScreenSize;
+ CHAR16 NullCharacter;
+ CHAR16 Space[2];
+ EFI_INPUT_KEY Key;
+ CHAR16 KeyPad[2];
+ UINTN Index;
+ UINTN Start;
+ UINTN Top;
+ CHAR16 *TempString;
+ CHAR16 *TempString2;
+ BOOLEAN Confirmation;
+ BOOLEAN ConfirmationComplete;
+ EFI_HII_CALLBACK_PACKET *Packet;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+ EFI_IFR_DATA_ENTRY *DataEntry;
+ UINTN WidthOfString;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ VariableDefinition = NULL;
+ NullCharacter = CHAR_NULL;
+ Space[0] = L' ';
+ Space[1] = CHAR_NULL;
+ Confirmation = FALSE;
+ ConfirmationComplete = FALSE;
+ Status = EFI_SUCCESS;
+ FormCallback = NULL;
+ Packet = NULL;
+
+ //
+ // Remember that dynamic pages in an environment where all pages are not
+ // dynamic require us to call back to the user to give them an opportunity
+ // to register fresh information in the HII database so that we can extract it.
+ //
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) MenuOption->Tags[0].CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ TempString = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
+ TempString2 = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
+
+ ASSERT (TempString);
+ ASSERT (TempString2);
+
+ if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ //
+ // Password requires a callback to determine if a password exists
+ //
+ DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1);
+ DataEntry->OpCode = EFI_IFR_PASSWORD_OP;
+ DataEntry->Length = 3;
+
+ ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
+
+ //
+ // The user is about to be prompted with a password field, Data = 0 (Return Status determines the type of prompt)
+ //
+ DataEntry->Data = (VOID *) (UINTN) (UINT8) (0 + SecondEntry * 2);
+ PageData->NvRamMap = VariableDefinition->NvRamMap;
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Tag->Key,
+ PageData,
+ &Packet
+ );
+ }
+ //
+ // If error on return, continue with the reading of a typed in password to verify user knows password
+ // If no error, there is no password set, so prompt for new password
+ // if the previous callback was to verify the user knew password, and user typed it correctly - should return no error
+ //
+ if (!EFI_ERROR (Status)) {
+ PromptForPassword = FALSE;
+
+ //
+ // Simulate this as the second entry into this routine for an interactive behavior
+ //
+ SecondEntry = TRUE;
+ } else if (Status == EFI_NOT_READY) {
+Error:
+ if (Packet != NULL) {
+ //
+ // Upon error, we will likely receive a string to print out
+ // Display error popup
+ //
+ WidthOfString = GetStringWidth (Packet->String);
+ ScreenSize = EFI_MAX(WidthOfString, GetStringWidth (gPressEnter)) / 2;
+ CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter);
+ FreePool (Packet);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+
+ Status = EFI_NOT_READY;
+ goto Done;
+ }
+ }
+
+ do {
+ //
+ // Display PopUp Screen
+ //
+ ScreenSize = GetStringWidth (gPromptForNewPassword) / 2;
+ if (GetStringWidth (gConfirmPassword) / 2 > ScreenSize) {
+ ScreenSize = GetStringWidth (gConfirmPassword) / 2;
+ }
+
+ Start = (DimensionsWidth - ScreenSize - 4) / 2 + gScreenDimensions.LeftColumn + 2;
+ Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+
+ if (!Confirmation) {
+ if (PromptForPassword) {
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForPassword, Space, &NullCharacter);
+ } else {
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForNewPassword, Space, &NullCharacter);
+ }
+ } else {
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmPassword, Space, &NullCharacter);
+ StringPtr[0] = CHAR_NULL;
+ }
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+ case CHAR_NULL:
+ if (Key.ScanCode == SCAN_ESC) {
+ return EFI_NOT_READY;
+ }
+
+ ConfirmationComplete = FALSE;
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ //
+ // User just typed a string in
+ //
+ DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1);
+ DataEntry->OpCode = EFI_IFR_PASSWORD_OP;
+
+ //
+ // If the user just typed in a password, Data = 1
+ // If the user just typed in a password to confirm the previous password, Data = 2
+ //
+ if (!Confirmation) {
+ DataEntry->Length = 3;
+ DataEntry->Data = (VOID *) (UINTN) (UINT8) (1 + SecondEntry * 2);
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Tag->Key,
+ PageData,
+ &Packet
+ );
+ }
+
+ DataEntry->Length = sizeof (EFI_IFR_DATA_ENTRY);
+ DataEntry->Data = (VOID *) TempString;
+ } else {
+ DataEntry->Length = 3;
+ DataEntry->Data = (VOID *) (UINTN) (UINT8) (2 + SecondEntry * 2);
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Tag->Key,
+ PageData,
+ &Packet
+ );
+ }
+
+ DataEntry->Length = sizeof (EFI_IFR_DATA_ENTRY);
+ DataEntry->Data = (VOID *) TempString2;
+ }
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Tag->Key,
+ PageData,
+ &Packet
+ );
+ }
+ //
+ // If this was the confirmation round of callbacks
+ // and an error comes back, display an error
+ //
+ if (Confirmation) {
+ if (EFI_ERROR (Status)) {
+ if (Packet->String == NULL) {
+ WidthOfString = GetStringWidth (gConfirmError);
+ ScreenSize = EFI_MAX (WidthOfString, GetStringWidth (gPressEnter)) / 2;
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter);
+ } else {
+ WidthOfString = GetStringWidth (Packet->String);
+ ScreenSize = EFI_MAX (WidthOfString, GetStringWidth (gPressEnter)) / 2;
+ CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter);
+ FreePool (Packet);
+ }
+
+ StringPtr[0] = CHAR_NULL;
+ do {
+ Status = WaitForKeyStroke (&Key);
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ Status = EFI_NOT_READY;
+ goto Done;
+ }
+ } while (1);
+ } else {
+ Status = EFI_NOT_READY;
+ goto Done;
+ }
+ } else {
+ //
+ // User typed a string in and it wasn't valid somehow from the callback
+ // For instance, callback may have said that some invalid characters were contained in the string
+ //
+ if (Status == EFI_NOT_READY) {
+ goto Error;
+ }
+
+ if (PromptForPassword && EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ }
+ }
+
+ if (Confirmation) {
+ //
+ // Compare tempstring and tempstring2, if the same, return with StringPtr success
+ // Otherwise, kick and error box, and return an error
+ //
+ if (StrCmp (TempString, TempString2) == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ } else {
+ WidthOfString = GetStringWidth (gConfirmError);
+ ScreenSize = EFI_MAX (WidthOfString, GetStringWidth (gPressEnter)) / 2;
+ CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter);
+ StringPtr[0] = CHAR_NULL;
+ do {
+ Status = WaitForKeyStroke (&Key);
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ } while (1);
+ }
+ }
+
+ if (PromptForPassword) {
+ //
+ // I was asked for a password, return it back in StringPtr
+ //
+ Status = EFI_SUCCESS;
+ goto Done;
+ } else {
+ //
+ // If the two passwords were not the same kick an error popup
+ //
+ Confirmation = TRUE;
+ ConfirmationComplete = TRUE;
+ break;
+ }
+
+ case CHAR_BACKSPACE:
+ if (StringPtr[0] != CHAR_NULL) {
+ if (!Confirmation) {
+ for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
+ TempString[Index] = StringPtr[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString[Index - 1] = CHAR_NULL;
+ StrCpy (StringPtr, TempString);
+ } else {
+ for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
+ TempString2[Index] = StringPtr[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString2[Index - 1] = CHAR_NULL;
+ StrCpy (StringPtr, TempString2);
+ }
+
+ ConfirmationComplete = FALSE;
+ } else {
+ ConfirmationComplete = FALSE;
+ }
+
+ //
+ // Must be a character we are interested in!
+ //
+ default:
+ if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ if (!Confirmation) {
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);
+ StrnCpy (TempString, &Key.UnicodeChar, 1);
+ } else {
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);
+ StrnCpy (TempString2, &Key.UnicodeChar, 1);
+ ConfirmationComplete = FALSE;
+ }
+ } else if ((GetStringWidth (StringPtr) / 2 <= (UINTN) (MenuOption->ThisTag->Maximum - 1) / 2) &&
+ (Key.UnicodeChar != CHAR_BACKSPACE)
+ ) {
+ KeyPad[0] = Key.UnicodeChar;
+ KeyPad[1] = CHAR_NULL;
+ if (!Confirmation) {
+ StrCat (StringPtr, KeyPad);
+ StrCat (TempString, KeyPad);
+ } else {
+ StrCat (StringPtr, KeyPad);
+ StrCat (TempString2, KeyPad);
+ }
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+ for (Index = 1; Index < ScreenSize; Index++) {
+ PrintCharAt (Start + Index, Top + 3, L' ');
+ }
+
+ gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ (DimensionsWidth - GetStringWidth (StringPtr) / 2) / 2 + gScreenDimensions.LeftColumn,
+ Top + 3
+ );
+ for (Index = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++) {
+ PrintChar (L'*');
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ break;
+ }
+ //
+ // end switch
+ //
+ } while (!ConfirmationComplete);
+
+ } while (1);
+
+Done:
+ FreePool (TempString);
+ FreePool (TempString2);
+ return Status;
+}
+
+VOID
+EncodePassword (
+ IN CHAR16 *Password,
+ IN UINT8 MaxSize
+ )
+{
+ UINTN Index;
+ UINTN Loop;
+ CHAR16 *Buffer;
+ CHAR16 *Key;
+
+ Key = (CHAR16 *) L"MAR10648567";
+ Buffer = AllocateZeroPool (MaxSize);
+
+ ASSERT (Buffer);
+
+ for (Index = 0; Key[Index] != 0; Index++) {
+ for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
+ Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
+ }
+ }
+
+ CopyMem (Password, Buffer, MaxSize);
+
+ FreePool (Buffer);
+ return ;
+}
+
+EFI_STATUS
+GetNumericInput (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN BOOLEAN ManualInput,
+ IN EFI_TAG *Tag,
+ IN UINTN NumericType,
+ OUT UINT16 *Value
+ )
+/*++
+
+Routine Description:
+
+ This routine reads a numeric value from the user input.
+
+Arguments:
+
+ MenuOption - Pointer to the current input menu.
+
+ FileFormTagsHead - Pointer to the root of formset.
+
+ ManualInput - If the input is manual or not.
+
+ Tag - Pointer to all the attributes and values associated with a tag.
+
+ Value - Pointer to the numeric value that is going to be read.
+
+Returns:
+
+ EFI_SUCCESS - If numerical input is read successfully
+ EFI_DEVICE_ERROR - If operation fails
+
+--*/
+{
+ EFI_INPUT_KEY Key;
+ BOOLEAN SelectionComplete;
+ UINTN Column;
+ UINTN Row;
+ CHAR16 FormattedNumber[6];
+ UINTN PreviousNumber[6];
+ INTN Number;
+ UINTN Count;
+ UINT16 BackupValue;
+ STRING_REF PopUp;
+ CHAR16 NullCharacter;
+ CHAR16 *StringPtr;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ UINTN Loop;
+
+ NullCharacter = CHAR_NULL;
+ StringPtr = NULL;
+ Column = MenuOption->OptCol;
+ Row = MenuOption->Row;
+ Number = 0;
+ PreviousNumber[0] = 0;
+ Count = 0;
+ SelectionComplete = FALSE;
+ BackupValue = Tag->Value;
+ FileFormTags = FileFormTagsHead;
+
+ if (ManualInput) {
+ PrintAt (Column, Row, (CHAR16 *) L"[ ]");
+ Column++;
+ if (Tag->Operand != EFI_IFR_TIME_OP) {
+ *Value = BackupValue;
+ }
+ }
+ //
+ // First time we enter this handler, we need to check to see if
+ // we were passed an increment or decrement directive
+ //
+ do {
+ Key.UnicodeChar = CHAR_NULL;
+ if (gDirection != 0) {
+ Key.ScanCode = gDirection;
+ gDirection = 0;
+ goto TheKey2;
+ }
+
+ WaitForKeyStroke (&Key);
+
+TheKey2:
+ switch (Key.UnicodeChar) {
+ case '+':
+ case '-':
+ if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
+ Key.UnicodeChar = CHAR_NULL;
+ if (Key.UnicodeChar == '+') {
+ Key.ScanCode = SCAN_RIGHT;
+ } else {
+ Key.ScanCode = SCAN_LEFT;
+ }
+
+ goto TheKey2;
+ }
+ break;
+
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_LEFT:
+ case SCAN_RIGHT:
+ if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
+ //
+ // By setting this value, we will return back to the caller.
+ // We need to do this since an auto-refresh will destroy the adjustment
+ // based on what the real-time-clock is showing. So we always commit
+ // upon changing the value.
+ //
+ gDirection = SCAN_DOWN;
+ }
+
+ if (!ManualInput) {
+ Tag->Value = *Value;
+ if (Key.ScanCode == SCAN_LEFT) {
+ Number = *Value - Tag->Step;
+ if (Number < Tag->Minimum) {
+ Number = Tag->Minimum;
+ }
+ } else if (Key.ScanCode == SCAN_RIGHT) {
+ Number = *Value + Tag->Step;
+ if (Number > Tag->Maximum) {
+ Number = Tag->Maximum;
+ }
+ }
+
+ Tag->Value = (UINT16) Number;
+ *Value = (UINT16) Number;
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Number,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
+ for (Loop = 0; Loop < (UINTN) ((Number >= 8) ? 4 : 2); Loop++) {
+ PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, (CHAR16 *) L" ");
+ }
+ } else {
+ for (Loop = 0; Loop < gOptionBlockWidth; Loop++) {
+ PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, (CHAR16 *) L" ");
+ }
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+
+ if ((MenuOption->Col + gPromptBlockWidth + 1) == MenuOption->OptCol) {
+ PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
+ Column = MenuOption->OptCol + 1;
+ }
+ //
+ // If Number looks like "3", convert it to "03/"
+ //
+ if (Number == 4 && (NumericType == DATE_NUMERIC)) {
+ FormattedNumber[3] = FormattedNumber[1];
+ FormattedNumber[2] = DATE_SEPARATOR;
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 8;
+ }
+ //
+ // If Number looks like "13", convert it to "13/"
+ //
+ if (Number == 6 && (NumericType == DATE_NUMERIC)) {
+ FormattedNumber[3] = FormattedNumber[2];
+ FormattedNumber[2] = DATE_SEPARATOR;
+ Number = 8;
+ }
+
+ if (Number == 4 &&
+ (NumericType == TIME_NUMERIC) &&
+ (MenuOption->Col + gPromptBlockWidth + 8) != MenuOption->OptCol
+ ) {
+ FormattedNumber[3] = FormattedNumber[1];
+ FormattedNumber[2] = TIME_SEPARATOR;
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 8;
+ }
+
+ if (Number == 4 &&
+ (NumericType == TIME_NUMERIC) &&
+ (MenuOption->Col + gPromptBlockWidth + 8) == MenuOption->OptCol
+ ) {
+ FormattedNumber[3] = FormattedNumber[1];
+ FormattedNumber[2] = RIGHT_NUMERIC_DELIMITER;
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 8;
+ }
+
+ PrintStringAt (Column, Row, FormattedNumber);
+ if (Number == 10 && (NumericType == DATE_NUMERIC)) {
+ PrintChar (RIGHT_NUMERIC_DELIMITER);
+ }
+
+ if (NumericType == REGULAR_NUMERIC) {
+ PrintChar (RIGHT_NUMERIC_DELIMITER);
+ }
+ }
+ break;
+
+ case SCAN_UP:
+ case SCAN_DOWN:
+ goto EnterCarriageReturn;
+
+ case SCAN_ESC:
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+EnterCarriageReturn:
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // Check to see if the Value is something reasonable against consistency limitations.
+ // If not, let's kick the error specified.
+ //
+ //
+ // This gives us visibility to the FileFormTags->NvRamMap to check things
+ // ActiveIfr is a global maintained by the menuing code to ensure that we
+ // are pointing to the correct formset's file data.
+ //
+ for (Count = 0; Count < gActiveIfr; Count++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
+
+ CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth);
+
+ //
+ // Data associated with a NULL device (in the fake NV storage)
+ //
+ if (Tag->StorageWidth == (UINT16) 0) {
+ CopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2);
+ }
+ //
+ // If a late check is required save off the information. This is used when consistency checks
+ // are required, but certain values might be bound by an impossible consistency check such as
+ // if two questions are bound by consistency checks and each only has two possible choices, there
+ // would be no way for a user to switch the values. Thus we require late checking.
+ //
+ if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
+ CopyMem (&Tag->OldValue, &BackupValue, Tag->StorageWidth);
+ } else {
+ //
+ // In theory, passing the value and the Id are sufficient to determine what needs
+ // to be done. The Id is the key to look for the entry needed in the Inconsistency
+ // database. That will yields operand and ID data - and since the ID's correspond
+ // to the NV storage, we can determine the values for other IDs there.
+ //
+ if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
+ if (PopUp == 0x0000) {
+ SelectionComplete = TRUE;
+ break;
+ }
+
+ StringPtr = GetToken (PopUp, MenuOption->Handle);
+
+ CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);
+
+ do {
+ WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+
+ case CHAR_CARRIAGE_RETURN:
+ SelectionComplete = TRUE;
+ FreePool (StringPtr);
+ break;
+
+ default:
+ break;
+ }
+ } while (!SelectionComplete);
+
+ Tag->Value = BackupValue;
+ *Value = BackupValue;
+
+ CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth);
+
+ //
+ // Data associated with a NULL device (in the fake NV storage)
+ //
+ if (Tag->StorageWidth == (UINT16) 0) {
+ CopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2);
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+ break;
+
+ case CHAR_BACKSPACE:
+ if (ManualInput) {
+ if (Count == 0) {
+ break;
+ }
+ //
+ // Remove a character
+ //
+ Number = PreviousNumber[Count - 1];
+ *Value = (UINT16) Number;
+ UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE);
+ Count--;
+ Column--;
+ PrintAt (Column, Row, (CHAR16 *) L" ");
+ }
+ break;
+
+ default:
+ if (ManualInput) {
+ if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
+ UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE);
+ break;
+ }
+ //
+ // If Count 0-4 is complete, there is no way more is valid
+ //
+ if (Count > 4) {
+ break;
+ }
+ //
+ // Someone typed something valid!
+ //
+ if (Count != 0) {
+ Number = Number * 10 + (Key.UnicodeChar - L'0');
+ } else {
+ Number = Key.UnicodeChar - L'0';
+ }
+
+ if (Number > Tag->Maximum) {
+ UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE);
+ Number = PreviousNumber[Count];
+ break;
+ } else {
+ UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE);
+ }
+
+ Count++;
+
+ PreviousNumber[Count] = Number;
+ *Value = (UINT16) Number;
+ Tag->Value = (UINT16) Number;
+
+ PrintCharAt (Column, Row, Key.UnicodeChar);
+ Column++;
+ }
+ break;
+ }
+ } while (!SelectionComplete);
+ return EFI_SUCCESS;
+}
+//
+// Notice that this is at least needed for the ordered list manipulation.
+// Left/Right doesn't make sense for this op-code
+//
+EFI_STATUS
+GetSelectionInputPopUp (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_TAG *Tag,
+ IN UINTN ValueCount,
+ OUT UINT16 *Value,
+ OUT UINT16 *KeyValue
+ )
+{
+ EFI_INPUT_KEY Key;
+ UINTN Index;
+ UINTN TempIndex;
+ CHAR16 *StringPtr;
+ CHAR16 *TempStringPtr;
+ UINT16 Token;
+ UINTN Index2;
+ UINTN TopOptionIndex;
+ UINTN HighlightPosition;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ UINT16 TempValue;
+ UINTN Count;
+ UINTN PopUpMenuLines;
+ UINTN MenuLinesInView;
+ UINTN PopUpWidth;
+ CHAR16 Character;
+ BOOLEAN FirstOptionFoundFlag;
+ INT32 SavedAttribute;
+ EFI_TAG TagBackup;
+ UINT8 *ValueArray;
+ UINT8 *ValueArrayBackup;
+ UINT8 ValueBackup;
+ BOOLEAN Initialized;
+ BOOLEAN KeyInitialized;
+ BOOLEAN ShowDownArrow;
+ BOOLEAN ShowUpArrow;
+ UINTN DimensionsWidth;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+
+ TempValue = 0;
+ TempIndex = 0;
+ ValueArray = (UINT8 *) Value;
+ ValueArrayBackup = NULL;
+ Initialized = FALSE;
+ KeyInitialized = FALSE;
+ ShowDownArrow = FALSE;
+ ShowUpArrow = FALSE;
+
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ ValueArrayBackup = AllocateZeroPool (Tag->StorageWidth);
+ ASSERT (ValueArrayBackup != NULL);
+ CopyMem (ValueArrayBackup, ValueArray, ValueCount);
+ TempValue = *(UINT8 *) (ValueArray);
+ if (ValueArray[0] != 0x00) {
+ Initialized = TRUE;
+ }
+
+ for (Index = 0; ValueArray[Index] != 0x00; Index++)
+ ;
+ ValueCount = Index;
+ } else {
+ TempValue = *Value;
+ }
+
+ Count = 0;
+ PopUpWidth = 0;
+
+ FirstOptionFoundFlag = FALSE;
+
+ StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
+ ASSERT (StringPtr);
+
+ //
+ // Initialization for "One of" pop-up menu
+ //
+ //
+ // Get the number of one of options present and its size
+ //
+ for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP &&
+ !MenuOption->Tags[Index].Suppress) {
+ if (!FirstOptionFoundFlag) {
+ FirstOptionFoundFlag = TRUE;
+ }
+
+ Count++;
+ Token = MenuOption->Tags[Index].Text;
+
+ //
+ // If this is an ordered list that is initialized
+ //
+ if (Initialized) {
+ for (ValueBackup = (UINT8) MenuOption->TagIndex;
+ MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_OP;
+ ValueBackup++
+ ) {
+ if (MenuOption->Tags[ValueBackup].Value == ((UINT8 *) ValueArrayBackup)[Index - MenuOption->TagIndex - 1]) {
+ StringPtr = GetToken (MenuOption->Tags[ValueBackup].Text, MenuOption->Handle);
+ break;
+ }
+ }
+ } else {
+ StringPtr = GetToken (Token, MenuOption->Handle);
+ }
+
+ if (StrLen (StringPtr) > PopUpWidth) {
+ PopUpWidth = StrLen (StringPtr);
+ }
+
+ FreePool (StringPtr);
+ }
+ }
+ //
+ // Perform popup menu initialization.
+ //
+ PopUpMenuLines = Count;
+ PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
+
+ SavedAttribute = gST->ConOut->Mode->Attribute;
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+ if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
+ PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
+ }
+
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
+ End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
+ Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
+ Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT;
+
+ MenuLinesInView = Bottom - Top - 1;
+ if (MenuLinesInView >= PopUpMenuLines) {
+ Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;
+ Bottom = Top + PopUpMenuLines + 1;
+ } else {
+ TempValue = MenuOption->Tags[MenuOption->TagIndex + 1].Value;
+ ShowDownArrow = TRUE;
+ }
+
+ TopOptionIndex = 1;
+ HighlightPosition = 0;
+ do {
+ if (Initialized) {
+ for (Index = MenuOption->TagIndex, Index2 = 0; Index2 < ValueCount; Index++, Index2++) {
+ //
+ // Set the value for the item we are looking for
+ //
+ Count = ValueArrayBackup[Index2];
+
+ //
+ // If we hit the end of the Array, we are complete
+ //
+ if (Count == 0) {
+ break;
+ }
+
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ for (ValueBackup = (UINT8) MenuOption->TagIndex;
+ MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_ONE_OF_OP;
+ ValueBackup++
+ ) {
+ //
+ // We just found what we are looking for
+ //
+ if (MenuOption->Tags[ValueBackup].Value == Count) {
+ //
+ // As long as the two indexes aren't the same, we have
+ // two different op-codes we need to swap internally
+ //
+ if (Index != ValueBackup) {
+ //
+ // Backup destination tag, then copy source to destination, then copy backup to source location
+ //
+ CopyMem (&TagBackup, &MenuOption->Tags[Index], sizeof (EFI_TAG));
+ CopyMem (&MenuOption->Tags[Index], &MenuOption->Tags[ValueBackup], sizeof (EFI_TAG));
+ CopyMem (&MenuOption->Tags[ValueBackup], &TagBackup, sizeof (EFI_TAG));
+ } else {
+ //
+ // If the indexes are the same, then the op-code is where he belongs
+ //
+ }
+ }
+ }
+ } else {
+ //
+ // Since this wasn't an option op-code (likely the ordered list op-code) decerement Index2
+ //
+ Index2--;
+ }
+ }
+ }
+ //
+ // Clear that portion of the screen
+ //
+ ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
+
+ //
+ // Draw "One of" pop-up menu
+ //
+ Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ for (Index = Start; Index + 2 < End; Index++) {
+ if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
+ Character = (CHAR16) GEOMETRICSHAPE_UP_TRIANGLE;
+ } else {
+ Character = (CHAR16) BOXDRAW_HORIZONTAL;
+ }
+
+ PrintChar (Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = (CHAR16) BOXDRAW_VERTICAL;
+ for (Index = Top + 1; Index < Bottom; Index++) {
+ PrintCharAt (Start, Index, Character);
+ PrintCharAt (End - 1, Index, Character);
+ }
+ //
+ // Display the One of options
+ //
+ Index2 = Top + 1;
+ for (Index = MenuOption->TagIndex + TopOptionIndex;
+ (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP) && (Index2 < Bottom);
+ Index++
+ ) {
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ Token = MenuOption->Tags[Index].Text;
+ if (Initialized) {
+ for (ValueBackup = (UINT8) MenuOption->TagIndex;
+ MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_ONE_OF_OP;
+ ValueBackup++
+ ) {
+ if (MenuOption->Tags[ValueBackup].Value == ((UINT8 *) ValueArrayBackup)[Index - MenuOption->TagIndex - 1]) {
+ StringPtr = GetToken (MenuOption->Tags[ValueBackup].Text, MenuOption->Handle);
+ break;
+ }
+ }
+ } else {
+ ValueBackup = (UINT8) Index;
+ StringPtr = GetToken (Token, MenuOption->Handle);
+ }
+ //
+ // If the string occupies multiple lines, truncate it to fit in one line,
+ // and append a "..." for indication.
+ //
+ if (StrLen (StringPtr) > (PopUpWidth - 1)) {
+ TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
+ ASSERT (TempStringPtr != NULL);
+ CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
+ FreePool (StringPtr);
+ StringPtr = TempStringPtr;
+ StrCat (StringPtr, (CHAR16 *) L"...");
+ }
+ //
+ // Code to display the text should go here. Follwed by the [*]
+ //
+ if (MenuOption->Tags[ValueBackup].Suppress == TRUE) {
+ //
+ // Don't show the one, so decrease the Index2 for balance
+ //
+ Index2--;
+ } else if (MenuOption->Tags[ValueBackup].GrayOut == TRUE) {
+ //
+ // Gray Out the one
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | POPUP_BACKGROUND);
+ PrintStringAt (Start + 2, Index2, StringPtr);
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ } else if (MenuOption->Tags[ValueBackup].Value == TempValue) {
+ //
+ // Highlight the selected one
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
+ PrintStringAt (Start + 2, Index2, StringPtr);
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ HighlightPosition = Index2;
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ PrintStringAt (Start + 2, Index2, StringPtr);
+ }
+
+ FreePool (StringPtr);
+ Index2 = Index2 + 1;
+ }
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom, Character);
+ for (Index = Start; Index + 2 < End; Index++) {
+ if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
+ Character = (CHAR16) GEOMETRICSHAPE_DOWN_TRIANGLE;
+ } else {
+ Character = (CHAR16) BOXDRAW_HORIZONTAL;
+ }
+
+ PrintChar (Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+ //
+ // Get User selection and change TempValue if necessary
+ //
+ //
+ // Stop: One of pop-up menu
+ //
+ Key.UnicodeChar = CHAR_NULL;
+ if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
+ Key.ScanCode = gDirection;
+ gDirection = 0;
+ goto TheKey;
+ }
+
+ if (!KeyInitialized) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_ONE_OF_OP) {
+ *KeyValue = MenuOption->Tags[MenuOption->TagIndex + 1].Key;
+ } else {
+ *KeyValue = MenuOption->ThisTag->Key;
+ }
+
+ KeyInitialized = TRUE;
+ }
+
+ WaitForKeyStroke (&Key);
+
+TheKey:
+ switch (Key.UnicodeChar) {
+ case '+':
+ case '-':
+ //
+ // If an ordered list op-code, we will allow for a popup of +/- keys
+ // to create an ordered list of items
+ //
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ if (Key.UnicodeChar == '+') {
+ if ((TopOptionIndex > 1) && (HighlightPosition == (Top + 1))) {
+ //
+ // Highlight reaches the top of the popup window, scroll one menu item.
+ //
+ TopOptionIndex--;
+ ShowDownArrow = TRUE;
+ }
+
+ if (TopOptionIndex == 1) {
+ ShowUpArrow = FALSE;
+ }
+ } else {
+ if (((TopOptionIndex + MenuLinesInView) <= PopUpMenuLines) && (HighlightPosition == (Bottom - 1))) {
+ //
+ // Highlight reaches the bottom of the popup window, scroll one menu item.
+ //
+ TopOptionIndex++;
+ ShowUpArrow = TRUE;
+ }
+
+ if ((TopOptionIndex + MenuLinesInView) == (PopUpMenuLines + 1)) {
+ ShowDownArrow = FALSE;
+ }
+ }
+
+ for (Index = MenuOption->TagIndex + TopOptionIndex;
+ MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP;
+ Index++
+ ) {
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ORDERED_LIST_OP) {
+ continue;
+ }
+
+ if (Key.UnicodeChar == '+') {
+ TempIndex = Index - 1;
+ } else {
+ TempIndex = Index + 1;
+ }
+ //
+ // Is this the current tag we are on?
+ //
+ if (MenuOption->Tags[Index].Value == TempValue) {
+ //
+ // Is this prior tag a valid choice? If not, bail out
+ //
+ if (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ //
+ // Copy the destination tag to the local variable
+ //
+ CopyMem (&TagBackup, &MenuOption->Tags[TempIndex], sizeof (EFI_TAG));
+ //
+ // Copy the current tag to the tag location before us
+ //
+ CopyMem (&MenuOption->Tags[TempIndex], &MenuOption->Tags[Index], sizeof (EFI_TAG));
+ //
+ // Copy the backed up tag to the current location
+ //
+ CopyMem (&MenuOption->Tags[Index], &TagBackup, sizeof (EFI_TAG));
+
+ //
+ // Adjust the array of values
+ //
+ for (Index = 0; Index < ValueCount; Index++) {
+ if (ValueArrayBackup[Index] == (UINT8) TempValue) {
+ if (Key.UnicodeChar == '+') {
+ if (Index == 0) {
+ //
+ // It is the top of the array already
+ //
+ break;
+ }
+
+ TempIndex = Index - 1;
+ } else {
+ if ((Index + 1) == ValueCount) {
+ //
+ // It is the bottom of the array already
+ //
+ break;
+ }
+
+ TempIndex = Index + 1;
+ }
+
+ ValueBackup = ValueArrayBackup[TempIndex];
+ ValueArrayBackup[TempIndex] = ValueArrayBackup[Index];
+ ValueArrayBackup[Index] = ValueBackup;
+ Initialized = TRUE;
+ break;
+ }
+ }
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_UP:
+ case SCAN_DOWN:
+ if (Key.ScanCode == SCAN_UP) {
+ if ((TopOptionIndex > 1) && (HighlightPosition == (Top + 1))) {
+ //
+ // Highlight reaches the top of the popup window, scroll one menu item.
+ //
+ TopOptionIndex--;
+ ShowDownArrow = TRUE;
+ }
+
+ if (TopOptionIndex == 1) {
+ ShowUpArrow = FALSE;
+ }
+ } else {
+ if (((TopOptionIndex + MenuLinesInView) <= PopUpMenuLines) && (HighlightPosition == (Bottom - 1))) {
+ //
+ // Highlight reaches the bottom of the popup window, scroll one menu item.
+ //
+ TopOptionIndex++;
+ ShowUpArrow = TRUE;
+ }
+
+ if ((TopOptionIndex + MenuLinesInView) == (PopUpMenuLines + 1)) {
+ ShowDownArrow = FALSE;
+ }
+ }
+
+ for (Index = MenuOption->TagIndex + TopOptionIndex;
+ MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP;
+ Index++
+ ) {
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ if (Initialized) {
+ for (Index = 0; (ValueArrayBackup[Index] != TempValue) && (Index < ValueCount); Index++)
+ ;
+
+ //
+ // Did we hit the end of the array? Either get the first TempValue or the next one
+ //
+ if (Key.ScanCode == SCAN_UP) {
+ if (Index == 0) {
+ TempValue = ValueArrayBackup[0];
+ } else {
+ TempValue = ValueArrayBackup[Index - 1];
+ }
+ } else {
+ if ((Index + 1) == ValueCount) {
+ TempValue = ValueArrayBackup[Index];
+ } else {
+ TempValue = ValueArrayBackup[Index + 1];
+ }
+ }
+ break;
+ } else {
+ if (Key.ScanCode == SCAN_UP) {
+ TempIndex = Index - 1;
+
+ //
+ // Keep going until meets meaningful tag.
+ //
+ while ((MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OPTION_OP &&
+ MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OP &&
+ MenuOption->Tags[TempIndex].Operand != EFI_IFR_END_ONE_OF_OP)
+ ||
+ (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP &&
+ (MenuOption->Tags[TempIndex].Suppress || MenuOption->Tags[TempIndex].GrayOut))) {
+ TempIndex--;
+ }
+ } else {
+ TempIndex = Index + 1;
+
+ //
+ // Keep going until meets meaningful tag.
+ //
+ while ((MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OPTION_OP &&
+ MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OP &&
+ MenuOption->Tags[TempIndex].Operand != EFI_IFR_END_ONE_OF_OP)
+ ||
+ (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP &&
+ (MenuOption->Tags[TempIndex].Suppress || MenuOption->Tags[TempIndex].GrayOut))) {
+ TempIndex++;
+ }
+ }
+ //
+ // The option value is the same as what is stored in NV store. This is where we take action
+ //
+ if (MenuOption->Tags[Index].Value == TempValue) {
+ //
+ // Only if the previous op-code is an option can we select it, otherwise we are at the left-most option
+ //
+ if (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ TempValue = MenuOption->Tags[TempIndex].Value;
+ *KeyValue = MenuOption->Tags[TempIndex].Key;
+ } else {
+ TempValue = MenuOption->Tags[Index].Value;
+ *KeyValue = MenuOption->Tags[Index].Key;
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case SCAN_ESC:
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ if (ValueArrayBackup != NULL) {
+ FreePool (ValueArrayBackup);
+ }
+
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // return the current selection
+ //
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ CopyMem (ValueArray, ValueArrayBackup, ValueCount);
+ FreePool (ValueArrayBackup);
+ } else {
+ *Value = TempValue;
+ }
+
+ goto Done;
+
+ default:
+ break;
+ }
+ } while (1);
+
+Done:
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ do {
+ UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
+ } while (EFI_ERROR(Status));
+
+ return Status;
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Presentation.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Presentation.c
new file mode 100644
index 0000000000..be5ba57ef7
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -0,0 +1,1490 @@
+/*++
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ Presentation.c
+
+Abstract:
+
+ Some presentation routines.
+
+Revision History:
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+#include "Colors.h"
+
+VOID
+ClearLines (
+ UINTN LeftColumn,
+ UINTN RightColumn,
+ UINTN TopRow,
+ UINTN BottomRow,
+ UINTN TextAttribute
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Row;
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Set foreground and background as defined
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
+
+ //
+ // Much faster to buffer the long string instead of print it a character at a time
+ //
+ SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
+
+ //
+ // Clear the desired area with the appropriate foreground/background
+ //
+ for (Row = TopRow; Row <= BottomRow; Row++) {
+ PrintStringAt (LeftColumn, Row, Buffer);
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
+
+ FreePool (Buffer);
+ return ;
+}
+
+VOID
+NewStrCat (
+ CHAR16 *Destination,
+ CHAR16 *Source
+ )
+{
+ UINTN Length;
+
+ for (Length = 0; Destination[Length] != 0; Length++)
+ ;
+
+ //
+ // We now have the length of the original string
+ // We can safely assume for now that we are concatenating a narrow value to this string.
+ // For instance, the string is "XYZ" and cat'ing ">"
+ // If this assumption changes, we need to make this routine a bit more complex
+ //
+ Destination[Length] = (CHAR16) NARROW_CHAR;
+ Length++;
+
+ StrCpy (Destination + Length, Source);
+}
+
+UINTN
+GetStringWidth (
+ CHAR16 *String
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN IncrementValue;
+
+ Index = 0;
+ Count = 0;
+ IncrementValue = 1;
+
+ do {
+ //
+ // Advance to the null-terminator or to the first width directive
+ //
+ for (;
+ (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
+ Index++, Count = Count + IncrementValue
+ )
+ ;
+
+ //
+ // We hit the null-terminator, we now have a count
+ //
+ if (String[Index] == 0) {
+ break;
+ }
+ //
+ // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
+ // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
+ //
+ if (String[Index] == NARROW_CHAR) {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 1;
+ } else {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 2;
+ }
+ } while (String[Index] != 0);
+
+ //
+ // Increment by one to include the null-terminator in the size
+ //
+ Count++;
+
+ return Count * sizeof (CHAR16);
+}
+
+VOID
+DisplayPageFrame (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT8 Line;
+ UINT8 Alignment;
+ CHAR16 Character;
+ CHAR16 *Buffer;
+ CHAR16 *StrFrontPageBanner;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ UINTN Row;
+
+ ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
+ ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer != NULL);
+
+ Character = (CHAR16) BOXDRAW_HORIZONTAL;
+
+ for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
+ Buffer[Index] = Character;
+ }
+
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ //
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+ //
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.TopRow,
+ FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
+ BANNER_TEXT | BANNER_BACKGROUND
+ );
+ //
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+ //
+ for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
+ //
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
+ //
+ for (Alignment = (UINT8) LocalScreen.LeftColumn;
+ Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
+ Alignment++
+ ) {
+ if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
+ StrFrontPageBanner = GetToken (
+ BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
+ FrontPageHandle
+ );
+ } else {
+ continue;
+ }
+
+ switch (Alignment - LocalScreen.LeftColumn) {
+ case 0:
+ //
+ // Handle left column
+ //
+ PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
+ break;
+
+ case 1:
+ //
+ // Handle center column
+ //
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+
+ case 2:
+ //
+ // Handle right column
+ //
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+ }
+
+ FreePool (StrFrontPageBanner);
+ }
+ }
+ }
+
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
+ KEYHELP_TEXT | KEYHELP_BACKGROUND
+ );
+
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.TopRow,
+ LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
+ TITLE_TEXT | TITLE_BACKGROUND
+ );
+ //
+ // Print Top border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
+
+ PrintChar (Character);
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+
+ Character = (CHAR16) BOXDRAW_VERTICAL;
+ for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ //
+ // Print Bottom border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
+
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = (CHAR16) BOXDRAW_VERTICAL;
+ for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
+ Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
+ Row++
+ ) {
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+ }
+ }
+
+ FreePool (Buffer);
+
+}
+
+/*
++------------------------------------------------------------------------------+
+?F2=Previous Page Setup Page ?
++------------------------------------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
++------------------------------------------------------------------------------+
+?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
++------------------------------------------------------------------------------+
+*/
+STATIC
+UI_MENU_OPTION *
+DisplayForm (
+ OUT UI_MENU_OPTION *Selection,
+ IN UINT16 FormHandle,
+ IN UINT16 TitleToken,
+ IN EFI_FORM_TAGS FormTags,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+{
+ CHAR16 *StringPtr;
+ UINTN Index;
+ UINTN Count;
+ UINT16 MenuItemCount;
+ EFI_HII_HANDLE Handle;
+ UINT16 FormId;
+ STRING_REF String;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ BOOLEAN SuppressIf;
+ BOOLEAN Suppress;
+ BOOLEAN GrayOut;
+ BOOLEAN Conditional;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ UINT16 Width;
+ UINTN ArrayEntry;
+ CHAR16 *OutputString;
+
+ Handle = Selection->Handle;
+ FormId = 0;
+ String = 0;
+ MenuItemCount = 0;
+ ArrayEntry = 0;
+ OutputString = NULL;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need
+ //
+ if (Selection->Previous) {
+ Selection->Previous = FALSE;
+ } else {
+ UiFreeMenu ();
+ UiInitMenu ();
+ }
+
+ StringPtr = GetToken (TitleToken, Handle);
+
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
+ PrintStringAt (
+ (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
+ LocalScreen.TopRow + 1,
+ StringPtr
+ );
+ }
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ //
+ // Display the infrastructure strings
+ //
+ if (!IsListEmpty (&gMenuList)) {
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
+ }
+
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ LocalScreen.BottomRow - 4,
+ gFunctionNineString
+ );
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+ LocalScreen.BottomRow - 4,
+ gFunctionTenString
+ );
+ PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ LocalScreen.BottomRow - 3,
+ gEscapeString
+ );
+ }
+ //
+ // Remove Buffer allocated for StringPtr after it has been used.
+ //
+ FreePool (StringPtr);
+
+ for (Index = 0; FormTags.Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
+ GrayOut = FALSE;
+ Suppress = FALSE;
+ SuppressIf = FALSE;
+ Conditional = FALSE;
+ FileFormTags = FileFormTagsHead;
+
+ if (FormTags.Tags[Index].Operand == EFI_IFR_FORM_OP) {
+ FormId = FormTags.Tags[Index].Id;
+ }
+ //
+ // This gives us visibility to the FileFormTags->NvRamMap to check things
+ // ActiveIfr is a global maintained by the menuing code to ensure that we
+ // are pointing to the correct formset's file data.
+ //
+ for (Count = 0; Count < gActiveIfr; Count++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+ //
+ // GrayoutIf [SuppressIf]
+ // <BOOLEANS>
+ // OpCode(s)
+ // EndIf
+ //
+ // SuppressIf [GrayoutIf]
+ // <BOOLEANS>
+ // OpCode(s)
+ // EndIf
+ //
+ Count = 0;
+
+ do {
+ switch (FormTags.Tags[Index].Operand) {
+ case EFI_IFR_SUPPRESS_IF_OP:
+ SuppressIf = TRUE;
+
+ case EFI_IFR_GRAYOUT_IF_OP:
+
+ Conditional = TRUE;
+
+ //
+ // Advance to the next op-code
+ //
+ Index++;
+
+ //
+ // We are now pointing to the beginning of the consistency checking. Let's fast forward
+ // through the AND/OR/NOT data to come up with some meaningful ID data.
+ //
+ for (;
+ FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP;
+ Index++
+ )
+ ;
+
+ //
+ // We need to walk through the consistency checks until we hit the end of the consistency
+ // FALSE means evaluate this single expression
+ // The ConsistencyId refers to which expression in the Consistency database to use
+ //
+ if (SuppressIf) {
+ Suppress = ValueIsNotValid (
+ FALSE,
+ FormTags.Tags[Index].ConsistencyId,
+ &FormTags.Tags[Index],
+ FileFormTags,
+ &String
+ );
+ SuppressIf = FALSE;
+ } else {
+ GrayOut = ValueIsNotValid (
+ FALSE,
+ FormTags.Tags[Index].ConsistencyId,
+ &FormTags.Tags[Index],
+ FileFormTags,
+ &String
+ );
+ }
+ //
+ // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected)
+ //
+ for (;
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_VAL_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_VAR_VAL_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_ID_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_LIST_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_TRUE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_FALSE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_LABEL_OP;
+ Index++
+ )
+ ;
+ break;
+
+ default:
+ goto GetOut;
+ }
+ //
+ // Do this two times (at most will see a suppress and grayout combination
+ //
+ Count++;
+ } while (Count < 2);
+
+GetOut:
+ do {
+ if (GrayOut) {
+ FormTags.Tags[Index].GrayOut = TRUE;
+ } else {
+ FormTags.Tags[Index].GrayOut = FALSE;
+ }
+ if (Suppress && FormTags.Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ //
+ // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly.
+ //
+ FormTags.Tags[Index].Suppress = TRUE;
+ } else {
+ FormTags.Tags[Index].Suppress = FALSE;
+ }
+
+ if ((
+ FormTags.Tags[Index].NumberOfLines > 0 ||
+ FormTags.Tags[Index].Operand == EFI_IFR_DATE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_TIME_OP
+ ) &&
+ !Suppress
+ ) {
+
+ StringPtr = GetToken (FormTags.Tags[Index].Text, Handle);
+
+ Width = GetWidth (&FormTags.Tags[Index], Handle);
+
+ //
+ // This data can be retrieved over and over again. Therefore, reset to original values
+ // before processing otherwise things will start growing linearly
+ //
+ if (FormTags.Tags[Index].NumberOfLines > 1) {
+ FormTags.Tags[Index].NumberOfLines = 1;
+ }
+
+ for (Count = 0; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&StringPtr[ArrayEntry])) {
+ FormTags.Tags[Index].NumberOfLines++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ ArrayEntry = 0;
+
+ //
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
+ // it in UiFreeMenu.
+ //
+ UiAddSubMenuOption (StringPtr, Handle, FormTags.Tags, Index, FormId, MenuItemCount);
+ MenuItemCount++;
+ }
+ //
+ // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if
+ //
+ Index++;
+ } while (FormTags.Tags[Index].Operand != EFI_IFR_END_IF_OP && Conditional);
+
+ //
+ // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic
+ //
+ Index--;
+ }
+
+ Selection = UiDisplayMenu (TRUE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
+
+ return Selection;
+}
+
+VOID
+InitializeBrowserStrings (
+ VOID
+ )
+{
+ gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
+ gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
+ gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
+ gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
+ gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
+ gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
+ gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
+ gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
+ gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
+ gNumericInput = GetToken (STRING_TOKEN (NUMERIC_INPUT), gHiiHandle);
+ gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
+ gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
+ gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
+ gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
+ gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
+ gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
+ gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
+ gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
+ gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
+ gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
+ gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
+ gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
+ return ;
+}
+
+VOID
+UpdateKeyHelp (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Selected
+ )
+/*++
+Routine Description:
+ Update key's help imformation
+
+Arguments:
+ Selection C The form that current display
+ Selected C Whether or not a tag be selected
+
+Returns:
+ None
+--*/
+{
+ UINTN SecCol;
+ UINTN ThdCol;
+ UINTN LeftColumnOfHelp;
+ UINTN RightColumnOfHelp;
+ UINTN TopRowOfHelp;
+ UINTN BottomRowOfHelp;
+ UINTN StartColumnOfHelp;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
+ ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
+
+ StartColumnOfHelp = LocalScreen.LeftColumn + 2;
+ LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
+ RightColumnOfHelp = LocalScreen.RightColumn - 2;
+ TopRowOfHelp = LocalScreen.BottomRow - 4;
+ BottomRowOfHelp = LocalScreen.BottomRow - 3;
+
+ if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
+ return ;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ switch (Selection->ThisTag->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_DATE_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (!Selected) {
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+
+ }
+
+ if ((Selection->ThisTag->Operand == EFI_IFR_DATE_OP) || (Selection->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ PrintAt (
+ StartColumnOfHelp,
+ BottomRowOfHelp,
+ (CHAR16 *) L"%c%c%c%c%s",
+ ARROW_UP,
+ ARROW_DOWN,
+ ARROW_RIGHT,
+ ARROW_LEFT,
+ gMoveHighlight
+ );
+ PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
+ } else {
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+
+ //
+ // If it is a selected numeric with manual input, display different message
+ //
+ if ((Selection->ThisTag->Operand == EFI_IFR_NUMERIC_OP) && (Selection->ThisTag->Step == 0)) {
+ PrintStringAt (SecCol, TopRowOfHelp, gNumericInput);
+ } else if (Selection->ThisTag->Operand != EFI_IFR_ORDERED_LIST_OP) {
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ }
+
+ if (Selection->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
+ }
+
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
+ break;
+
+ case EFI_IFR_REF_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (!Selected) {
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ } else {
+ if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
+ PrintStringAt (
+ (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
+ BottomRowOfHelp,
+ gEnterCommitString
+ );
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+ }
+ break;
+ }
+
+}
+
+STATIC
+VOID
+ExtractFormHandle (
+ IN UI_MENU_OPTION *Selection,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINTN IdValue,
+ OUT UINT16 *FormHandle,
+ OUT UINT16 *TitleToken,
+ OUT EFI_FORM_TAGS *FormTags
+ )
+{
+ UINTN Index;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_FORM_TAGS LocalTags;
+
+ FileFormTags = FileFormTagsHead;
+
+ //
+ // Advance FileFormTags to the correct file's tag information.
+ // For instance, if Selection->IfrNumber is 3, that means the 4th
+ // file (0-based) in the FileFormTags linked-list contains the tag
+ // information.
+ //
+ for (Index = 0; Index < Selection->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ LocalTags = FileFormTags->FormTags;
+
+ if (IdValue == 0) {
+ //
+ // Advance Index to the first FormOp tag information
+ //
+ for (Index = 0; FileFormTags->FormTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ } else {
+ //
+ // Advance Index to the FormOp with the correct ID value
+ //
+ for (; LocalTags.Next != NULL; LocalTags = *LocalTags.Next) {
+ for (Index = 0; LocalTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ if (LocalTags.Tags[Index].Id == IdValue) {
+ break;
+ }
+ }
+ }
+ //
+ // return the Form Id, Text, and the File's FormTags structure
+ //
+ *FormHandle = LocalTags.Tags[Index].Id;
+ *TitleToken = LocalTags.Tags[Index].Text;
+ *FormTags = LocalTags;
+ return ;
+}
+
+STATIC
+EFI_STATUS
+UpdateNewTagData (
+ IN UINT8 *FormData,
+ IN UINT16 ConsistencyId,
+ IN UINT16 CurrentVariable,
+ IN EFI_FORM_TAGS *FormTags,
+ OUT EFI_FILE_FORM_TAGS *FileFormTags
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 QuestionIndex;
+ UINT16 NumberOfTags;
+ INT16 CurrTag;
+ UINT8 TagLength;
+ UINTN Count;
+ BOOLEAN Finished;
+
+ //
+ // Initialize some Index variable and Status
+ //
+ Count = 0;
+ QuestionIndex = 0;
+ NumberOfTags = 1;
+ Index = 0;
+ Status = EFI_SUCCESS;
+ Finished = FALSE;
+
+ //
+ // Determine the number of tags for the first form
+ //
+ GetTagCount (&FormData[Index], &NumberOfTags);
+
+ //
+ // Allocate memory for our tags on the first form
+ //
+ FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
+ ASSERT (FormTags->Tags != NULL);
+
+ for (CurrTag = 0; FormData[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
+ //
+ // Operand = IFR OpCode
+ //
+ FormTags->Tags[CurrTag].Operand = FormData[Index];
+
+ //
+ // Assume for now 0 lines occupied by this OpCode
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 0;
+
+ //
+ // Determine the length of the Tag so we can later skip to the next tag in the form
+ //
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ //
+ // Operate on the Found OpCode
+ //
+ switch (FormData[Index]) {
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_SUBTITLE_OP:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_REF_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &FormData[Index])->VarId, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_END_FORM_OP:
+ FormTags->Tags[CurrTag].Operand = FormData[Index];
+ FormTags->Tags[CurrTag].NumberOfLines = 0;
+
+ Finished = TRUE;
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+
+ //
+ // Store away the CurrTag since what follows will be the answer that we
+ // need to place into the appropriate location in the tag array
+ //
+ //
+ // record for setting default later
+ //
+ QuestionIndex = (UINT16) CurrTag;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[QuestionIndex].Key = ((EFI_IFR_ONE_OF_OPTION *) &FormData[Index])->Key;
+ FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_DATE_OP:
+ //
+ // Date elements come in as a Year, Month, Day. We need to process them as a country-based
+ // Order. It is much easier to do it here than anywhere else.
+ //
+ // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2
+ //
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag],
+ FormData,
+ (UINT16) (Index + TagLength),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 1].Operand = FormData[Index];
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag + 1],
+ FormData,
+ (UINT16) (Index + TagLength + FormData[Index + TagLength + 1]),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 2].Operand = FormData[Index];
+ GetNumericHeader (&FormTags->Tags[CurrTag + 2], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+
+ CurrTag = (INT16) (CurrTag + 2);
+
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ break;
+
+ case EFI_IFR_TIME_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 0, FileFormTags, CurrentVariable);
+
+ if (Count == 2) {
+ //
+ // Override the GetQuestionHeader information - date/time are treated very differently
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 1;
+ Count = 0;
+ } else {
+ //
+ // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
+ // associated with them, and the third has 1 line to allow to space beyond the choice.
+ //
+ Count++;
+ }
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ case EFI_IFR_SUPPRESS_IF_OP:
+ case EFI_IFR_GRAYOUT_IF_OP:
+ ConsistencyId++;
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_GT_OP:
+ case EFI_IFR_GE_OP:
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ default:
+ break;
+ }
+ //
+ // End of switch
+ //
+ if (Finished) {
+ break;
+ }
+ //
+ // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
+ //
+ Index = (UINT16) (Index + TagLength);
+ }
+ //
+ // End of Index
+ //
+ return Status;
+}
+
+STATIC
+VOID
+ExtractDynamicFormHandle (
+ IN UI_MENU_OPTION *Selection,
+ IN UINT8 *CallbackData,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINTN IdValue,
+ OUT UINT16 *FormHandle,
+ OUT UINT16 *TitleToken,
+ OUT EFI_FORM_TAGS *FormTags
+ )
+/*++
+
+Routine Description:
+
+ The function does the most of the works when the EFI_TAG that
+ user selects on is EFI_IFR_FLAG_INTERACTIVE or EFI_IFR_PASSWORD_OP:
+ invoke CallBack, update the new form data.
+
+Arguments:
+
+ Selection - The current selection of the form.
+ CallbackData - The pointer to host the data passed back by the callback function.
+ FileFormTagsHead - Prompt string token of the one-of box
+ IdValue - The current page number.
+ FormHandle - Output the the handle of the form.
+ TitleToken - Output the TitleToken of the new page.
+ FormTags - Output the FormFags of the new page.
+
+Returns:
+ VOID
+
+--*/
+{
+ UINTN Index;
+ UINTN BackupIndex;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_FORM_TAGS *LocalTags;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ EFI_PHYSICAL_ADDRESS CallbackHandle;
+ EFI_GUID TagGuid;
+ UINT16 TargetPage;
+ EFI_HII_CALLBACK_PACKET *Packet;
+ UINTN ScreenSize;
+ CHAR16 NullCharacter;
+ EFI_INPUT_KEY Key;
+ UINT16 ConsistencyId;
+ UINT16 CurrentVariable;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_IFR_DATA_ENTRY *DataEntry;
+
+ VariableDefinition = NULL;
+ NullCharacter = CHAR_NULL;
+
+ CurrentVariable = 0;
+ FileFormTags = FileFormTagsHead;
+ Length = 0;
+ CallbackHandle = 0;
+ TargetPage = (UINT16) IdValue;
+ Packet = NULL;
+ ConsistencyId = 0;
+
+ //
+ // Advance FileFormTags to the correct file's tag information.
+ // For instance, if Selection->IfrNumber is 3, that means the 4th
+ // file (0-based) in the FileFormTags linked-list contains the tag
+ // information.
+ //
+ for (Index = 0; Index < Selection->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ LocalTags = &FileFormTags->FormTags;
+
+ //
+ // Advance Index to the FormOp with the correct ID value
+ //
+ for (; LocalTags->Next != NULL; LocalTags = LocalTags->Next) {
+ if ((LocalTags->Tags[0].CallbackHandle != 0) && (CallbackHandle == 0)) {
+ CallbackHandle = LocalTags->Tags[0].CallbackHandle;
+ CopyMem (&TagGuid, &LocalTags->Tags[0].GuidValue, sizeof (EFI_GUID));
+ }
+
+ for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ if (LocalTags->Tags[Index].Id == IdValue) {
+ break;
+ }
+ }
+ //
+ // If we are going to callback on a non-goto opcode, make sure we don't change pages
+ //
+ if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
+ TargetPage = Selection->FormId;
+ }
+ //
+ // The first tag below should be the form op-code. We need to store away the
+ // current variable setting to ensure if we have to reload the page, that we
+ // can correctly restore the values for the active variable
+ //
+ CurrentVariable = Selection->Tags[0].VariableNumber;
+
+ //
+ // Remember that dynamic pages in an environment where all pages are not
+ // dynamic require us to call back to the user to give them an opportunity
+ // to register fresh information in the HII database so that we can extract it.
+ //
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (LocalTags->Tags);
+ return ;
+ }
+
+ ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition);
+
+ if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) {
+ ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap;
+ } else {
+ ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL;
+ }
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Selection->ThisTag->Key,
+ (EFI_IFR_DATA_ARRAY *) CallbackData,
+ &Packet
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Restore Previous Value
+ //
+ CopyMem (
+ &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
+ gPreviousValue,
+ Selection->ThisTag->StorageWidth
+ );
+
+ if (Packet != NULL) {
+ //
+ // Upon error, we will likely receive a string to print out
+ //
+ ScreenSize = GetStringWidth (Packet->String) / 2;
+
+ //
+ // Display error popup
+ //
+ CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ } else {
+ UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE);
+ }
+
+ } else {
+ if (Packet != NULL) {
+ //
+ // We need to on a non-error, look in the outbound Packet for information and update the NVRAM
+ // location associated with the op-code specified there. This is used on single op-code instances
+ // and not for when a hyperlink sent us a whole page of data.
+ //
+ DataEntry = (EFI_IFR_DATA_ENTRY *) (&Packet->DataArray + 1);
+ if (Packet->DataArray.EntryCount == 1) {
+ switch (DataEntry->OpCode) {
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_CHECKBOX_OP:
+ CopyMem (
+ &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
+ &DataEntry->Data,
+ Selection->ThisTag->StorageWidth
+ );
+ break;
+
+ case EFI_IFR_NV_ACCESS_COMMAND:
+ CopyMem (
+ &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId],
+ ((EFI_IFR_NV_DATA *) Packet) + 1,
+ ((EFI_IFR_NV_DATA *) Packet)->StorageWidth
+ );
+ break;
+
+ }
+
+ if (DataEntry->Flags & RESET_REQUIRED) {
+ gResetRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & EXIT_REQUIRED) {
+ gExitRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & SAVE_REQUIRED) {
+ gSaveRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & NV_CHANGED) {
+ gNvUpdateRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & NV_NOT_CHANGED) {
+ gNvUpdateRequired = FALSE;
+ }
+ }
+ }
+ }
+
+ if (Packet != NULL) {
+ FreePool (Packet);
+ }
+
+ for (BackupIndex = 0; LocalTags->Tags[BackupIndex].Operand != EFI_IFR_END_FORM_OP; BackupIndex++) {
+ switch (LocalTags->Tags[BackupIndex].Operand) {
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ case EFI_IFR_EQ_ID_VAL_OP:
+ case EFI_IFR_EQ_ID_ID_OP:
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_GT_OP:
+ case EFI_IFR_GE_OP:
+ case EFI_IFR_EQ_ID_LIST_OP:
+ //
+ // If we encountered a ConsistencyId value, on this page they will be incremental
+ // So register the first value we encounter. We will pass this in when we re-create this page
+ //
+ if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) {
+ ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1);
+ }
+ break;
+ }
+ }
+ //
+ // Delete the buffer associated with previous dynamic page
+ // We will re-allocate a buffer....
+ //
+ FreePool (LocalTags->Tags);
+
+ Length = 0xF000;
+ Buffer = AllocateZeroPool (Length);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Get the form that was updated by the callback
+ //
+ Hii->GetForms (
+ Hii,
+ Selection->Handle,
+ TargetPage,
+ &Length,
+ Buffer
+ );
+
+ //
+ // Ok, we have the new page.....now we must purge the old page and re-allocate
+ // the tag page with the new data
+ //
+ UpdateNewTagData (
+ Buffer,
+ ConsistencyId,
+ CurrentVariable,
+ LocalTags,
+ FileFormTags
+ );
+
+ //
+ // return the Form Id, Text, and the File's FormTags structure
+ //
+ *FormHandle = LocalTags->Tags[0].Id;
+ *TitleToken = LocalTags->Tags[0].Text;
+ *FormTags = *LocalTags;
+
+ FormTags->Tags[0].CallbackHandle = CallbackHandle;
+ CopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID));
+
+ return ;
+}
+
+UI_MENU_OPTION *
+SetupBrowser (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Callback,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+{
+ UINT16 FormHandle;
+ UINT16 TitleToken;
+ EFI_FORM_TAGS FormTags;
+
+ gEntryNumber = -1;
+ gLastOpr = FALSE;
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ //
+ // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR
+ //
+ ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags);
+
+ Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
+
+ //
+ // If selection is null use the former selection
+ //
+ if (Selection == NULL) {
+ return Selection;
+ }
+
+ if (Callback) {
+ return Selection;
+ }
+
+ while (Selection->Tags != NULL) {
+ if (Selection->Previous) {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
+ } else {
+ //
+ // True if a hyperlink/jump is selected
+ //
+ if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) {
+ if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ ExtractDynamicFormHandle (
+ Selection,
+ CallbackData,
+ FileFormTagsHead,
+ Selection->ThisTag->Id,
+ &FormHandle,
+ &TitleToken,
+ &FormTags
+ );
+ goto DisplayPage;
+ } else {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags);
+ goto DisplayPage;
+ }
+ }
+
+ if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) &&
+ (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP)
+ ) {
+ ExtractDynamicFormHandle (
+ Selection,
+ CallbackData,
+ FileFormTagsHead,
+ Selection->FormId,
+ &FormHandle,
+ &TitleToken,
+ &FormTags
+ );
+ } else {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
+ }
+ }
+
+DisplayPage:
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
+
+ if (Selection == NULL) {
+ break;
+ }
+ };
+
+ return Selection;
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.c
new file mode 100644
index 0000000000..a0143ddb51
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.c
@@ -0,0 +1,298 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Print.c
+
+Abstract:
+
+ Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
+ simple implemenation of SPrint() and Print() to support debug.
+
+ You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
+ time. This makes the implementation very simple.
+
+ VSPrint, Print, SPrint format specification has the follwoing form
+
+ %type
+
+ type:
+ 'S','s' - argument is an Unicode string
+ 'c' - argument is an ascii character
+ '%' - Print a %
+
+--*/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Print.h"
+
+STATIC
+UINTN
+_IPrint (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *Out,
+ IN CHAR16 *fmt,
+ IN VA_LIST args
+ )
+//
+// Display string worker for: Print, PrintAt, IPrint, IPrintAt
+//
+{
+ CHAR16 *Buffer;
+ CHAR16 *BackupBuffer;
+ UINTN Index;
+ UINTN PreviousIndex;
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ BackupBuffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer);
+ ASSERT (BackupBuffer);
+
+ if (Column != (UINTN) -1) {
+ Out->SetCursorPosition (Out, Column, Row);
+ }
+
+ UnicodeVSPrint (Buffer, 0x10000, fmt, args);
+
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+
+ Index = 0;
+ PreviousIndex = 0;
+
+ do {
+ for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
+ BackupBuffer[Index] = Buffer[Index];
+ }
+
+ if (Buffer[Index] == 0) {
+ break;
+ }
+ //
+ // Null-terminate the temporary string
+ //
+ BackupBuffer[Index] = 0;
+
+ //
+ // Print this out, we are about to switch widths
+ //
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+
+ //
+ // Preserve the current index + 1, since this is where we will start printing from next
+ //
+ PreviousIndex = Index + 1;
+
+ //
+ // We are at a narrow or wide character directive. Set attributes and strip it and print it
+ //
+ if (Buffer[Index] == NARROW_CHAR) {
+ //
+ // Preserve bits 0 - 6 and zero out the rest
+ //
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ } else {
+ //
+ // Must be wide, set bit 7 ON
+ //
+ Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ }
+
+ Index++;
+
+ } while (Buffer[Index] != 0);
+
+ //
+ // We hit the end of the string - print it
+ //
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+
+ FreePool (Buffer);
+ FreePool (BackupBuffer);
+ return EFI_SUCCESS;
+}
+
+UINTN
+Print (
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console
+
+Arguments:
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ VA_LIST args;
+
+ VA_START (args, fmt);
+ return _IPrint ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args);
+}
+
+UINTN
+PrintString (
+ CHAR16 *String
+ )
+/*++
+
+Routine Description:
+
+ Prints a unicode string to the default console,
+ using L"%s" format.
+
+Arguments:
+
+ String - String pointer.
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ return Print ((CHAR16 *) L"%s", String);
+}
+
+UINTN
+PrintChar (
+ CHAR16 Character
+ )
+/*++
+
+Routine Description:
+
+ Prints a chracter to the default console,
+ using L"%c" format.
+
+Arguments:
+
+ Character - Character to print.
+
+Returns:
+
+ Length of string printed to the console.
+
+--*/
+{
+ return Print ((CHAR16 *) L"%c", Character);
+}
+
+UINTN
+PrintAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position
+
+Arguments:
+
+ Column, Row - The cursor position to print the string at
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ VA_LIST args;
+
+ VA_START (args, fmt);
+ return _IPrint (Column, Row, gST->ConOut, fmt, args);
+}
+
+UINTN
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 *String
+ )
+/*++
+
+Routine Description:
+
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+Arguments:
+
+ Column, Row - The cursor position to print the string at
+
+ String - String pointer.
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ return PrintAt (Column, Row, (CHAR16 *) L"%s", String);
+}
+
+UINTN
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+/*++
+
+Routine Description:
+
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+Arguments:
+
+ Column, Row - The cursor position to print the string at
+
+ Character - Character to print.
+
+Returns:
+
+ Length of string printed to the console.
+
+--*/
+{
+ return PrintAt (Column, Row, (CHAR16 *) L"%c", Character);
+}
+
+
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.h b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.h
new file mode 100644
index 0000000000..8ce993b765
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Print.h
@@ -0,0 +1,44 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Print.h
+
+Abstract:
+
+ Private data for Print.c
+
+--*/
+
+#ifndef _PRINT_H_
+#define _PRINT_H_
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+
+#define LEFT_JUSTIFY 0x01
+#define PREFIX_SIGN 0x02
+#define PREFIX_BLANK 0x04
+#define COMMA_TYPE 0x08
+#define LONG_TYPE 0x10
+#define PREFIX_ZERO 0x20
+
+//
+// Largest number of characters that can be printed out.
+//
+#define EFI_DRIVER_LIB_MAX_PRINT_BUFFER (80 * 4)
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
new file mode 100644
index 0000000000..fd6addf518
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
@@ -0,0 +1,1692 @@
+/**@file
+ Implementation for handling the User Interface option processing.
+
+Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+
+EFI_STATUS
+ExtractRequestedNvMap (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 VariableId,
+ OUT EFI_VARIABLE_DEFINITION **VariableDefinition
+ )
+{
+ *VariableDefinition = FileFormTags->VariableDefinitions;
+
+ //
+ // Extract the data from the NV variable - consumer will free the buffer.
+ //
+ for (; *VariableDefinition != NULL; *VariableDefinition = (*VariableDefinition)->Next) {
+ //
+ // If there is a variable with this ID return with EFI_SUCCESS
+ //
+ if (!CompareMem (&(*VariableDefinition)->VariableId, &VariableId, sizeof (UINT16))) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+ExtractNvValue (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 VariableId,
+ IN UINT16 VariableSize,
+ IN UINT16 OffsetValue,
+ OUT VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+
+ Status = ExtractRequestedNvMap (FileFormTags, VariableId, &VariableDefinition);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocate sufficient space for the data and copy it into the outgoing buffer
+ //
+ if (VariableSize != 0) {
+ *Buffer = AllocateZeroPool (VariableSize);
+ ASSERT (*Buffer != NULL);
+ CopyMem (*Buffer, &VariableDefinition->NvRamMap[OffsetValue], VariableSize);
+ }
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+STATIC
+VOID
+AdjustNvMap (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UI_MENU_OPTION *MenuOption
+ )
+{
+ CHAR8 *NvRamMap;
+ UINTN SizeRequired;
+ UINTN Index;
+ UINTN CachedStart;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+
+ CachedStart = 0;
+
+ SizeRequired = MenuOption->ThisTag->StorageStart + MenuOption->ThisTag->StorageWidth;
+
+ ExtractRequestedNvMap (FileFormTags, MenuOption->Tags->VariableNumber, &VariableDefinition);
+
+ //
+ // We arrived here because the current NvRamMap is too small for the new op-code to store things and
+ // we need to adjust the buffer to support this.
+ //
+ NvRamMap = AllocateZeroPool (SizeRequired + 1);
+ ASSERT (NvRamMap != NULL);
+
+ //
+ // Copy current NvRamMap to the new NvRamMap
+ //
+ CopyMem (NvRamMap, VariableDefinition->NvRamMap, VariableDefinition->VariableFakeSize);
+
+ //
+ // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap
+ //
+ for (Index = MenuOption->TagIndex;
+ (MenuOption->Tags[Index].Operand != EFI_IFR_END_FORM_OP) && (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP);
+ Index++
+ ) {
+
+ switch (MenuOption->Tags[Index].Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ CachedStart = MenuOption->Tags[Index].StorageStart;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) {
+ CopyMem (&NvRamMap[CachedStart], &MenuOption->Tags[Index].Value, 2);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ CopyMem (&NvRamMap[MenuOption->Tags[Index].StorageStart], &MenuOption->Tags[Index].Flags, 1);
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_DATE_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_PASSWORD_OP:
+ CopyMem (
+ &NvRamMap[MenuOption->Tags[Index].StorageStart],
+ &MenuOption->Tags[Index].Value,
+ MenuOption->Tags[Index].StorageWidth
+ );
+ break;
+
+ }
+ }
+
+ FreePool (VariableDefinition->NvRamMap);
+ VariableDefinition->NvRamMap = NvRamMap;
+ VariableDefinition->VariableFakeSize = (UINT16) SizeRequired;
+}
+
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN EFI_IFR_DATA_ARRAY *PageData,
+ OUT CHAR16 **OptionString
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ UINTN Index;
+ UINTN CachedIndex;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_TAG *Tag;
+ CHAR16 FormattedNumber[6];
+ UINT16 Number;
+ UINT16 Value;
+ UINT16 *ValueArray;
+ UINT16 *NvRamMap;
+ CHAR8 *TmpNvRamMap;
+ UINTN Default;
+ UINTN StringCount;
+ CHAR16 Character[2];
+ UINTN Count;
+ EFI_TIME Time;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ STRING_REF PopUp;
+ CHAR16 NullCharacter;
+ EFI_INPUT_KEY Key;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ BOOLEAN OrderedList;
+ BOOLEAN Initialized;
+ UINT16 KeyValue;
+ BOOLEAN Skip;
+
+ FileFormTags = FileFormTagsHead;
+
+ for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ OrderedList = FALSE;
+ Initialized = FALSE;
+ ValueArray = NULL;
+ VariableDefinition = NULL;
+ Skip = FALSE;
+
+ ZeroMem (&Time, sizeof (EFI_TIME));
+
+ StringPtr = (CHAR16 *) L"\0";
+ Tag = MenuOption->ThisTag;
+ ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
+
+ if (Tag->StorageStart > VariableDefinition->VariableSize) {
+ NvRamMap = (UINT16 *) &VariableDefinition->FakeNvRamMap[Tag->StorageStart];
+ } else {
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ StringCount = 0;
+ Character[1] = 0;
+ Count = 0;
+ Default = 0;
+ NullCharacter = CHAR_NULL;
+ FormCallback = NULL;
+
+ if (MenuOption->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ OrderedList = TRUE;
+ if (((UINT8 *) NvRamMap)[0] != 0x00) {
+ Initialized = TRUE;
+ }
+ }
+
+ ZeroMem (FormattedNumber, 12);
+
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ if (*OptionString != NULL) {
+ FreePool (*OptionString);
+ *OptionString = NULL;
+ }
+
+ switch (Tag->Operand) {
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ CachedIndex = MenuOption->TagIndex;
+
+ //
+ // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP,
+ // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks
+ // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice
+ //
+ for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {
+ //
+ // We found an option - which assumedly has a string. We will eventually have to support
+ // wrapping of strings. For now, let's pretend they don't wrap and code that up.
+ //
+ // Count how many strings there are
+ //
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ //
+ // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too
+ //
+ if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ MenuOption->Tags[CachedIndex].Flags = (UINT8) (MenuOption->Tags[CachedIndex].Flags | EFI_IFR_FLAG_INTERACTIVE);
+ }
+
+ StringCount++;
+ }
+ }
+ //
+ // We now know how many strings we will have, so we can allocate the
+ // space required for the array or strings.
+ //
+ *OptionString = AllocateZeroPool (StringCount * (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ //
+ // Add left delimeter to string
+ //
+ *OptionString[0] = LEFT_ONEOF_DELIMITER;
+
+ //
+ // Retrieve the current OneOf value
+ //
+ if (Selected) {
+ //
+ // Auto selection from list
+ //
+ Value = 0;
+ //
+ // Copy current setting to the seed Value
+ //
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ ValueArray = AllocateZeroPool (MenuOption->ThisTag->StorageWidth);
+ ASSERT (ValueArray != NULL);
+ CopyMem (ValueArray, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ } else {
+ CopyMem (&Value, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ }
+
+ Number = Value;
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ Status = GetSelectionInputPopUp (MenuOption, Tag, MenuOption->ThisTag->StorageWidth, ValueArray, &KeyValue);
+ } else {
+ Status = GetSelectionInputPopUp (MenuOption, Tag, 1, &Value, &KeyValue);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ CopyMem (NvRamMap, ValueArray, MenuOption->ThisTag->StorageWidth);
+ FreePool (ValueArray);
+ } else {
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Value, Tag->StorageWidth);
+ MenuOption->ThisTag->Key = KeyValue;
+ }
+ //
+ // If a late check is required save off the information. This is used when consistency checks
+ // are required, but certain values might be bound by an impossible consistency check such as
+ // if two questions are bound by consistency checks and each only has two possible choices, there
+ // would be no way for a user to switch the values. Thus we require late checking.
+ //
+ if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
+ CopyMem (&Tag->OldValue, &Value, Tag->StorageWidth);
+ } else {
+ //
+ // In theory, passing the value and the Id are sufficient to determine what needs
+ // to be done. The Id is the key to look for the entry needed in the Inconsistency
+ // database. That will yields operand and ID data - and since the ID's correspond
+ // to the NV storage, we can determine the values for other IDs there.
+ //
+ if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
+ if (PopUp == 0x0000) {
+ //
+ // Restore Old Value
+ //
+ if (!Tag->Suppress && !Tag->GrayOut) {
+ CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);
+ }
+ break;
+ }
+
+ StringPtr = GetToken (PopUp, MenuOption->Handle);
+
+ CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);
+ FreePool (StringPtr);
+ break;
+
+ default:
+ break;
+ }
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+ }
+
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
+ } else {
+ if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ FreePool (ValueArray);
+ }
+
+ return EFI_SUCCESS;
+ }
+ } else {
+ for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {
+ //
+ // We found an option - which assumedly has a string. We will eventually have to support
+ // wrapping of strings. For now, let's pretend they don't wrap and code that up.
+ //
+ if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ if (OrderedList) {
+ if (!Initialized) {
+ //
+ // If the first entry is invalid, then the "default" settings are based on what is reflected
+ // in the order of the op-codes
+ //
+ ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1] = (UINT8) MenuOption->Tags[Index].Value;
+ }
+ //
+ // Only display 3 lines of stuff at most
+ //
+ if ((Index - MenuOption->TagIndex) > ORDERED_LIST_SIZE) {
+ break;
+ }
+
+ if (((Index - MenuOption->TagIndex) != 1) && !Skip) {
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ }
+
+ MenuOption->ThisTag->NumberOfLines = (UINT16) (Index - MenuOption->TagIndex);
+ if (!Initialized) {
+ StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle);
+ } else {
+ for (Value = (UINT16) (MenuOption->TagIndex + 1);
+ MenuOption->Tags[Value].Operand != EFI_IFR_END_ONE_OF_OP;
+ Value++
+ ) {
+ if (MenuOption->Tags[Value].Value == ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1]) {
+ StringPtr = GetToken (MenuOption->Tags[Value].Text, MenuOption->Handle);
+ break;
+ }
+ }
+
+ if (MenuOption->Tags[Value].Operand == EFI_IFR_END_ONE_OF_OP) {
+ Skip = TRUE;
+ continue;
+ }
+ }
+
+ Skip = FALSE;
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ Character[0] = CHAR_CARRIAGE_RETURN;
+ NewStrCat (OptionString[0], Character);
+
+ //
+ // Remove Buffer allocated for StringPtr after it has been used.
+ //
+ FreePool (StringPtr);
+ } else {
+ //
+ // The option value is the same as what is stored in NV store. Print this.
+ //
+ if (!CompareMem (&(MenuOption->Tags[Index].Value), NvRamMap, MenuOption->ThisTag->StorageWidth)) {
+ StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ //
+ // Remove Buffer allocated for StringPtr after it has been used.
+ //
+ FreePool (StringPtr);
+ Default = 0;
+ break;
+ }
+
+ if ((MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) == 1) {
+ Default = MenuOption->Tags[Index].Text;
+ Value = MenuOption->Tags[Index].Value;
+ };
+ }
+ }
+ }
+ //
+ // We didn't find a value that matched a setting in the NVRAM Map - display default - set default
+ //
+ if (Default != 0) {
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Value, MenuOption->ThisTag->StorageWidth);
+
+ StringPtr = GetToken ((UINT16) Default, MenuOption->Handle);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ //
+ // Remove Buffer allocated for StringPtr after it has been used.
+ //
+ FreePool (StringPtr);
+ }
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ Default = Tag->Flags & 1;
+ //
+ // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN
+ //
+ *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ //
+ // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if
+ // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not
+ // an active field for Checkboxes.
+ //
+ StrnCpy (OptionString[0], (CHAR16 *) LEFT_CHECKBOX_DELIMITER, 1);
+
+ //
+ // Since this is a BOOLEAN operation, flip bit 0 upon selection
+ //
+ if (Selected) {
+ Tag->Value = (UINT16) (Tag->Value ^ 1);
+ *(UINT8 *) NvRamMap = (UINT8) (Tag->Value & 1);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
+ }
+
+ if ((*(UINT8 *) NvRamMap & 1) == 0x01) {
+ NewStrCat (OptionString[0], (CHAR16 *) CHECK_ON);
+ //
+ // If someone reset default variables - we may need to reload from our NvMapping....
+ //
+ Tag->Value = *(UINT8 *) NvRamMap;
+ } else {
+ //
+ // If someone reset default variables - we may need to reload from our NvMapping....
+ //
+ NewStrCat (OptionString[0], (CHAR16 *) CHECK_OFF);
+ Tag->Value = *(UINT8 *) NvRamMap;
+ }
+
+ NewStrCat (OptionString[0], (CHAR16 *) RIGHT_CHECKBOX_DELIMITER);
+ NewStrCat (OptionString[0], StringPtr);
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ //
+ // Add left delimeter to string
+ //
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+
+ //
+ // Retrieve the current numeric value
+ //
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ if (Tag->Step == 0) {
+ //
+ // Manual Input
+ //
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, REGULAR_NUMERIC, &Number);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
+
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // Auto selection from list
+ //
+ if ((((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) > Tag->Maximum) || ((UINT8) (*NvRamMap) < Tag->Minimum)) ||
+ (((Tag->StorageWidth == 2) && *NvRamMap > Tag->Maximum) || (*NvRamMap < Tag->Minimum))
+ ) {
+ //
+ // Seed Number with valid value if currently invalid
+ //
+ Number = Tag->Default;
+ } else {
+ if (Tag->StorageWidth == 1) {
+ Number = (UINT8) (*NvRamMap);
+ } else {
+ Number = *NvRamMap;
+ }
+ }
+
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, REGULAR_NUMERIC, &Number);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
+
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth);
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+ } else {
+ if (((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) <= Tag->Maximum && (UINT8) (*NvRamMap) >= Tag->Minimum) ||
+ ((Tag->StorageWidth == 2) && *NvRamMap <= Tag->Maximum && *NvRamMap >= Tag->Minimum)
+ ) {
+ if (Tag->StorageWidth == 1) {
+ Number = (UINT8) (*NvRamMap);
+ } else {
+ Number = *NvRamMap;
+ }
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Number,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ StrnCpy (OptionString[0] + 1, FormattedNumber, Number);
+ } else {
+ //
+ // If *NvRamMap isn't within parameters, set it to within parameters
+ //
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Tag->Default, MenuOption->ThisTag->StorageWidth);
+ Number = Tag->Default;
+
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Number,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ StrnCpy (OptionString[0] + 1, FormattedNumber, Number);
+ }
+
+ *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
+ NewStrCat (OptionString[0] + (Number / 2) + 1, StringPtr);
+ }
+ break;
+
+ case EFI_IFR_DATE_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ Status = gRT->GetTime (&Time, NULL);
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // This for loop advances Index till it points immediately after a date entry. We can then
+ // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
+ // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
+ // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
+ // date operands.
+ //
+ //
+ // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code
+ // against such silliness.
+ //
+ // Also, we want to internationalize the order of the date information. We need to code for it as well.
+ //
+ for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_DATE_OP; Index++)
+ ;
+
+ //
+ // Count 0 = We entered on the first Date operand
+ // Count 1 = We entered on the second Date operand
+ // Count 2 = We entered on the third Date operand
+ //
+ Count = 3 - (Index - MenuOption->TagIndex);
+ if (Count > 2) {
+ return EFI_SUCCESS;
+ }
+ //
+ // This is similar to numerics, except for the following:
+ // We will under normal circumstances get 3 consecutive calls
+ // to process this opcodes data.
+ //
+ *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ switch (Count) {
+ case 0:
+ if (Selected) {
+ Number = (UINT16) Time.Month;
+
+ if (Tag->Step == 0) {
+ MenuOption->OptCol++;
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);
+ } else {
+ //
+ // Seed value with current setting
+ //
+ Tag->Value = (UINT16) Time.Month;
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Time.Month = (UINT8) Number;
+ gRT->SetTime (&Time);
+ }
+ }
+
+ VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Month;
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Month,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+
+ if (Number == 4) {
+ FormattedNumber[2] = FormattedNumber[1];
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 6;
+ }
+
+ StrnCpy (OptionString[0] + 1, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2) = DATE_SEPARATOR;
+ StrCat (OptionString[0] + (Number / 2) + 1, StringPtr);
+ break;
+
+ case 1:
+ if (Selected) {
+ Number = (UINT16) Time.Day;
+
+ if (Tag->Step == 0) {
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);
+ } else {
+ //
+ // Seed value with current setting
+ //
+ Tag->Value = (UINT16) Time.Day;
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Time.Day = (UINT8) Number;
+ gRT->SetTime (&Time);
+ }
+ }
+
+ VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Day;
+ SetUnicodeMem (OptionString[0], 4, L' ');
+
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Day,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ if (Number == 4) {
+ FormattedNumber[2] = FormattedNumber[1];
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 6;
+ }
+
+ StrnCpy (OptionString[0] + 4, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2 + 3) = DATE_SEPARATOR;
+ StrCat (OptionString[0] + (Number / 2) + 4, StringPtr);
+ break;
+
+ case 2:
+ if (Selected) {
+ Number = (UINT16) Time.Year;
+
+ if (Tag->Step == 0) {
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number);
+ } else {
+ //
+ // Seed value with current setting
+ //
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Time.Year = (UINT16) Number;
+ gRT->SetTime (&Time);
+ }
+ }
+
+ Tag->Value = (UINT16) Time.Year;
+ VariableDefinition->FakeNvRamMap[Tag->Id] = (UINT8) Tag->Value;
+ VariableDefinition->FakeNvRamMap[Tag->Id + 1] = (UINT8) (Tag->Value >> 8);
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Year,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ StrnCpy (OptionString[0] + 7, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER;
+ StrCat (OptionString[0] + (Number / 2) + 7, StringPtr);
+ break;
+ }
+
+ break;
+
+ //
+ // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
+ // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
+ // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ //
+ case EFI_IFR_TIME_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ Status = gRT->GetTime (&Time, NULL);
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // This is similar to numerics, except for the following:
+ // We will under normal circumstances get 3 consecutive calls
+ // to process this opcodes data.
+ //
+ *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ //
+ // This for loop advances Index till it points immediately after a date entry. We can then
+ // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date
+ // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index
+ // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3
+ // date operands.
+ //
+ for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_TIME_OP; Index++)
+ ;
+ //
+ // Count 0 = We entered on the first Date operand
+ // Count 1 = We entered on the second Date operand
+ // Count 2 = We entered on the third Date operand
+ //
+ Count = 3 - (Index - MenuOption->TagIndex);
+ if (Count > 2) {
+ return EFI_SUCCESS;
+ }
+
+ switch (Count) {
+ case 0:
+ Number = Time.Hour;
+ break;
+
+ case 1:
+ Number = Time.Minute;
+ break;
+
+ case 2:
+ Number = Time.Second;
+ }
+ //
+ // Retrieve the current numeric value
+ //
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ if (Tag->Step == 0) {
+ //
+ // Manual Input
+ //
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, TIME_NUMERIC, &Number);
+ if (!EFI_ERROR (Status)) {
+ *NvRamMap = Number;
+ Time.Nanosecond = 0;
+ gRT->SetTime (&Time);
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // Auto selection from list
+ //
+ Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, TIME_NUMERIC, &Number);
+ if (!EFI_ERROR (Status)) {
+ *NvRamMap = Number;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ switch (Count) {
+ case 0:
+ Time.Hour = (UINT8) Number;
+ break;
+
+ case 1:
+ Time.Minute = (UINT8) Number;
+ break;
+
+ case 2:
+ Time.Second = (UINT8) Number;
+ }
+
+ Time.Nanosecond = 0;
+ gRT->SetTime (&Time);
+ } else {
+ switch (Count) {
+ case 0:
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Hour,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ if (Number == 4) {
+ FormattedNumber[2] = FormattedNumber[1];
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 6;
+ }
+
+ StrnCpy (OptionString[0] + 1, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2) = TIME_SEPARATOR;
+ StrCat (OptionString[0] + (Number / 2) + 1, StringPtr);
+ break;
+
+ case 1:
+ SetUnicodeMem (OptionString[0], 4, L' ');
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Minute,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ if (Number == 4) {
+ FormattedNumber[2] = FormattedNumber[1];
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 6;
+ }
+
+ StrnCpy (OptionString[0] + 4, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2 + 3) = TIME_SEPARATOR;
+ StrCat (OptionString[0] + (Number / 2) + 4, StringPtr);
+ break;
+
+ case 2:
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeValueToString (
+ FormattedNumber,
+ FALSE,
+ (UINTN) Time.Second,
+ (sizeof (FormattedNumber) / sizeof (FormattedNumber[0]))
+ );
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ if (Number == 4) {
+ FormattedNumber[2] = FormattedNumber[1];
+ FormattedNumber[1] = FormattedNumber[0];
+ FormattedNumber[0] = L'0';
+ Number = 6;
+ }
+
+ StrnCpy (OptionString[0] + 7, FormattedNumber, Number);
+ *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER;
+ StrCat (OptionString[0] + (Number / 2) + 7, StringPtr);
+ break;
+ }
+ //
+ // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone
+ // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction
+ // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG
+ //
+ }
+ break;
+
+ case EFI_IFR_STRING_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow);
+ ASSERT (*OptionString);
+
+ if (Selected) {
+ StringPtr = AllocateZeroPool (Tag->Maximum);
+ ASSERT (StringPtr);
+
+ Status = ReadString (MenuOption, StringPtr);
+
+ if (!EFI_ERROR (Status)) {
+ CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth);
+ CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);
+
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE);
+ }
+
+ FreePool (StringPtr);
+ return Status;
+ } else {
+ for (Index = 0; Index < gOptionBlockWidth; Index++) {
+ if (VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)] != 0x0000) {
+ CopyMem (OptionString[0] + Index, &VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)], 2);
+ } else {
+ if (Index == 0) {
+ *(OptionString[0] + Index) = '_';
+ *(OptionString[0] + 1 + Index) = 0;
+ }
+ break;
+ }
+ }
+
+ return Status;
+ }
+
+ case EFI_IFR_PASSWORD_OP:
+ //
+ // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically
+ // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust
+ // the NvMap so that we can properly display the information
+ //
+ if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) {
+ AdjustNvMap (FileFormTags, MenuOption);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+ }
+
+ if (Selected) {
+ StringPtr = AllocateZeroPool (Tag->Maximum);
+ ASSERT (StringPtr);
+
+ //
+ // If interactive, read the password and do the appropriate callbacks in that routine.
+ // Since interactive passwords assume to handle the password data in a separate variable
+ // storage, we don't need to do more than what is below for password callbacks
+ //
+ if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ MenuOption->Tags[0].CallbackHandle = FileFormTags->FormTags.Tags[0].CallbackHandle;
+ Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);
+ ZeroMem (StringPtr, Tag->Maximum);
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_READY) {
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ReadPassword (MenuOption, TRUE, Tag, PageData, TRUE, FileFormTags, StringPtr);
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; Index < Tag->Maximum; Index++) {
+ if (VariableDefinition->NvRamMap[Tag->StorageStart + Index] != 0x00) {
+ //
+ // There is something there! Prompt for password
+ //
+ Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr);
+ if (EFI_ERROR (Status)) {
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+
+ if (Tag->Encoding == 1) {
+ EncodePassword (StringPtr, (UINT8) Tag->Maximum);
+ Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);
+ } else {
+ Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum);
+ }
+
+ if (Status != 0) {
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ } else {
+ break;
+ }
+ }
+ }
+ //
+ // Clean the string
+ //
+ ZeroMem (StringPtr, Tag->Maximum);
+
+ //
+ // No password set! Go ahead and prompt the user for a password.
+ //
+ Status = ReadPassword (MenuOption, FALSE, Tag, PageData, FALSE, FileFormTags, StringPtr);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // User couldn't figure out how to type two identical passwords
+ //
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+ //
+ // Very simple example of how one MIGHT do password encoding
+ //
+ if (Tag->Encoding == 1) {
+ EncodePassword (StringPtr, (UINT8) Tag->Maximum);
+ }
+
+ TmpNvRamMap = AllocatePool (VariableDefinition->VariableSize);
+ ASSERT (TmpNvRamMap != NULL);
+
+ Count = VariableDefinition->VariableSize;
+
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
+ Status = FormCallback->NvRead (
+ FormCallback,
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &Count,
+ (VOID *) TmpNvRamMap
+ );
+ } else {
+ Status = gRT->GetVariable (
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &Count,
+ (VOID *) TmpNvRamMap
+ );
+ }
+
+ CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);
+ CopyMem (&TmpNvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth);
+
+ if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
+ Status = FormCallback->NvWrite (
+ FormCallback,
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) TmpNvRamMap,
+ &gResetRequired
+ );
+ } else {
+ Status = gRT->SetVariable (
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) TmpNvRamMap
+ );
+ }
+
+ FreePool (TmpNvRamMap);
+ FreePool (StringPtr);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Split StringPtr to several lines of strings stored in FormattedString and the glyph width of
+ each line cannot exceed gHelpBlockWidth.
+
+ @param StringPtr The pointer of string
+ @param FormattedString The pointer of format string
+ @param RowCount The count of row
+
+**/
+VOID
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ IN UINTN RowCount
+ )
+{
+ CONST UINTN BlockWidth = (UINTN) gHelpBlockWidth - 1;
+ UINTN AllocateSize;
+ //
+ // [PrevCurrIndex, CurrIndex) forms a range of a screen-line
+ //
+ UINTN CurrIndex;
+ UINTN PrevCurrIndex;
+ UINTN LineCount;
+ UINTN VirtualLineCount;
+ //
+ // GlyphOffset stores glyph width of current screen-line
+ //
+ UINTN GlyphOffset;
+ //
+ // GlyphWidth equals to 2 if we meet width directive
+ //
+ UINTN GlyphWidth;
+ //
+ // during scanning, we remember the position of last space character
+ // in case that if next word cannot put in current line, we could restore back to the position
+ // of last space character
+ // while we should also remmeber the glyph width of the last space character for restoring
+ //
+ UINTN LastSpaceIndex;
+ UINTN LastSpaceGlyphWidth;
+ //
+ // every time we begin to form a new screen-line, we should remember glyph width of single character
+ // of last line
+ //
+ UINTN LineStartGlyphWidth;
+ UINTN *IndexArray;
+ UINTN *OldIndexArray;
+
+ //
+ // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )
+ // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want
+ // to bring the width directive of the last line to current screen-line.
+ // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line
+ // different from that of "\wideabcde", we should remember the width directive.
+ //
+ AllocateSize = 0x20;
+ IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+
+ if (*FormattedString != NULL) {
+ FreePool (*FormattedString);
+ *FormattedString = NULL;
+ }
+
+ for (PrevCurrIndex = 0, CurrIndex = 0, LineCount = 0, LastSpaceIndex = 0,
+ IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1;
+ (StringPtr[CurrIndex] != CHAR_NULL);
+ CurrIndex ++) {
+
+ if (LineCount == AllocateSize) {
+ AllocateSize += 0x10;
+ OldIndexArray = IndexArray;
+ IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);
+ CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3);
+ if (OldIndexArray != NULL) {
+ FreePool (OldIndexArray);
+ }
+ }
+
+ switch (StringPtr[CurrIndex]) {
+
+ case NARROW_CHAR:
+ case WIDE_CHAR:
+ GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1);
+ if (CurrIndex == 0) {
+ LineStartGlyphWidth = GlyphWidth;
+ }
+ break;
+
+ //
+ // char is '\n'
+ // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN
+ //
+ case CHAR_LINEFEED:
+ //
+ // Store a range of string as a line
+ //
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineCount ++;
+ //
+ // Reset offset and save begin position of line
+ //
+ GlyphOffset = 0;
+ LineStartGlyphWidth = GlyphWidth;
+ PrevCurrIndex = CurrIndex + 1;
+ break;
+
+ //
+ // char is '\r'
+ // "\r\n" and "\r" both are handled here
+ //
+ case CHAR_CARRIAGE_RETURN:
+ if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) {
+ //
+ // next char is '\n'
+ //
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineCount ++;
+ CurrIndex ++;
+ }
+ GlyphOffset = 0;
+ LineStartGlyphWidth = GlyphWidth;
+ PrevCurrIndex = CurrIndex + 1;
+ break;
+
+ //
+ // char is space or other char
+ //
+ default:
+ GlyphOffset += GlyphWidth;
+ if (GlyphOffset >= BlockWidth) {
+ if (LastSpaceIndex > PrevCurrIndex) {
+ //
+ // LastSpaceIndex points to space inside current screen-line,
+ // restore to LastSpaceIndex
+ // (Otherwise the word is too long to fit one screen-line, just cut it)
+ //
+ CurrIndex = LastSpaceIndex;
+ GlyphWidth = LastSpaceGlyphWidth;
+ } else if (GlyphOffset > BlockWidth) {
+ //
+ // the word is too long to fit one screen-line and we don't get the chance
+ // of GlyphOffset == BlockWidth because GlyphWidth = 2
+ //
+ CurrIndex --;
+ }
+
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex + 1;
+ IndexArray[LineCount*3+2] = LineStartGlyphWidth;
+ LineStartGlyphWidth = GlyphWidth;
+ LineCount ++;
+ //
+ // Reset offset and save begin position of line
+ //
+ GlyphOffset = 0;
+ PrevCurrIndex = CurrIndex + 1;
+ }
+
+ //
+ // LastSpaceIndex: remember position of last space
+ //
+ if (StringPtr[CurrIndex] == CHAR_SPACE) {
+ LastSpaceIndex = CurrIndex;
+ LastSpaceGlyphWidth = GlyphWidth;
+ }
+ break;
+ }
+ }
+
+ if (GlyphOffset > 0) {
+ IndexArray[LineCount*3] = PrevCurrIndex;
+ IndexArray[LineCount*3+1] = CurrIndex;
+ IndexArray[LineCount*3+2] = GlyphWidth;
+ LineCount ++;
+ }
+
+ if (LineCount == 0) {
+ //
+ // in case we meet null string
+ //
+ IndexArray[0] = 0;
+ IndexArray[1] = 1;
+ //
+ // we assume null string's glyph width is 1
+ //
+ IndexArray[1] = 1;
+ LineCount ++;
+ }
+
+ VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0));
+ *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2);
+
+ for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) {
+ *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16)((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR);
+ StrnCpy (
+ *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1,
+ StringPtr + IndexArray[CurrIndex*3],
+ IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3]
+ );
+ }
+
+ if (IndexArray != NULL) {
+ FreePool (IndexArray);
+ }
+}
+
+VOID
+IfrToFormTag (
+ IN UINT8 OpCode,
+ IN EFI_TAG *TargetTag,
+ IN VOID *FormData,
+ EFI_VARIABLE_DEFINITION *VariableDefinitionsHead
+ )
+{
+ UINT16 TempValue;
+ CHAR16 *VariableName;
+ CHAR8 *AsciiString;
+ EFI_VARIABLE_DEFINITION *VariableDefinitions;
+ EFI_VARIABLE_DEFINITION *PreviousVariableDefinitions;
+ STATIC UINT16 VariableSize;
+ EFI_GUID Guid;
+ STATIC UINT16 CurrentVariable;
+ STATIC UINT16 CurrentVariable2;
+ UINTN Index;
+
+ switch (OpCode) {
+ case EFI_IFR_FORM_OP:
+ CopyMem (&TargetTag->Id, &((EFI_IFR_FORM *) FormData)->FormId, sizeof (UINT16));
+ CopyMem (&TargetTag->Text, &((EFI_IFR_FORM *) FormData)->FormTitle, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ if (VariableDefinitionsHead != NULL) {
+ VariableName = AllocateZeroPool (12);
+ ASSERT (VariableName != NULL);
+ CopyMem (VariableName, L"Setup", 12);
+ VariableDefinitionsHead->VariableName = VariableName;
+ VariableDefinitionsHead->VariableSize = VariableSize;
+ CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID));
+ }
+ break;
+
+ case EFI_IFR_SUBTITLE_OP:
+ TargetTag->NumberOfLines = 1;
+ CopyMem (&TargetTag->Text, &((EFI_IFR_SUBTITLE *) FormData)->SubTitle, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_TEXT_OP:
+ TargetTag->NumberOfLines = 1;
+ CopyMem (&TargetTag->Text, &((EFI_IFR_TEXT *) FormData)->Text, sizeof (UINT16));
+ CopyMem (&TargetTag->Help, &((EFI_IFR_TEXT *) FormData)->Help, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+
+ //
+ // To optimize the encoding size, certain opcodes have optional fields such as those
+ // inside the if() statement. If the encoded length is the complete size, then we
+ // know we have valid data encoded that we want to integrate
+ //
+ if (((EFI_IFR_TEXT *) FormData)->Header.Length == sizeof (EFI_IFR_TEXT)) {
+ //
+ // Text has no help associated with it, but in case there is a second entry due to
+ // dynamic/interactive flags being active, bring this data over.
+ //
+ CopyMem (&TargetTag->TextTwo, &((EFI_IFR_TEXT *) FormData)->TextTwo, sizeof (UINT16));
+ TargetTag->Flags = ((EFI_IFR_TEXT *) FormData)->Flags;
+ CopyMem (&TargetTag->Key, &((EFI_IFR_TEXT *) FormData)->Key, sizeof (UINT16));
+ }
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ CopyMem (&TargetTag->Text, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Option, sizeof (UINT16));
+ CopyMem (&TargetTag->Value, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Value, sizeof (UINT16));
+ TargetTag->Flags = ((EFI_IFR_ONE_OF_OPTION *) FormData)->Flags;
+ CopyMem (&TargetTag->Key, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Key, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ TargetTag->Flags = ((EFI_IFR_CHECKBOX *) FormData)->Flags;
+ TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ CopyMem (&TargetTag->Key, &((EFI_IFR_CHECKBOX *) FormData)->Key, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ TargetTag->Flags = ((EFI_IFR_NUMERIC *) FormData)->Flags;
+ CopyMem (&TargetTag->Key, &((EFI_IFR_NUMERIC *) FormData)->Key, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_STRING_OP:
+ //
+ // Convert EFI_IFR_STRING.MinSize and EFI_IFR_STRING.MaxSize to actual minimum and maximum bytes
+ // and store to EFI_TAG.Minimum and EFI_TAG.Maximum
+ //
+ TempValue = 0;
+ CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MinSize, sizeof (UINT8));
+ TempValue = (UINT16) (TempValue * 2);
+ CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16));
+
+ TempValue = 0;
+ CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MaxSize, sizeof (UINT8));
+ TempValue = (UINT16) (TempValue * 2);
+ CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16));
+ CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16));
+ TargetTag->Flags = (UINT8) (((EFI_IFR_STRING *) FormData)->Flags);
+ TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ CopyMem (&TargetTag->Key, &((EFI_IFR_STRING *) FormData)->Key, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ TempValue = 0;
+ CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MinSize, sizeof (UINT8));
+ TempValue = (UINT16) (TempValue * 2);
+ CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16));
+
+ TempValue = 0;
+ CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MaxSize, sizeof (UINT8));
+ TempValue = (UINT16) (TempValue * 2);
+ CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16));
+ CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16));
+ TargetTag->Flags = ((EFI_IFR_PASSWORD *) FormData)->Flags;
+ TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ CopyMem (&TargetTag->Key, &((EFI_IFR_PASSWORD *) FormData)->Key, sizeof (UINT16));
+ CopyMem (&TargetTag->Encoding, &((EFI_IFR_PASSWORD *) FormData)->Encoding, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_VARSTORE_OP:
+ //
+ // It should NEVER be NULL
+ //
+ if (VariableDefinitionsHead == NULL) {
+ break;
+ }
+
+ VariableDefinitions = VariableDefinitionsHead;
+
+ //
+ // Advance VariableDefinitions to the last entry
+ //
+ for (; VariableDefinitions != NULL; VariableDefinitions = VariableDefinitions->Next) {
+ PreviousVariableDefinitions = VariableDefinitions;
+ //
+ // If there is a variable with this GUID and ID already, we need to bail out
+ //
+ if (!CompareMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID)) &&
+ !CompareMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16))
+ ) {
+ return ;
+ }
+
+ if (VariableDefinitions->Next == NULL) {
+ break;
+ }
+ }
+ //
+ // If the last entry has a variable in it already, allocate a new entry and use it
+ //
+ if (VariableDefinitions->VariableName != NULL) {
+ VariableDefinitions->Next = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
+ ASSERT (VariableDefinitions->Next != NULL);
+ PreviousVariableDefinitions = VariableDefinitions;
+ VariableDefinitions = VariableDefinitions->Next;
+ VariableDefinitions->Previous = PreviousVariableDefinitions;
+ }
+ //
+ // Copy the Variable data to our linked list
+ //
+ CopyMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16));
+ CopyMem (&VariableDefinitions->VariableSize, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));
+ CopyMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID));
+
+ //
+ // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition
+ // due to it being variable sized. There are rules preventing it from being > 40 characters long and should
+ // be enforced by the compiler.
+ //
+ AsciiString = (CHAR8 *) (&((EFI_IFR_VARSTORE *) FormData)->Size);
+ AsciiString = AsciiString + 2;
+ VariableDefinitions->VariableName = AllocateZeroPool ((AsciiStrLen (AsciiString) + 1) * 2);
+ ASSERT (VariableDefinitions->VariableName != NULL);
+ for (Index = 0; AsciiString[Index] != 0; Index++) {
+ VariableDefinitions->VariableName[Index] = (CHAR16) AsciiString[Index];
+ }
+
+ VariableDefinitions->VariableName[Index] = 0;
+
+ //
+ // Propogate the tag information for this op-code
+ //
+ CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16));
+ CopyMem (&TargetTag->GuidValue, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&TargetTag->StorageWidth, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));
+ CopyMem (&TargetTag->Maximum, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16));
+ CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16));
+ CurrentVariable2 = CurrentVariable;
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
+ CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16));
+ CopyMem (
+ &TargetTag->VariableNumber2,
+ &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId,
+ sizeof (UINT16)
+ );
+ CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16));
+ CopyMem (&CurrentVariable2, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_REF_OP:
+ TargetTag->NumberOfLines = 1;
+ CopyMem (&TargetTag->Id, &((EFI_IFR_REF *) FormData)->FormId, sizeof (UINT16));
+ CopyMem (&TargetTag->Key, &((EFI_IFR_REF *) FormData)->Key, sizeof (UINT16));
+ CopyMem (&TargetTag->Text, &((EFI_IFR_REF *) FormData)->Prompt, sizeof (UINT16));
+ CopyMem (&TargetTag->Help, &((EFI_IFR_REF *) FormData)->Help, sizeof (UINT16));
+ TargetTag->Flags = ((EFI_IFR_REF *) FormData)->Flags;
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_ID_VAL *) FormData)->Value, sizeof (UINT16));
+ CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_VAL *) FormData)->QuestionId, sizeof (UINT16));
+ TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_VAL *) FormData)->Width;
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_VAR_VAL *) FormData)->Value, sizeof (UINT16));
+ CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_VAR_VAL *) FormData)->VariableId, sizeof (UINT16));
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId1, sizeof (UINT16));
+ CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId2, sizeof (UINT16));
+ TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_ID *) FormData)->Width;
+ TargetTag->VariableNumber = CurrentVariable;
+ TargetTag->VariableNumber = CurrentVariable2;
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_LIST *) FormData)->QuestionId, sizeof (UINT16));
+ CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_LIST *) FormData)->ListLength, sizeof (UINT16));
+ TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_LIST *) FormData)->Width;
+
+ TargetTag->IntList = AllocateZeroPool (TargetTag->Id2 * sizeof (UINT16));
+ ASSERT (TargetTag->IntList);
+
+ for (TempValue = 0; TempValue < TargetTag->Id2; TempValue++) {
+ CopyMem (
+ &TargetTag->IntList[TempValue],
+ &((EFI_IFR_EQ_ID_LIST *) FormData)->ValueList[TempValue],
+ sizeof (UINT16)
+ );
+ }
+
+ TargetTag->VariableNumber = CurrentVariable;
+ break;
+
+ case EFI_IFR_FORM_SET_OP:
+ CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) FormData)->NvDataSize, sizeof (UINT16));
+ CopyMem (&Guid, &((EFI_IFR_FORM_SET *) FormData)->Guid, sizeof (EFI_GUID));
+ //
+ // If there is a size specified in the formste, we will establish a "default" variable
+ //
+ if (VariableDefinitionsHead != NULL) {
+ VariableName = AllocateZeroPool (12);
+ ASSERT (VariableName != NULL);
+ CopyMem (VariableName, L"Setup", 12);
+ VariableDefinitionsHead->VariableName = VariableName;
+ VariableDefinitionsHead->VariableSize = VariableSize;
+ CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID));
+ }
+ break;
+
+ case EFI_IFR_END_FORM_SET_OP:
+ CurrentVariable = 0;
+ CurrentVariable2 = 0;
+ break;
+ }
+
+ return ;
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.c
new file mode 100644
index 0000000000..58698c82cd
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -0,0 +1,2224 @@
+/**@file
+ Entry and initialization module for the browser.
+
+Copyright (c) 2006 - 2007 Intel Corporation. <BR>
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
+ //
+ // Boot Manager
+ //
+ {
+ {
+ 0x847bc3fe,
+ 0xb974,
+ 0x446d,
+ {
+ 0x94,
+ 0x49,
+ 0x5a,
+ 0xd5,
+ 0x41,
+ 0x2e,
+ 0x99,
+ 0x3b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // Device Manager
+ //
+ {
+ {
+ 0x3ebfa8e6,
+ 0x511d,
+ 0x4b5b,
+ {
+ 0xa9,
+ 0x5f,
+ 0xfb,
+ 0x38,
+ 0x26,
+ 0xf,
+ 0x1c,
+ 0x27
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM Formset.
+ //
+ {
+ {
+ 0x642237c7,
+ 0x35d4,
+ 0x472d,
+ {
+ 0x83,
+ 0x65,
+ 0x12,
+ 0xe0,
+ 0xcc,
+ 0xf2,
+ 0x7a,
+ 0x22
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM File Explorer Formset.
+ //
+ {
+ {
+ 0x1f2d63e1,
+ 0xfebd,
+ 0x4dc7,
+ {
+ 0x9c,
+ 0xc5,
+ 0xba,
+ 0x2b,
+ 0x1c,
+ 0xef,
+ 0x9c,
+ 0x5b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+};
+
+STATIC
+EFI_STATUS
+InitializeBinaryStructures (
+ IN EFI_HII_HANDLE *Handle,
+ IN BOOLEAN UseDatabase,
+ IN EFI_IFR_PACKET *Packet,
+ IN UINT8 *NvMapOverride,
+ IN UINTN NumberOfIfrImages,
+ EFI_FILE_FORM_TAGS **FileFormTagsHead
+ );
+
+STATIC
+EFI_STATUS
+InitializeTagStructures (
+ IN EFI_IFR_BINARY *BinaryData,
+ OUT EFI_FILE_FORM_TAGS *FileFormTags
+ );
+
+STATIC
+UI_MENU_OPTION *
+DisplayHomePage (
+ IN UINTN NumberOfIfrImages,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ );
+
+STATIC
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_PROTOCOL *Hii,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_IFR_PACKET *Packet,
+ IN EFI_IFR_BINARY *BinaryData
+ );
+
+STATIC
+EFI_STATUS
+InstallPrint (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+SendForm (
+ IN EFI_FORM_BROWSER_PROTOCOL * This,
+ IN BOOLEAN UseDatabase,
+ IN EFI_HII_HANDLE * Handle,
+ IN UINTN HandleCount,
+ IN EFI_IFR_PACKET * Packet,
+ IN EFI_HANDLE CallbackHandle,
+ IN UINT8 *NvMapOverride,
+ IN EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT BOOLEAN *ResetRequired OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This is the routine which an external caller uses to direct the browser
+ where to obtain it's information.
+
+Arguments:
+
+ UseDatabase - If set to TRUE, then all information is retrieved from the HII database handle specified
+ If set to FALSE, then the passed in Packet and CallbackHandle is used and Handle is ignored
+
+ Handle - A pointer to an array of Handles. If HandleCount > 1 we display a list of the formsets for the handles specified
+
+ HandleCount - The number of Handles specified in Handle.
+
+ Packet - Valid only if UseDatabase is FALSE. Packet defines the pages being passed into
+ the browser. This is composed of IFR data as well as String information.
+
+ CallbackHandle - The handle which contains the calling driver's EFI_FORM_CALLBACK_PROTOCOL interface.
+
+ ScreenDimenions - This allows the browser to be called so that it occupies a portion of the physical screen instead of
+ dynamically determining the screen dimensions.
+
+ NvMapOverride - This buffer is used only when there is no NV variable to define the current settings and the caller
+ needs to provide to the browser the current settings for the "fake" NV variable. If used, no saving
+ of an NV variable will be possible. This parameter is also ignored if HandleCount > 1.
+
+Returns:
+
+--*/
+{
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_FILE_FORM_TAGS *FileFormTagsHead;
+ UI_MENU_OPTION *Selection;
+ UI_MENU_OPTION *AltSelection;
+ EFI_STATUS Status;
+ BOOLEAN Callback;
+ VOID *CallbackData;
+ EFI_HII_HANDLE BackupHandle;
+
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ gPreviousValue = AllocatePool (0x1000);
+ CallbackData = AllocatePool (0x10000);
+ ASSERT (gPreviousValue != NULL);
+ ASSERT (CallbackData != NULL);
+
+ do {
+ //
+ // Seed the dimensions in the global
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &gScreenDimensions.RightColumn,
+ &gScreenDimensions.BottomRow
+ );
+
+ if (ScreenDimensions != NULL) {
+ //
+ // Check local dimension vs. global dimension.
+ //
+ if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
+ (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Local dimension validation.
+ //
+ if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
+ (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
+ ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
+ (
+ (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
+ SCROLL_ARROW_HEIGHT *
+ 2 +
+ FRONT_PAGE_HEADER_HEIGHT +
+ FOOTER_HEIGHT +
+ 1
+ )
+ ) {
+ CopyMem (&gScreenDimensions, ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
+ gHelpBlockWidth = gOptionBlockWidth;
+ gPromptBlockWidth = gOptionBlockWidth;
+
+ //
+ // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
+ //
+ InitializeBrowserStrings ();
+
+ gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
+ gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
+ gResetRequired = FALSE;
+ gExitRequired = FALSE;
+ gSaveRequired = FALSE;
+ gNvUpdateRequired = FALSE;
+ gActiveIfr = 0;
+ gConsistencyId = 0;
+ gPriorMenuEntry = 0;
+ BackupHandle = *Handle;
+ gMenuRefreshHead = NULL;
+ ASSERT (CallbackData);
+ ZeroMem (CallbackData, 0x10000);
+
+ //
+ // We can recurse through this and might need to re-allocate this particular buffer
+ //
+ if (gPreviousValue == NULL) {
+ gPreviousValue = AllocatePool (0x1000);
+ ASSERT (gPreviousValue != NULL);
+ }
+
+ Callback = FALSE;
+ FormCallback = NULL;
+
+ if (CallbackHandle != NULL) {
+ //
+ // Retrieve the Callback protocol interface
+ //
+ Status = gBS->HandleProtocol (
+ CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (CallbackData);
+ return Status;;
+ }
+
+ Callback = TRUE;
+ }
+ //
+ // Initializes all the internal state structures for all IFR images in system
+ //
+ Status = InitializeBinaryStructures (Handle, UseDatabase, Packet, NvMapOverride, HandleCount, &FileFormTagsHead);
+
+ if (EFI_ERROR (Status)) {
+ FreePool (CallbackData);
+ return Status;
+ }
+ //
+ // Beginning of the Presentation of the Data
+ //
+ if (UseDatabase && (HandleCount > 1)) {
+ Selection = DisplayHomePage (HandleCount, FileFormTagsHead, CallbackData);
+ } else {
+ //
+ // If passing something specific, we know there is only one Ifr
+ //
+ Selection = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (Selection != NULL);
+ Selection->IfrNumber = 0;
+ Selection->Handle = Handle[0];
+ UiInitMenu ();
+ }
+
+ UiInitMenuList ();
+
+ if (UseDatabase && (HandleCount > 1)) {
+ if (Selection == NULL) {
+ FreePool (CallbackData);
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // Launch the setup browser with the user's selection information
+ //
+ AltSelection = SetupBrowser (Selection, Callback, FileFormTagsHead, CallbackData);
+
+ //
+ // If the caller cares about Reset status, we can return to the caller if something happened that required a reset
+ //
+ if (ResetRequired != NULL) {
+ *ResetRequired = gResetRequired;
+ }
+
+ if (Callback && (AltSelection != NULL)) {
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ AltSelection->ThisTag->Key,
+ CallbackData,
+ (EFI_HII_CALLBACK_PACKET **) &Packet
+ );
+ }
+ }
+
+ *Handle = BackupHandle;
+
+ if (EFI_ERROR (Status)) {
+ FreePool (CallbackData);
+ return Status;
+ }
+
+ if (Callback && (AltSelection == NULL)) {
+ FreePool (CallbackData);
+ return Status;
+ }
+
+ if (UseDatabase && (HandleCount > 1)) {
+ } else {
+
+ if (gBinaryDataHead->UnRegisterOnExit) {
+ Hii->RemovePack (Hii, Handle[0]);
+ }
+
+ if (Callback &&
+ ((AltSelection->ThisTag->SubClass == EFI_FRONT_PAGE_SUBCLASS) ||
+ (AltSelection->ThisTag->SubClass == EFI_SINGLE_USE_SUBCLASS))) {
+ //
+ // If this is the FrontPage, return after every selection
+ //
+ FreePool (Selection);
+ UiFreeMenu ();
+
+ //
+ // Clean up the allocated data buffers
+ //
+ FreeData (FileFormTagsHead, NULL, NULL);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ FreePool (CallbackData);
+ return EFI_SUCCESS;
+ }
+
+ FreePool (Selection);
+ UiFreeMenu ();
+
+ //
+ // Clean up the allocated data buffers
+ //
+ FreeData (FileFormTagsHead, NULL, NULL);
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ if (!Callback) {
+ FreePool (CallbackData);
+ return EFI_SUCCESS;
+ }
+ }
+
+ } while (!EFI_ERROR (Status));
+
+ FreePool (CallbackData);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeSetup (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initialize Setup
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_SUCCESS - Setup loaded.
+ other - Setup Error
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FORM_CONFIGURATION_DATA *FormData;
+ EFI_FORM_BROWSER_PROTOCOL *FormBrowser;
+ EFI_HANDLE Handle;
+ EFI_HII_PACKAGES *PackageList;
+
+ //
+ // There will be only one FormConfig in the system
+ // If there is another out there, someone is trying to install us
+ // again. Fail that scenario.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiFormBrowserProtocolGuid,
+ NULL,
+ (VOID **) &FormBrowser
+ );
+
+ gFirstIn = TRUE;
+
+ //
+ // If there was no error, assume there is an installation and fail to load
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ FormData = AllocatePool (sizeof (EFI_FORM_CONFIGURATION_DATA));
+
+ if (FormData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Fill in HII data
+ //
+ FormData->Signature = EFI_FORM_DATA_SIGNATURE;
+ FormData->FormConfig.SendForm = SendForm;
+ FormData->FormConfig.CreatePopUp = CreateDialog;
+
+ //
+ // There should only be one HII image
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &FormData->Hii
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Hii = FormData->Hii;
+
+ PackageList = PreparePackages (1, &gEfiFormBrowserProtocolGuid, SetupBrowserStrings);
+
+ Status = Hii->NewPack (Hii, PackageList, &gHiiHandle);
+
+ FreePool (PackageList);
+
+ //
+ // Install protocol interface
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiFormBrowserProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &FormData->FormConfig
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
+ ASSERT (BannerData != NULL);
+
+ Status = InstallPrint ();
+ return Status;
+}
+
+VOID
+GetQuestionHeader (
+ IN EFI_TAG *Tag,
+ IN UINT8 *RawFormSet,
+ IN UINT16 Index,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 CurrentVariable
+ )
+/*++
+
+Routine Description:
+ Initialize question tag's members.
+
+Arguments:
+ Tag - Pointer of the current EFI_TAG structure.
+ RawFormSet - Pointer of the formset raw data.
+ Index - Offset of the current opcode in the Ifr raw data.
+ FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
+ CurrentVariable - Current variable number.
+
+Returns:
+ None.
+--*/
+{
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+
+ Tag->NumberOfLines = 1;
+ Tag->VariableNumber = CurrentVariable;
+ CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
+ CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
+ CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
+ CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
+ CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
+
+ VariableDefinition = FileFormTags->VariableDefinitions;
+
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ //
+ // Have we found the correct variable for the request?
+ //
+ if (CurrentVariable == VariableDefinition->VariableId) {
+ if (VariableDefinition->VariableSize < (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
+ }
+
+ if (VariableDefinition->NvRamMap != NULL) {
+ //
+ // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
+ // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
+ //
+ if (Tag->StorageWidth == (UINT16) 1) {
+ CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
+ }
+
+ if (Tag->StorageWidth == (UINT16) 2) {
+ Index = (UINT16)
+ (
+ VariableDefinition->NvRamMap[Tag->StorageStart] +
+ (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
+ );
+ CopyMem (&Tag->Value, &Index, sizeof (UINT16));
+ }
+ } else {
+ Index = 0;
+ CopyMem (&Tag->Value, &Index, sizeof (UINT16));
+ }
+ break;
+ }
+ }
+}
+
+VOID
+GetNumericHeader (
+ IN EFI_TAG *Tag,
+ IN UINT8 *RawFormSet,
+ IN UINT16 Index,
+ IN UINT16 NumberOfLines,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 CurrentVariable
+ )
+/*++
+
+Routine Description:
+ Initialize numeric tag's members.
+
+Arguments:
+ Tag - Pointer of the current EFI_TAG structure.
+ RawFormSet - Pointer of the formset raw data.
+ Index - Offset of the current opcode in the Ifr raw data.
+ NumberOfLines - Number of lines this opcode occupied.
+ FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure.
+ CurrentVariable - Current variable number.
+
+Returns:
+ None.
+--*/
+{
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+
+ Tag->NumberOfLines = NumberOfLines;
+ Tag->VariableNumber = CurrentVariable;
+ CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
+ CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
+ CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
+ CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
+ CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
+ CopyMem (&Tag->Minimum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Minimum, sizeof (UINT16));
+ CopyMem (&Tag->Maximum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Maximum, sizeof (UINT16));
+ CopyMem (&Tag->Step, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Step, sizeof (UINT16));
+ CopyMem (&Tag->Default, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Default, sizeof (UINT16));
+ Tag->ResetRequired = (BOOLEAN) (((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+
+ VariableDefinition = FileFormTags->VariableDefinitions;
+
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ //
+ // Have we found the correct variable for the request?
+ //
+ if (CurrentVariable == VariableDefinition->VariableId) {
+ if (VariableDefinition->VariableSize <= (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
+ if (Tag->StorageWidth == 0) {
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + 2);
+ } else {
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
+ }
+ }
+
+ if (VariableDefinition->NvRamMap != NULL) {
+ //
+ // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
+ // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
+ //
+ if (Tag->StorageWidth == (UINT16) 1) {
+ CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
+ }
+
+ if (Tag->StorageWidth == (UINT16) 2) {
+ Index = (UINT16)
+ (
+ VariableDefinition->NvRamMap[Tag->StorageStart] +
+ (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
+ );
+ CopyMem (&Tag->Value, &Index, sizeof (UINT16));
+ }
+ } else {
+ CopyMem (&Tag->Value, &Tag->Default, sizeof (UINT16));
+ }
+ break;
+ }
+ }
+}
+
+VOID
+GetTagCount (
+ IN UINT8 *RawFormSet,
+ IN OUT UINT16 *NumberOfTags
+ )
+{
+ UINT16 Index;
+
+ //
+ // Assume on entry we are pointing to an OpCode - reasonably this should
+ // be a FormOp since the purpose is to count the tags in a particular Form.
+ //
+ for (Index = 0; RawFormSet[Index] != EFI_IFR_END_FORM_OP;) {
+ //
+ // If we encounter the end of a form set, bail out
+ //
+ if (RawFormSet[Index] == EFI_IFR_END_FORM_SET_OP) {
+ break;
+ }
+ //
+ // We treat date/time internally as three op-codes
+ //
+ if (RawFormSet[Index] == EFI_IFR_DATE_OP || RawFormSet[Index] == EFI_IFR_TIME_OP) {
+ *NumberOfTags = (UINT16) (*NumberOfTags + 3);
+ } else {
+ //
+ // Assume that we could have no more tags than op-codes
+ //
+ (*NumberOfTags)++;
+ }
+
+ Index = (UINT16) (Index + RawFormSet[Index + 1]);
+ }
+ //
+ // Increase the tag count by one so it is inclusive of the end_form_op
+ //
+ (*NumberOfTags)++;
+}
+
+STATIC
+VOID
+AddNextInconsistentTag (
+ IN OUT EFI_INCONSISTENCY_DATA **InconsistentTagsPtr
+ )
+/*++
+
+Routine Description:
+ Initialize the next inconsistent tag data and add it to the inconsistent tag list.
+
+Arguments:
+ InconsistentTagsPtr - Pointer of the inconsistent tag's pointer.
+
+Returns:
+ None.
+
+--*/
+{
+ EFI_INCONSISTENCY_DATA *PreviousInconsistentTags;
+ EFI_INCONSISTENCY_DATA *InconsistentTags;
+
+ InconsistentTags = *InconsistentTagsPtr;
+ //
+ // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
+ //
+ InconsistentTags->Next = AllocatePool (sizeof (EFI_INCONSISTENCY_DATA));
+ ASSERT (InconsistentTags->Next != NULL);
+
+ //
+ // Preserve current Tag entry
+ //
+ PreviousInconsistentTags = InconsistentTags;
+
+ InconsistentTags = InconsistentTags->Next;
+
+ //
+ // This will zero on the entry including the ->Next so I don't have to do it
+ //
+ ZeroMem (InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
+
+ //
+ // Point our Previous field to the previous entry
+ //
+ InconsistentTags->Previous = PreviousInconsistentTags;
+
+ *InconsistentTagsPtr = InconsistentTags;
+
+ return ;
+}
+
+STATIC
+EFI_STATUS
+InitializeTagStructures (
+ IN EFI_IFR_BINARY *BinaryData,
+ OUT EFI_FILE_FORM_TAGS *FileFormTags
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *RawFormSet;
+ UINT16 Index;
+ UINT16 QuestionIndex;
+ UINT16 NumberOfTags;
+ INT16 CurrTag;
+ UINT8 TagLength;
+ EFI_FORM_TAGS *FormTags;
+ EFI_FORM_TAGS *SavedFormTags;
+ EFI_INCONSISTENCY_DATA *InconsistentTags;
+ EFI_VARIABLE_DEFINITION *VariableDefinitions;
+ UINTN Count;
+ UINT16 Class;
+ UINT16 SubClass;
+ UINT16 TempValue;
+ UINT16 CurrentVariable;
+ UINT16 CurrentVariable2;
+
+ //
+ // Initialize some Index variable and Status
+ //
+ Count = 0;
+ Class = 0;
+ SubClass = 0;
+ CurrentVariable = 0;
+ CurrentVariable2 = 0;
+ QuestionIndex = 0;
+ NumberOfTags = 1;
+ Status = EFI_SUCCESS;
+ FormTags = &FileFormTags->FormTags;
+ FormTags->Next = NULL;
+ if (FileFormTags->InconsistentTags == NULL) {
+ InconsistentTags = NULL;
+ } else {
+ InconsistentTags = FileFormTags->InconsistentTags;
+ }
+
+ if (FileFormTags->VariableDefinitions == NULL) {
+ VariableDefinitions = NULL;
+ } else {
+ VariableDefinitions = FileFormTags->VariableDefinitions;
+ }
+ //
+ // RawFormSet now points to the beginning of the forms portion of
+ // the specific IFR Binary.
+ //
+ RawFormSet = (UINT8 *) BinaryData->FormBinary;
+
+ //
+ // Determine the number of tags for the first form
+ //
+ GetTagCount (&RawFormSet[0], &NumberOfTags);
+
+ SavedFormTags = FormTags;
+
+ if (FormTags->Tags != NULL) {
+ do {
+ //
+ // Advance FormTags to the last entry
+ //
+ for (; FormTags->Next != NULL; FormTags = FormTags->Next)
+ ;
+
+ //
+ // Walk through each of the tags and free the IntList allocation
+ //
+ for (Index = 0; Index < NumberOfTags; Index++) {
+ if (FormTags->Tags[Index].IntList != NULL) {
+ FreePool (FormTags->Tags[Index].IntList);
+ }
+ }
+
+ FreePool (FormTags->Tags);
+
+ ASSERT (FormTags->Next == NULL);
+
+ FormTags->Tags = NULL;
+
+ FormTags = SavedFormTags;
+
+ } while (FormTags->Next != NULL);
+ }
+
+ Index = 0;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (FormTags->Tags == NULL) {
+ //
+ // Allocate memory for our tags on the first form
+ //
+ FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
+ ASSERT (FormTags->Tags);
+ }
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags == NULL) {
+ //
+ // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure
+ //
+ InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA));
+ ASSERT (InconsistentTags != NULL);
+
+ FileFormTags->InconsistentTags = InconsistentTags;
+ }
+
+ ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG));
+
+ for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
+ //
+ // Operand = IFR OpCode
+ //
+ FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
+
+ //
+ // Assume for now 0 lines occupied by this OpCode
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 0;
+
+ FormTags->Tags[CurrTag].Class = Class;
+ FormTags->Tags[CurrTag].SubClass = SubClass;
+
+ //
+ // Determine the length of the Tag so we can later skip to the next tag in the form
+ //
+ TagLength = RawFormSet[Index + 1];
+ //
+ // get the length
+ //
+ // Operate on the Found OpCode
+ //
+ switch (RawFormSet[Index]) {
+
+ case EFI_IFR_FORM_OP:
+ //
+ // If there was no variable op-code defined, create a dummy entry for one
+ //
+ if (FileFormTags->VariableDefinitions == NULL) {
+ FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
+ ASSERT (FileFormTags->VariableDefinitions != NULL);
+ IfrToFormTag (
+ RawFormSet[Index],
+ &FormTags->Tags[CurrTag],
+ (VOID *) &RawFormSet[Index],
+ FileFormTags->VariableDefinitions
+ );
+ } else {
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ }
+ break;
+
+ case EFI_IFR_SUBTITLE_OP:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_REF_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ break;
+
+ case EFI_IFR_VARSTORE_OP:
+ if (FileFormTags->VariableDefinitions == NULL) {
+ VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
+ ASSERT (VariableDefinitions != NULL);
+ FileFormTags->VariableDefinitions = VariableDefinitions;
+ }
+
+ IfrToFormTag (
+ RawFormSet[Index],
+ &FormTags->Tags[CurrTag],
+ (VOID *) &RawFormSet[Index],
+ FileFormTags->VariableDefinitions
+ );
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16));
+ CurrentVariable2 = CurrentVariable;
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16));
+ CopyMem (
+ &CurrentVariable2,
+ &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId,
+ sizeof (UINT16)
+ );
+ break;
+
+ case EFI_IFR_END_FORM_OP:
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (FormTags->Next == NULL) {
+ //
+ // We just hit the end of a form. Let's allocate the ->Next structure
+ //
+ FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS));
+ ASSERT (FormTags->Next);
+ }
+
+ FormTags = FormTags->Next;
+ ZeroMem (FormTags, sizeof (EFI_FORM_TAGS));
+
+ //
+ // Reset the tag count to one
+ //
+ NumberOfTags = 1;
+
+ //
+ // Reset the CurrTag value (it will be incremented, after this case statement
+ // so set to a negative one so that we get the desired effect.) Fish can beat me later.
+ //
+ CurrTag = -1;
+
+ //
+ // Determine the number of tags after this form. If this is the last
+ // form, then we will count the endformset and preserve that information
+ // in the tag structure.
+ //
+ GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags);
+
+ //
+ // Allocate memory for our tags
+ //
+ FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
+ ASSERT (FormTags->Tags);
+ break;
+
+ //
+ // Two types of tags constitute the One Of question: a one-of header and
+ // several one-of options.
+ //
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_ORDERED_LIST_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
+
+ //
+ // Store away the CurrTag since what follows will be the answer that we
+ // need to place into the appropriate location in the tag array
+ //
+ //
+ // record for setting default later
+ //
+ QuestionIndex = (UINT16) CurrTag;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags;
+ CopyMem (
+ &FormTags->Tags[QuestionIndex].Key,
+ &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key,
+ sizeof (UINT16)
+ );
+ FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ break;
+
+ case EFI_IFR_DATE_OP:
+ //
+ // Date elements come in as a Year, Month, Day. We need to process them as a country-based
+ // Order. It is much easier to do it here than anywhere else.
+ //
+ // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2
+ //
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag],
+ RawFormSet,
+ (UINT16) (Index + TagLength),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index];
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag + 1],
+ RawFormSet,
+ (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index];
+ GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+
+ CurrTag = (INT16) (CurrTag + 2);
+
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = RawFormSet[Index + 1];
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = RawFormSet[Index + 1];
+ break;
+
+ case EFI_IFR_TIME_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable);
+
+ if (Count == 2) {
+ //
+ // Override the GetQuestionHeader information - date/time are treated very differently
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 1;
+ Count = 0;
+ } else {
+ //
+ // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
+ // associated with them, and the third has 1 line to allow to space beyond the choice.
+ //
+ Count++;
+ }
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+ case EFI_IFR_GRAYOUT_IF_OP:
+ InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
+ gConsistencyId++;
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_FORM_SET_OP:
+ CopyMem (
+ &FormTags->Tags[CurrTag].GuidValue,
+ &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid,
+ sizeof (EFI_GUID)
+ );
+ CopyMem (
+ &FormTags->Tags[CurrTag].CallbackHandle,
+ &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle,
+ sizeof (EFI_PHYSICAL_ADDRESS)
+ );
+ CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8));
+ CopyMem (
+ &FormTags->Tags[CurrTag].SubClass,
+ &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass,
+ sizeof (UINT8)
+ );
+ CopyMem (
+ &FormTags->Tags[CurrTag].NvDataSize,
+ &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize,
+ sizeof (UINT16)
+ );
+ Class = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class;
+ SubClass = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass;
+ //
+ // If the formset has a size value, that means someone must be using this, so create a variable
+ // We also shall reserve the formid of 0 for this specific purpose.
+ //
+ if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) {
+ FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
+ ASSERT (FileFormTags->VariableDefinitions != NULL);
+ IfrToFormTag (
+ RawFormSet[Index],
+ &FormTags->Tags[CurrTag],
+ (VOID *) &RawFormSet[Index],
+ FileFormTags->VariableDefinitions
+ );
+ } else {
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+ }
+ break;
+
+ case EFI_IFR_BANNER_OP:
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ TempValue = 0;
+ CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8));
+ //
+ // If this is the special timeout value, we will dynamically figure out where to put it
+ // Also the least significant byte refers to the TimeOut desired.
+ //
+ if (TempValue == EFI_IFR_BANNER_TIMEOUT) {
+ CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16));
+ if (FrontPageTimeOutValue != (INT16) -1) {
+ CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16));
+ }
+ break;
+ }
+
+ CopyMem (
+ &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][
+ ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment],
+ &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title,
+ sizeof (STRING_REF)
+ );
+ }
+ break;
+
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ CopyMem (
+ &FormTags->Tags[CurrTag].Text,
+ &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup,
+ sizeof (UINT16)
+ );
+ gConsistencyId++;
+
+ InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
+ CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16));
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+
+ InconsistentTags->VariableNumber = CurrentVariable;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+
+ InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode;
+ CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
+ CopyMem (
+ &InconsistentTags->QuestionId1,
+ &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId,
+ sizeof (UINT16)
+ );
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+ InconsistentTags->ConsistencyId = gConsistencyId;
+ FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
+
+ InconsistentTags->VariableNumber = CurrentVariable;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+
+ InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode;
+ CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
+ CopyMem (
+ &InconsistentTags->QuestionId1,
+ &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId,
+ sizeof (UINT16)
+ );
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+ InconsistentTags->ConsistencyId = gConsistencyId;
+ FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
+
+ InconsistentTags->VariableNumber = CurrentVariable;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+
+ InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode;
+ CopyMem (
+ &InconsistentTags->QuestionId1,
+ &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1,
+ sizeof (UINT16)
+ );
+ CopyMem (
+ &InconsistentTags->QuestionId2,
+ &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2,
+ sizeof (UINT16)
+ );
+
+ InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
+ InconsistentTags->ConsistencyId = gConsistencyId;
+ FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
+
+ InconsistentTags->VariableNumber = CurrentVariable;
+ InconsistentTags->VariableNumber2 = CurrentVariable2;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_GT_OP:
+ case EFI_IFR_GE_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode;
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+
+ //
+ // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but
+ // have no coresponding id. The examination of id is needed by evaluating boolean expression.
+ //
+ if (RawFormSet[Index] == EFI_IFR_TRUE_OP ||
+ RawFormSet[Index] == EFI_IFR_FALSE_OP) {
+ InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE - 1;
+ } else {
+ InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
+ }
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+ InconsistentTags->ConsistencyId = gConsistencyId;
+ FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+
+ InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode;
+ CopyMem (
+ &InconsistentTags->QuestionId1,
+ &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId,
+ sizeof (UINT16)
+ );
+ CopyMem (
+ &InconsistentTags->ListLength,
+ &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength,
+ sizeof (UINT16)
+ );
+ InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList;
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth;
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+ InconsistentTags->ConsistencyId = gConsistencyId;
+ FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_END_IF_OP:
+ InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode;
+
+ //
+ // Since this op-code doesn't use the next field(s), initialize them with something invalid.
+ // Unfortunately 0 is a valid offset value for a QuestionId
+ //
+ InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
+ InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
+
+ //
+ // Test for an allocated buffer. If already allocated this is due to having called this routine
+ // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize
+ // the tag structure with current values from the NV
+ //
+ if (InconsistentTags->Next == NULL) {
+ AddNextInconsistentTag (&InconsistentTags);
+ break;
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ break;
+
+ case EFI_IFR_END_ONE_OF_OP:
+ break;
+
+ default:
+ break;
+ }
+ //
+ // End of switch
+ //
+ // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
+ //
+ Index = (UINT16) (Index + TagLength);
+ }
+ //
+ // End of Index
+ //
+ // When we eventually exit, make sure we mark the last tag with an op-code
+ //
+ FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
+
+ IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
+
+ //
+ // Place this as an end of the database marker
+ //
+ InconsistentTags->Operand = 0xFF;
+
+ //
+ // This is the Head of the linked list of pages. Each page is an array of tags
+ //
+ FormTags = &FileFormTags->FormTags;
+ InconsistentTags = FileFormTags->InconsistentTags;
+
+ for (; InconsistentTags->Operand != 0xFF;) {
+ if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) {
+ //
+ // Search the tags for the tag which corresponds to this ID
+ //
+ for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
+ //
+ // If we hit the end of a form, go to the next set of Tags.
+ // Remember - EndFormSet op-codes sit on their own page after an end form.
+ //
+ if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
+ //
+ // Reset the CurrTag value (it will be incremented, after this case statement
+ // so set to a negative one so that we get the desired effect.) Fish can beat me later.
+ //
+ CurrTag = -1;
+ FormTags = FormTags->Next;
+ continue;
+ }
+
+ if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) {
+ FormTags->Tags[CurrTag].Consistency++;
+ }
+ }
+ }
+
+ FormTags = &FileFormTags->FormTags;
+
+ if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) {
+ //
+ // Search the tags for the tag which corresponds to this ID
+ //
+ for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
+ //
+ // If we hit the end of a form, go to the next set of Tags.
+ // Remember - EndFormSet op-codes sit on their own page after an end form.
+ //
+ if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
+ //
+ // Reset the CurrTag value (it will be incremented, after this case statement
+ // so set to a negative one so that we get the desired effect.) Fish can beat me later.
+ //
+ CurrTag = -1;
+ FormTags = FormTags->Next;
+ continue;
+ }
+
+ if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) {
+ FormTags->Tags[CurrTag].Consistency++;
+ }
+ }
+ }
+
+ InconsistentTags = InconsistentTags->Next;
+ }
+
+ return Status;
+}
+
+VOID
+InitPage (
+ VOID
+ )
+{
+ CHAR16 *HomePageString;
+ CHAR16 *HomeEscapeString;
+
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ HomePageString = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle);
+ HomeEscapeString = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ //
+ // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);
+ //
+ PrintStringAt (
+ (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2,
+ 1,
+ HomePageString
+ );
+ PrintAt (
+ gScreenDimensions.LeftColumn + 2,
+ gScreenDimensions.BottomRow - 3,
+ (CHAR16 *) L"%c%c%s",
+ ARROW_UP,
+ ARROW_DOWN,
+ gMoveHighlight
+ );
+ PrintAt (
+ gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,
+ gScreenDimensions.BottomRow - 3,
+ (CHAR16 *) L" %s",
+ HomeEscapeString
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ FreePool (HomeEscapeString);
+ FreePool (HomePageString);
+
+ return ;
+}
+
+CHAR16 *
+GetToken (
+ IN STRING_REF Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+/*++
+
+Routine Description:
+
+ Get the string based on the TokenID and HII Handle.
+
+Arguments:
+
+ Token - The Token ID.
+ HiiHandle - Handle of Ifr to be fetched.
+
+Returns:
+
+ The output string.
+
+--*/
+{
+ CHAR16 *Buffer;
+ UINTN BufferLength;
+ EFI_STATUS Status;
+
+ //
+ // Set default string size assumption at no more than 256 bytes
+ //
+ BufferLength = 0x100;
+
+ Buffer = AllocateZeroPool (BufferLength);
+ ASSERT (Buffer != NULL);
+
+ Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Free the old pool
+ //
+ FreePool (Buffer);
+
+ //
+ // Allocate new pool with correct value
+ //
+ Buffer = AllocatePool (BufferLength);
+ ASSERT (Buffer != NULL);
+
+ Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
+
+ if (!EFI_ERROR (Status)) {
+ return Buffer;
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Buffer;
+}
+
+STATIC
+EFI_STATUS
+PopulateHomePage (
+ IN UINTN NumberOfIfrImages,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_IFR_BINARY *IfrBinary;
+ CHAR16 *StringPtr;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_FORM_TAGS LocalTags;
+
+ FileFormTags = FileFormTagsHead;
+
+ UiInitMenu ();
+
+ Status = EFI_SUCCESS;
+
+ //
+ // If there are no images
+ //
+ if (NumberOfIfrImages == 0) {
+ Status = EFI_NO_MEDIA;
+ return Status;
+ }
+ //
+ // IfrBinary points to the beginning of the Binary data linked-list
+ //
+ IfrBinary = gBinaryDataHead;
+
+ //
+ // Print the entries which were in the default language.
+ //
+ for (Index = 0; Index < NumberOfIfrImages; Index++) {
+ LocalTags = FileFormTags->FormTags;
+
+ //
+ // Populate the Menu
+ //
+ StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);
+
+ //
+ // If the default language doesn't exist, don't add a menu option yet
+ //
+ if (StringPtr[0] != CHAR_NULL) {
+ //
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
+ // it in UiFreeMenu.
+ //
+ UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);
+ }
+ //
+ // Advance to the next HII handle
+ //
+ IfrBinary = IfrBinary->Next;
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ return Status;
+}
+
+STATIC
+UI_MENU_OPTION *
+DisplayHomePage (
+ IN UINTN NumberOfIfrImages,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UI_MENU_OPTION *Selection;
+
+ //
+ // This prints the basic home page template which the user sees
+ //
+ InitPage ();
+
+ Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);
+
+ if (EFI_ERROR (Status)) {
+ Selection = NULL;
+ return Selection;
+ }
+
+ Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
+
+ return Selection;
+}
+
+STATIC
+EFI_STATUS
+InitializeBinaryStructures (
+ IN EFI_HII_HANDLE *Handle,
+ IN BOOLEAN UseDatabase,
+ IN EFI_IFR_PACKET *Packet,
+ IN UINT8 *NvMapOverride,
+ IN UINTN NumberOfIfrImages,
+ OUT EFI_FILE_FORM_TAGS **FileFormTagsHead
+ )
+{
+ UINTN HandleIndex;
+ EFI_STATUS Status;
+ EFI_IFR_BINARY *BinaryData;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ UINTN SizeOfNvStore;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_VARIABLE_DEFINITION *OverrideDefinition;
+ VOID *NvMap;
+ UINTN NvMapSize;
+ EFI_HII_VARIABLE_PACK_LIST *NvMapListHead;
+ EFI_HII_VARIABLE_PACK_LIST *NvMapListNode;
+
+ //
+ // Initialize some variables to avoid warnings
+ //
+ BinaryData = NULL;
+ *FileFormTagsHead = NULL;
+ FileFormTags = NULL;
+ gBinaryDataHead = NULL;
+ Status = EFI_SUCCESS;
+ FormCallback = NULL;
+ NvMap = NULL;
+ NvMapSize = 0;
+
+ if (NumberOfIfrImages > 1) {
+ NvMapOverride = NULL;
+ }
+
+ for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) {
+ //
+ // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
+ //
+ if ((BinaryData == NULL) || (FileFormTags == NULL)) {
+ //
+ // Allocate memory for our Binary Data
+ //
+ BinaryData = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
+ ASSERT (BinaryData);
+
+ //
+ // Preserve the Head of what will be a linked-list.
+ //
+ gBinaryDataHead = BinaryData;
+ gBinaryDataHead->Next = NULL;
+
+ if (UseDatabase) {
+ Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
+ } else {
+ Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
+ }
+ //
+ // Allocate memory for our File Form Tags
+ //
+ FileFormTags = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
+ ASSERT (FileFormTags);
+
+ //
+ // Preserve the Head of what will be a linked-list.
+ //
+ *FileFormTagsHead = FileFormTags;
+ (*FileFormTagsHead)->NextFile = NULL;
+
+ } else {
+ //
+ // Allocate memory for our Binary Data linked-list
+ // Each handle represents a Binary and we will store that data away.
+ //
+ BinaryData->Next = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
+ ASSERT (BinaryData->Next);
+
+ BinaryData = BinaryData->Next;
+ BinaryData->Next = NULL;
+
+ if (UseDatabase) {
+ Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
+ } else {
+ Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Allocate memory for our FileFormTags linked-list
+ // Each allocation reserves handle represents a Binary and we will store that data away.
+ //
+ FileFormTags->NextFile = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
+ ASSERT (FileFormTags->NextFile);
+
+ FileFormTags = FileFormTags->NextFile;
+ }
+ //
+ // endif
+ //
+ // Tag Structure Initialization
+ //
+ Status = InitializeTagStructures (BinaryData, FileFormTags);
+
+ VariableDefinition = FileFormTags->VariableDefinitions;
+
+ //
+ // Allocate memory for our NVRAM Maps for all of our variables
+ //
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ //
+ // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
+ // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
+ //
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize);
+
+ //
+ // In the case where a file has no "real" NV data, we should pad the buffer accordingly
+ //
+ if (VariableDefinition->VariableSize == 0) {
+ if (VariableDefinition->VariableFakeSize != 0) {
+ VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
+ ASSERT (VariableDefinition->NvRamMap != NULL);
+ }
+ } else {
+ VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
+ ASSERT (VariableDefinition->NvRamMap != NULL);
+ }
+
+ if (VariableDefinition->VariableFakeSize != 0) {
+ VariableDefinition->FakeNvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
+ ASSERT (VariableDefinition->FakeNvRamMap != NULL);
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ //
+ // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
+ // information as the information that we pass back and forth. NOTE that callbacks that are initiated will only have the
+ // NVRAM data refreshed based on the op-code that initiated the callback. In other words, we will pass to the caller a single
+ // NVRAM map for a single variable based on the op-code that the user selected.
+ //
+ if (NvMapOverride != NULL) {
+ VariableDefinition = FileFormTags->VariableDefinitions;
+ OverrideDefinition = ((EFI_VARIABLE_DEFINITION *) NvMapOverride);
+
+ //
+ // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
+ //
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ if ((!CompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) {
+ if (VariableDefinition->VariableSize != 0) {
+ CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize);
+ } else {
+ CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize);
+ }
+ break;
+ } else {
+ VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap;
+ }
+ //
+ // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
+ //
+ ASSERT (OverrideDefinition->Next);
+ OverrideDefinition = OverrideDefinition->Next;
+ }
+ } else {
+ VariableDefinition = FileFormTags->VariableDefinitions;
+
+ //
+ // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified
+ //
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ SizeOfNvStore = VariableDefinition->VariableSize;
+
+ //
+ // Getting the NvStore and placing it into our Global Data
+ //
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
+ Status = FormCallback->NvRead (
+ FormCallback,
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ } else {
+ Status = gRT->GetVariable (
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is a variable that exists already and it is larger than what we calculated the
+ // storage needs to be, we must assume the variable size from GetVariable is correct and not
+ // allow the truncation of the variable. It is very possible that the user who created the IFR
+ // we are cracking is not referring to a variable that was in a previous map, however we cannot
+ // allow it's truncation.
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
+ //
+ VariableDefinition->VariableSize = (UINT16) SizeOfNvStore;
+
+ //
+ // Free the buffer that was allocated that was too small
+ //
+ FreePool (VariableDefinition->NvRamMap);
+ FreePool (VariableDefinition->FakeNvRamMap);
+
+ VariableDefinition->NvRamMap = AllocateZeroPool (SizeOfNvStore);
+ VariableDefinition->FakeNvRamMap = AllocateZeroPool (SizeOfNvStore + VariableDefinition->VariableFakeSize);
+ ASSERT (VariableDefinition->NvRamMap);
+ ASSERT (VariableDefinition->FakeNvRamMap);
+
+ if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
+ Status = FormCallback->NvRead (
+ FormCallback,
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ } else {
+ Status = gRT->GetVariable (
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ }
+ }
+ //
+ // if the variable was not found, we will retrieve default values
+ //
+ if (Status == EFI_NOT_FOUND) {
+
+ if (0 == CompareMem (VariableDefinition->VariableName, L"Setup", 10)) {
+
+ NvMapListHead = NULL;
+
+ Status = Hii->GetDefaultImage (Hii, Handle[HandleIndex], EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
+
+ if (!EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (NULL != NvMapListHead);
+
+ NvMapListNode = NvMapListHead;
+
+ while (NULL != NvMapListNode) {
+ if (VariableDefinition->VariableId == NvMapListNode->VariablePack->VariableId) {
+ NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
+ NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
+ break;
+ }
+ NvMapListNode = NvMapListNode->NextVariablePack;
+ }
+
+ //
+ // Free the buffer that was allocated.
+ //
+ FreePool (VariableDefinition->NvRamMap);
+ FreePool (VariableDefinition->FakeNvRamMap);
+
+ //
+ // Allocate, copy the NvRamMap.
+ //
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize - VariableDefinition->VariableSize);
+ VariableDefinition->VariableSize = (UINT16) NvMapSize;
+ VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + VariableDefinition->VariableSize);
+
+ VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
+ VariableDefinition->FakeNvRamMap = AllocateZeroPool (NvMapSize + VariableDefinition->VariableFakeSize);
+
+ CopyMem (VariableDefinition->NvRamMap, NvMap, NvMapSize);
+ FreePool (NvMapListHead);
+ }
+
+ }
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ InitializeTagStructures (BinaryData, FileFormTags);
+ }
+ //
+ // endfor
+ //
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_PROTOCOL *Hii,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_IFR_PACKET *Packet,
+ IN OUT EFI_IFR_BINARY *BinaryData
+ )
+/*++
+
+Routine Description:
+ Fetch the Ifr binary data.
+
+Arguments:
+ Hii - Point to HII protocol.
+ HiiHandle - Handle of Ifr to be fetched.
+ Packet - Pointer to IFR packet.
+ BinaryData - Buffer to copy the string into
+
+Returns:
+ Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGES *PackageList;
+ UINTN BufferSize;
+ VOID *Buffer;
+ UINT8 *RawFormBinary;
+ EFI_IFR_FORM_SET *FormOp;
+ UINT16 Index;
+ UINT16 Index2;
+ UINT16 TitleToken;
+
+ //
+ // Initialize the TitleToken to 0 just in case not found
+ //
+ TitleToken = 0;
+
+ //
+ // Try for a 32K Buffer
+ //
+ BufferSize = 0x8000;
+
+ //
+ // Allocate memory for our Form binary
+ //
+ Buffer = AllocateZeroPool (BufferSize);
+ ASSERT (Buffer);
+
+ if (Packet == NULL) {
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ FreePool (Buffer);
+
+ //
+ // Allocate memory for our Form binary
+ //
+ Buffer = AllocatePool (BufferSize);
+ ASSERT (Buffer);
+
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
+ }
+ } else {
+ //
+ // Copies the data to local usable buffer
+ //
+ CopyMem (Buffer, Packet->IfrData, Packet->IfrData->Header.Length);
+
+ //
+ // Register the string data with HII
+ //
+ PackageList = PreparePackages (2, NULL, Packet->IfrData, Packet->StringData);
+
+ Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
+
+ FreePool (PackageList);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // We now have the IFR binary in our Buffer
+ //
+ BinaryData->IfrPackage = Buffer;
+ RawFormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
+ BinaryData->FormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
+ BinaryData->Handle = HiiHandle;
+
+ //
+ // If a packet was passed in, remove the string data when exiting.
+ //
+ if (Packet != NULL) {
+ BinaryData->UnRegisterOnExit = TRUE;
+ } else {
+ BinaryData->UnRegisterOnExit = FALSE;
+ }
+ //
+ // Walk through the FormSet Opcodes looking for the FormSet opcode
+ // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet.
+ //
+ for (Index = 0; RawFormBinary[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ FormOp = (EFI_IFR_FORM_SET *) &RawFormBinary[Index];
+ Index = (UINT16) (Index + FormOp->Header.Length);
+
+ if (FormOp->Header.OpCode == EFI_IFR_FORM_SET_OP) {
+ TitleToken = FormOp->FormSetTitle;
+ //
+ // If displaying FrontPage - set the flag signifying it
+ //
+ switch (FormOp->SubClass) {
+ case EFI_FRONT_PAGE_SUBCLASS:
+ FrontPageHandle = HiiHandle;
+
+ default:
+ gClassOfVfr = FormOp->SubClass;
+ }
+ //
+ // Match GUID to find out the function key setting. If match fail, use the default setting.
+ //
+ for (Index2 = 0; Index2 < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index2++) {
+ if (CompareGuid ((EFI_GUID *)(UINTN)&FormOp->Guid, &(gFunctionKeySettingTable[Index2].FormSetGuid))) {
+ //
+ // Update the function key setting.
+ //
+ gFunctionKeySetting = gFunctionKeySettingTable[Index2].KeySetting;
+ //
+ // Function key prompt can not be displayed if the function key has been disabled.
+ //
+ if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
+ gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
+ gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
+ gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
+ gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+ }
+ }
+ }
+ }
+
+ BinaryData->TitleToken = TitleToken;
+
+ return Status;
+}
+
+EFI_HANDLE PrintHandle = NULL;
+EFI_PRINT_PROTOCOL mPrintProtocol = { UnicodeVSPrint };
+
+STATIC
+EFI_STATUS
+InstallPrint (
+ VOID
+ )
+{
+ return gBS->InstallProtocolInterface (
+ &PrintHandle,
+ &gEfiPrintProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrintProtocol
+ );
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.h b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.h
new file mode 100644
index 0000000000..6cfcf68c3a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -0,0 +1,508 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Setup.h
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#ifndef _SETUP_H
+#define _SETUP_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+extern UINT8 SetupBrowserStrings[];
+
+//
+// Screen definitions
+//
+#define BANNER_HEIGHT 4
+#define BANNER_COLUMNS 3
+
+#define FRONT_PAGE_HEADER_HEIGHT 4
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
+#define LEFT_SKIPPED_COLUMNS 4
+#define FOOTER_HEIGHT 4
+#define STATUS_BAR_HEIGHT 1
+#define SCROLL_ARROW_HEIGHT 1
+#define POPUP_PAD_SPACE_COUNT 5
+#define POPUP_FRAME_WIDTH 2
+
+
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
+#define EFI_FRONT_PAGE_SUBCLASS 0x02
+#define EFI_SINGLE_USE_SUBCLASS 0x03 // Used to display a single entity and then exit
+//
+// Definition for function key setting
+//
+#define NONE_FUNCTION_KEY_SETTING 0
+#define DEFAULT_FUNCTION_KEY_SETTING (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)
+
+#define FUNCTION_ONE (1 << 0)
+#define FUNCTION_TWO (1 << 1)
+#define FUNCTION_NINE (1 << 2)
+#define FUNCTION_TEN (1 << 3)
+
+typedef struct {
+ EFI_GUID FormSetGuid;
+ UINTN KeySetting;
+} FUNCTIION_KEY_SETTING;
+
+//
+// Character definitions
+//
+#define CHAR_SPACE 0x0020
+#define UPPER_LOWER_CASE_OFFSET 0x20
+
+//
+// Time definitions
+//
+#define ONE_SECOND 10000000
+
+//
+// Display definitions
+//
+#define LEFT_HYPER_DELIMITER L'<'
+#define RIGHT_HYPER_DELIMITER L'>'
+
+#define LEFT_ONEOF_DELIMITER L'<'
+#define RIGHT_ONEOF_DELIMITER L'>'
+
+#define LEFT_NUMERIC_DELIMITER L'['
+#define RIGHT_NUMERIC_DELIMITER L']'
+
+#define LEFT_CHECKBOX_DELIMITER L"["
+#define RIGHT_CHECKBOX_DELIMITER L"]"
+
+#define CHECK_ON L"X"
+#define CHECK_OFF L" "
+
+#define TIME_SEPARATOR L':'
+#define DATE_SEPARATOR L'/'
+
+#define YES_ANSWER L'Y'
+#define NO_ANSWER L'N'
+
+//
+// Up to how many lines does the ordered list display
+//
+#define ORDERED_LIST_SIZE 4
+
+//
+// This is the Input Error Message
+//
+#define INPUT_ERROR 1
+
+//
+// This is the NV RAM update required Message
+//
+#define NV_UPDATE_REQUIRED 2
+
+//
+// Refresh the Status Bar with flags
+//
+#define REFRESH_STATUS_BAR 0xff
+
+//
+// This width is basically the sum of the prompt and option widths
+//
+#define QUESTION_BLOCK_WIDTH 50
+
+//
+// Width of the Language Description (Using ISO-639-2 3 ASCII letter standard)
+//
+#define LANG_DESC_WIDTH 3
+
+//
+// Maximum Number of Binaries we can see
+//
+#define MAX_BINARIES 255
+
+//
+// Invalid Handle
+//
+#define EFI_HII_INVALID_HANDLE 0xFFFF
+
+//
+// Invalid Offset Value
+//
+#define INVALID_OFFSET_VALUE 0xFFFF
+
+struct StringPart {
+ struct StringPart *Next;
+ CHAR8 String[QUESTION_BLOCK_WIDTH + 2];
+};
+
+//
+// The tag definition defines the data associated with a tag (an operation
+// in the IFR lingo). The tag is thus a modified union of all the data
+// required for tags. The user should be careful to only rely upon information
+// relevant to that tag as the contents of other fields is undefined.
+//
+// The intent here is for this to be all of the data associated with a particular tag.
+// Some of this data is extracted from the IFR and left alone. Other data will be derived
+// when the page is selected (since that's the first time we really know what language the
+// page is to be displayed in) and still other data will vary based on the selection.
+// If you'd like to consider alternatives, let me know. This structure has grown somewhat organically.
+// It gets a new item stuffed in it when a new item is needed. When I finally decided I needed the
+// StringPart structure, items got added here, for example.
+//
+typedef struct {
+ UINT8 Operand; // The operand (first byte) of the variable length tag.
+ EFI_GUID GuidValue; // Primarily for FormSet data
+ EFI_PHYSICAL_ADDRESS CallbackHandle;
+ UINT16 Class;
+ UINT16 SubClass;
+ UINT16 NumberOfLines; // The number of lines the tag takes up on the page. Adjusted when we display the page as it can change from language to language.
+ UINT16 PageLine;
+ UINT16 PageColumn;
+ UINT16 OptionWidth; // The option can be wider than the column usually associated with options. This is the width on the last option line
+ STRING_REF Text; // Used for title, subtitle, prompt, etc. This is the string token associated with the string. This token is language independent.
+ STRING_REF TextTwo; // Used for title, subtitle, prompt, etc. This is the string token associated with the string. This token is language independent.
+ STRING_REF Help; // Null means no help Same as above but for languages.
+ UINT16 Consistency; // Do we need to check this opcode against consistency? If > 0, yes.
+ UINT16 Id;
+ UINT16 Id2; // The questions (mainly) have identifiers associated with them. These are filled in from the IFR tags and used by e.g. the RPN calculations. (com1 is set to, versus com2 is set to)
+ //
+ // These are the three values that are created to determine where in the variable the data is stored. This should, in general,
+ // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess.
+ //
+ UINT16 StorageStart;
+ //
+ // These are the three values that are created to determine where in the variable the data is stored. This should, in general,
+ // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess.
+ //
+ UINT8 StorageWidth;
+ //
+ // These are the three values that are created to determine where in the variable the data is stored. This should, in general,
+ // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess.
+ //
+ UINT16 Value;
+ //
+ // (Default or current)
+ //
+ UINT8 Flags;
+ UINT16 Key;
+ //
+ // Used to preserve a value during late consistency checking
+ //
+ UINT16 OldValue;
+ UINT16 Minimum;
+ UINT16 Maximum;
+ UINT16 Step;
+ UINT16 Default;
+ UINT16 NvDataSize;
+ UINT16 ConsistencyId;
+ BOOLEAN GrayOut;
+ BOOLEAN Suppress;
+ UINT16 Encoding; // Data from the tags. The first three are used by the numeric input. Encoding is used by the password stuff (a placeholder today - may go away).
+ UINT16 *IntList; // List of the values possible for a list question
+ //
+ // The string is obtained from the string list and formatted into lines and the lines are held in this linked list.
+ // If we have more than a screen's worth of items, we will end up with cases where we have to display the last couple
+ // lines of a tag's string above the currently selected one, or, display a few lines of a tag at the bottom of a screen.
+ //
+ struct StringPart *StringList;
+ BOOLEAN ResetRequired; // Primarily used to determine if a reset is required by changing this op-code.
+ UINT16 VariableNumber; // Used to define which variable the StorageStart will be pertinent for (0-based) For single variable VFR this will always be 0.
+ //
+ // Used to define which variable the StorageStart will be pertinent for (0-based) This is used for boolean check of ID versus ID
+ // so that a user can compare the value of one variable.field content versus another variable.field content.
+ //
+ UINT16 VariableNumber2;
+} EFI_TAG;
+
+#define EFI_FORM_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'o', 'r', 'm')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HII_PROTOCOL *Hii;
+ EFI_FORM_BROWSER_PROTOCOL FormConfig;
+} EFI_FORM_CONFIGURATION_DATA;
+
+#define EFI_FORM_DATA_FROM_THIS(a) CR (a, EFI_FORM_CONFIGURATION_DATA, FormConfig, EFI_FORM_DATA_SIGNATURE)
+
+typedef struct _EFI_VARIABLE_DEFINITION {
+ CHAR8 *NvRamMap;
+ CHAR8 *FakeNvRamMap; // This is where the storage for NULL devices go (e.g. RTC)
+ EFI_GUID Guid;
+ UINT16 VariableId;
+ UINT16 VariableSize;
+ UINT16 VariableFakeSize; // For dynamically created and NULL device options, this is the latest size
+ CHAR16 *VariableName;
+ struct _EFI_VARIABLE_DEFINITION *Next;
+ struct _EFI_VARIABLE_DEFINITION *Previous;
+} EFI_VARIABLE_DEFINITION;
+
+typedef struct {
+ UINT32 Length; // Length in bytes between beginning of struc and end of Strings
+ CHAR8 LanguageCode[4]; // ISO-639-2 language code with a null-terminator
+ RELOFST PrintableLanguageName; // Translated name of the Language, "English"/"Espanol" etc
+ UINT32 Attributes; // If on, the language is intended to be printed right to left. The default (off) is to print left to right.
+ RELOFST StringsPointers[1]; // Pointing to string offset from beginning of String Binary
+ EFI_STRING Strings[1]; // Array of String Entries. Note the number of entries for Strings and StringsPointers will be the same
+} EFI_LANGUAGE_SET;
+
+//
+// This encapsulates all the pointers associated with found IFR binaries
+//
+typedef struct _EFI_IFR_BINARY {
+ struct _EFI_IFR_BINARY *Next;
+ VOID *IfrPackage; // Handy for use in freeing the data later since this is the header of the buffer
+ VOID *FormBinary;
+ EFI_HII_HANDLE Handle;
+ STRING_REF TitleToken;
+ BOOLEAN UnRegisterOnExit;
+} EFI_IFR_BINARY;
+
+//
+// This encapsulates all the questions (tags) for a particular Form Set
+//
+typedef struct _EFI_FORM_TAGS {
+ struct _EFI_FORM_TAGS *Next;
+ EFI_TAG *Tags;
+} EFI_FORM_TAGS;
+
+//
+// This is the database of all inconsistency data. Each op-code associated
+// with inconsistency will be tracked here. This optimizes the search requirement
+// since we will back mark the main tag structure with the op-codes that have reference
+// to inconsistency data. This way when parsing the main tag structure and encountering
+// the inconsistency mark - we can search this database to know what the inconsistency
+// parameters are for that entry.
+//
+typedef struct _EFI_INCONSISTENCY_DATA {
+ struct _EFI_INCONSISTENCY_DATA *Next;
+ struct _EFI_INCONSISTENCY_DATA *Previous;
+ UINT8 Operand;
+ STRING_REF Popup;
+ UINT16 QuestionId1;
+ UINT16 QuestionId2;
+ UINT16 Value;
+ UINT16 ListLength;
+ UINT16 ConsistencyId;
+ UINT16 *ValueList;
+ UINT16 VariableNumber;
+ UINT16 VariableNumber2;
+ UINT8 Width;
+} EFI_INCONSISTENCY_DATA;
+
+//
+// Encapsulating all found Tag information from all sources
+// Each encapsulation also contains the NvRamMap buffer and the Size of the NV store
+//
+typedef struct _EFI_FILE_FORM_TAGS {
+ struct _EFI_FILE_FORM_TAGS *NextFile;
+ EFI_INCONSISTENCY_DATA *InconsistentTags;
+ EFI_VARIABLE_DEFINITION *VariableDefinitions;
+ EFI_FORM_TAGS FormTags;
+} EFI_FILE_FORM_TAGS;
+
+typedef struct {
+ STRING_REF Banner[BANNER_HEIGHT][BANNER_COLUMNS];
+} BANNER_DATA;
+
+//
+// Head of the Binary structures
+//
+EFI_IFR_BINARY *gBinaryDataHead;
+
+//
+// The IFR binary that the user chose to run
+//
+UINTN gActiveIfr;
+
+EFI_HII_PROTOCOL *Hii;
+
+VOID *CachedNVEntry;
+BANNER_DATA *BannerData;
+EFI_HII_HANDLE FrontPageHandle;
+STRING_REF FrontPageTimeOutTitle;
+INT16 FrontPageTimeOutValue;
+UINTN gClassOfVfr;
+UINTN gFunctionKeySetting;
+BOOLEAN gResetRequired;
+BOOLEAN gExitRequired;
+BOOLEAN gSaveRequired;
+BOOLEAN gNvUpdateRequired;
+UINT16 gConsistencyId;
+UINTN gPriorMenuEntry;
+EFI_HII_HANDLE gHiiHandle;
+BOOLEAN gFirstIn;
+VOID *gPreviousValue;
+UINT16 gDirection;
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN gUpArrow;
+BOOLEAN gDownArrow;
+BOOLEAN gTimeOnScreen;
+BOOLEAN gDateOnScreen;
+
+//
+// Browser Global Strings
+//
+CHAR16 *gFunctionOneString;
+CHAR16 *gFunctionTwoString;
+CHAR16 *gFunctionNineString;
+CHAR16 *gFunctionTenString;
+CHAR16 *gEnterString;
+CHAR16 *gEnterCommitString;
+CHAR16 *gEscapeString;
+CHAR16 *gMoveHighlight;
+CHAR16 *gMakeSelection;
+CHAR16 *gNumericInput;
+CHAR16 *gToggleCheckBox;
+CHAR16 *gPromptForPassword;
+CHAR16 *gPromptForNewPassword;
+CHAR16 *gConfirmPassword;
+CHAR16 *gConfirmError;
+CHAR16 *gPressEnter;
+CHAR16 *gEmptyString;
+CHAR16 *gAreYouSure;
+CHAR16 *gYesResponse;
+CHAR16 *gNoResponse;
+CHAR16 *gMiniString;
+CHAR16 *gPlusString;
+CHAR16 *gMinusString;
+CHAR16 *gAdjustNumber;
+
+CHAR16 gPromptBlockWidth;
+CHAR16 gOptionBlockWidth;
+CHAR16 gHelpBlockWidth;
+
+//
+// Global Procedure Defines
+//
+VOID
+InitializeBrowserStrings (
+ VOID
+ )
+;
+
+UINTN
+Print (
+ IN CHAR16 *fmt,
+ ...
+ )
+;
+
+UINTN
+PrintString (
+ CHAR16 *String
+ )
+;
+
+UINTN
+PrintChar (
+ CHAR16 Character
+ )
+;
+
+UINTN
+PrintAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *fmt,
+ ...
+ )
+;
+
+UINTN
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 *String
+ )
+;
+
+UINTN
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+;
+
+VOID
+DisplayPageFrame (
+ VOID
+ )
+;
+
+CHAR16 *
+GetToken (
+ IN STRING_REF IfrBinaryTitle,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+;
+
+VOID
+GetTagCount (
+ IN UINT8 *RawFormSet,
+ IN OUT UINT16 *NumberOfTags
+ )
+;
+
+VOID
+GetNumericHeader (
+ IN EFI_TAG *Tag,
+ IN UINT8 *RawFormSet,
+ IN UINT16 Index,
+ IN UINT16 NumberOfLines,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 CurrentVariable
+ )
+;
+
+VOID
+GetQuestionHeader (
+ IN EFI_TAG *Tag,
+ IN UINT8 *RawFormSet,
+ IN UINT16 Index,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 CurrentVariable
+ )
+;
+
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 **ArrayOfStrings
+ )
+;
+
+EFI_STATUS
+CreateDialog (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+;
+
+#endif
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.inf b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.inf
new file mode 100644
index 0000000000..22f65e6648
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.inf
@@ -0,0 +1,108 @@
+#/** @file
+# Component description file for SetupBrowser module.
+#
+# This driver initializes Setup for the brower and installs FormBrowser protocol.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SetupBrowser
+ FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF670
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeSetup
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# Create Event Guid C Name: EFI_EVENT_TIMER Event Type: EVENT_GROUP_GUID
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ Colors.h
+ Ui.h
+ Ui.c
+ ProcessOptions.c
+ Presentation.c
+ Print.h
+ Print.c
+ InputHandler.c
+ Boolean.c
+ Setup.h
+ Setup.c
+ SetupBrowserStr.uni
+ CommonHeader.h
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ EdkGraphicsLib
+ FrameworkHiiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PrintLib
+ UefiDriverEntryPoint
+ MemoryAllocationLib
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiPrintProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiFormBrowserProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiFormCallbackProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa
new file mode 100644
index 0000000000..d3a0bd3229
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>SetupBrowser</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>EBf342FE-B1D3-4EF8-957C-8048606FF670</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for SetupBrowser module.</Abstract>
+ <Description>This driver initializes Setup for the brower and installs FormBrowser protocol.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>SetupBrowser</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HiiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkGraphicsLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>SetupBrowserStr.uni</Filename>
+ <Filename>Setup.c</Filename>
+ <Filename>Setup.h</Filename>
+ <Filename>Boolean.c</Filename>
+ <Filename>InputHandler.c</Filename>
+ <Filename>Print.c</Filename>
+ <Filename>Print.h</Filename>
+ <Filename>Presentation.c</Filename>
+ <Filename>ProcessOptions.c</Filename>
+ <Filename>Ui.c</Filename>
+ <Filename>Ui.h</Filename>
+ <Filename>Colors.h</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFormCallbackProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiFormBrowserProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">
+ <ProtocolCName>gEfiPrintProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Events>
+ <CreateEvents>
+ <EventTypes EventGuidCName="EFI_EVENT_TIMER" Usage="ALWAYS_CONSUMED">
+ <EventType>EVENT_GROUP_GUID</EventType>
+ </EventTypes>
+ </CreateEvents>
+ </Events>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeSetup</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
new file mode 100644
index 0000000000..feb82c20bc
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
Binary files differ
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.c b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.c
new file mode 100644
index 0000000000..8a514a000a
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.c
@@ -0,0 +1,3155 @@
+/**@file
+ Implementation for UI.
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+#include "Setup.h"
+#include "Ui.h"
+#include "Colors.h"
+
+//
+// Implementation
+//
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+/*++
+
+Routine Description:
+
+ Set Buffer to Value for Size bytes.
+
+Arguments:
+
+ Buffer - Memory to set.
+
+ Size - Number of bytes to set
+
+ Value - Value of the set operation.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR16 *Ptr;
+
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = Value;
+ }
+}
+
+VOID
+UiInitMenu (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialize Menu option list.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ InitializeListHead (&Menu);
+}
+
+VOID
+UiInitMenuList (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialize Menu option list.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ InitializeListHead (&gMenuList);
+}
+
+VOID
+UiRemoveMenuListEntry (
+ IN UI_MENU_OPTION *Selection,
+ OUT UI_MENU_OPTION **PreviousSelection
+ )
+/*++
+
+Routine Description:
+ Remove Menu option list.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UI_MENU_LIST *UiMenuList;
+
+ *PreviousSelection = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (*PreviousSelection != NULL);
+
+ if (!IsListEmpty (&gMenuList)) {
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+ (*PreviousSelection)->IfrNumber = UiMenuList->Selection.IfrNumber;
+ (*PreviousSelection)->FormId = UiMenuList->Selection.FormId;
+ (*PreviousSelection)->Tags = UiMenuList->Selection.Tags;
+ (*PreviousSelection)->ThisTag = UiMenuList->Selection.ThisTag;
+ (*PreviousSelection)->Handle = UiMenuList->Selection.Handle;
+ gEntryNumber = UiMenuList->FormerEntryNumber;
+ RemoveEntryList (&UiMenuList->MenuLink);
+ FreePool (UiMenuList);
+ }
+}
+
+VOID
+UiFreeMenuList (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free Menu option linked list.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UI_MENU_LIST *UiMenuList;
+
+ while (!IsListEmpty (&gMenuList)) {
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+ RemoveEntryList (&UiMenuList->MenuLink);
+ FreePool (UiMenuList);
+ }
+}
+
+VOID
+UiAddMenuListEntry (
+ IN UI_MENU_OPTION *Selection
+ )
+/*++
+
+Routine Description:
+ Add one menu entry to the linked lst
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UI_MENU_LIST *UiMenuList;
+
+ UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
+ ASSERT (UiMenuList != NULL);
+
+ UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
+ CopyMem (&UiMenuList->Selection, Selection, sizeof (UI_MENU_OPTION));
+
+ InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
+}
+
+VOID
+UiFreeMenu (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free Menu option linked list.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UI_MENU_OPTION *MenuOption;
+
+ while (!IsListEmpty (&Menu)) {
+ MenuOption = CR (Menu.ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ RemoveEntryList (&MenuOption->Link);
+
+ //
+ // We allocated space for this description when we did a GetToken, free it here
+ //
+ FreePool (MenuOption->Description);
+ FreePool (MenuOption);
+ }
+}
+
+STATIC
+VOID
+UpdateDateAndTime (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Refresh screen with current date and/or time based on screen context
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ CHAR16 *OptionString;
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;
+ UINTN Index;
+ UINTN Loop;
+
+ OptionString = NULL;
+
+ if (gMenuRefreshHead != NULL) {
+
+ MenuRefreshEntry = gMenuRefreshHead;
+
+ do {
+ gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
+ ProcessOptions (MenuRefreshEntry->MenuOption, FALSE, MenuRefreshEntry->FileFormTagsHead, NULL, &OptionString);
+
+ if (OptionString != NULL) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Loop] = OptionString[Index];
+ Loop++;
+ }
+
+ OptionString[Loop] = CHAR_NULL;
+
+ PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
+ }
+
+ MenuRefreshEntry = MenuRefreshEntry->Next;
+
+ } while (MenuRefreshEntry != NULL);
+ }
+
+ if (OptionString != NULL) {
+ FreePool (OptionString);
+ }
+}
+
+EFI_STATUS
+UiWaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Wait for a given event to fire, or for an optional timeout to expire.
+
+Arguments:
+ Event - The event to wait for
+
+ Timeout - An optional timeout value in 100 ns units.
+
+Returns:
+
+ EFI_SUCCESS - Event fired before Timeout expired.
+ EFI_TIME_OUT - Timout expired before Event fired.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // Update screen every second
+ //
+ Timeout = ONE_SECOND;
+
+ do {
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+
+ //
+ // If the timer expired, update anything that needs a refresh and keep waiting
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ UpdateDateAndTime ();
+ }
+
+ gBS->CloseEvent (TimerEvent);
+ } while (Status == EFI_TIMEOUT);
+ }
+
+ return Status;
+}
+
+VOID
+UiAddMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_TAG *Tags,
+ IN VOID *FormBinary,
+ IN UINTN IfrNumber
+ )
+/*++
+
+Routine Description:
+ Add one menu option by specified description and context.
+
+Arguments:
+ String - String description for this option.
+ Context - Context data for entry.
+
+Returns:
+
+--*/
+{
+ UI_MENU_OPTION *MenuOption;
+
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (MenuOption);
+
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
+ MenuOption->Description = String;
+ MenuOption->Handle = Handle;
+ MenuOption->FormBinary = FormBinary;
+ MenuOption->IfrNumber = IfrNumber;
+ MenuOption->Skip = 1;
+ MenuOption->Tags = Tags;
+ MenuOption->TagIndex = 0;
+ MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]);
+ MenuOption->EntryNumber = (UINT16) IfrNumber;
+
+ InsertTailList (&Menu, &MenuOption->Link);
+}
+
+VOID
+UiAddSubMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_TAG *Tags,
+ IN UINTN TagIndex,
+ IN UINT16 FormId,
+ IN UINT16 MenuItemCount
+ )
+/*++
+
+Routine Description:
+ Add one menu option by specified description and context.
+
+Arguments:
+ String - String description for this option.
+ Context - Context data for entry.
+
+Returns:
+
+--*/
+{
+ UI_MENU_OPTION *MenuOption;
+
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (MenuOption);
+
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
+ MenuOption->Description = String;
+ MenuOption->Handle = Handle;
+ MenuOption->Skip = Tags[TagIndex].NumberOfLines;
+ MenuOption->IfrNumber = gActiveIfr;
+ MenuOption->Tags = Tags;
+ MenuOption->TagIndex = TagIndex;
+ MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]);
+ MenuOption->Consistency = Tags[TagIndex].Consistency;
+ MenuOption->FormId = FormId;
+ MenuOption->GrayOut = Tags[TagIndex].GrayOut;
+ MenuOption->EntryNumber = MenuItemCount;
+
+ InsertTailList (&Menu, &MenuOption->Link);
+}
+
+EFI_STATUS
+CreateDialog (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+/*++
+
+Routine Description:
+ Routine used to abstract a generic dialog interface and return the selected key or string
+
+Arguments:
+ NumberOfLines - The number of lines for the dialog box
+ HotKey - Defines whether a single character is parsed (TRUE) and returned in KeyValue
+ or a string is returned in StringBuffer. Two special characters are considered when entering a string, a SCAN_ESC and
+ an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates string input and returns
+ MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes
+ StringBuffer - The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE
+ KeyValue - The EFI_KEY value returned if HotKey is TRUE..
+ String - Pointer to the first string in the list
+ ... - A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box
+
+Returns:
+ EFI_SUCCESS - Displayed dialog and received user interaction
+ EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE))
+ EFI_DEVICE_ERROR - User typed in an ESC character to exit the routine
+
+--*/
+{
+ VA_LIST Marker;
+ UINTN Count;
+ EFI_INPUT_KEY Key;
+ UINTN LargestString;
+ CHAR16 *TempString;
+ CHAR16 *BufferedString;
+ CHAR16 *StackString;
+ CHAR16 KeyPad[2];
+ UINTN Start;
+ UINTN Top;
+ UINTN Index;
+ BOOLEAN SelectionComplete;
+ UINTN InputOffset;
+ UINTN CurrentAttribute;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ SelectionComplete = FALSE;
+ InputOffset = 0;
+ TempString = AllocateZeroPool (MaximumStringSize * 2);
+ BufferedString = AllocateZeroPool (MaximumStringSize * 2);
+ CurrentAttribute = gST->ConOut->Mode->Attribute;
+
+ ASSERT (TempString);
+ ASSERT (BufferedString);
+
+ VA_START (Marker, String);
+
+ //
+ // Zero the outgoing buffer
+ //
+ ZeroMem (StringBuffer, MaximumStringSize);
+
+ if (HotKey) {
+ if (KeyValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (StringBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Disable cursor
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ LargestString = (GetStringWidth (String) / 2);
+
+ if (LargestString == L' ') {
+ InputOffset = 1;
+ }
+ //
+ // Determine the largest string in the dialog box
+ // Notice we are starting with 1 since String is the first string
+ //
+ for (Count = 1; Count < NumberOfLines; Count++) {
+ StackString = VA_ARG (Marker, CHAR16 *);
+
+ if (StackString[0] == L' ') {
+ InputOffset = Count + 1;
+ }
+
+ if ((GetStringWidth (StackString) / 2) > LargestString) {
+ //
+ // Size of the string visually and subtract the width by one for the null-terminator
+ //
+ LargestString = (GetStringWidth (StackString) / 2);
+ }
+ }
+
+ Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+
+ Count = 0;
+
+ //
+ // Display the Popup
+ //
+ CreateSharedPopUp (LargestString, NumberOfLines, &String);
+
+ //
+ // Take the first key typed and report it back?
+ //
+ if (HotKey) {
+ WaitForKeyStroke (&Key);
+ CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
+
+ } else {
+ do {
+ WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_ESC:
+ FreePool (TempString);
+ FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ SelectionComplete = TRUE;
+ FreePool (TempString);
+ FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+ break;
+
+ case CHAR_BACKSPACE:
+ if (StringBuffer[0] != CHAR_NULL) {
+ for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
+ TempString[Index] = StringBuffer[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString[Index - 1] = CHAR_NULL;
+ StrCpy (StringBuffer, TempString);
+ }
+
+ default:
+ //
+ // If it is the beginning of the string, don't worry about checking maximum limits
+ //
+ if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
+ StrnCpy (TempString, &Key.UnicodeChar, 1);
+ } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ KeyPad[0] = Key.UnicodeChar;
+ KeyPad[1] = CHAR_NULL;
+ StrCat (StringBuffer, KeyPad);
+ StrCat (TempString, KeyPad);
+ }
+ //
+ // If the width of the input string is now larger than the screen, we nee to
+ // adjust the index to start printing portions of the string
+ //
+ SetUnicodeMem (BufferedString, LargestString, L' ');
+
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+
+ if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
+ Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
+ } else {
+ Index = 0;
+ }
+
+ for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
+ BufferedString[Count] = StringBuffer[Index];
+ }
+
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+ break;
+ }
+ } while (!SelectionComplete);
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 **ArrayOfStrings
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ CHAR16 Character;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ CHAR16 *String;
+
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ Count = 0;
+
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+ if ((RequestedWidth + 2) > DimensionsWidth) {
+ RequestedWidth = DimensionsWidth - 2;
+ }
+ //
+ // Subtract the PopUp width from total Columns, allow for one space extra on
+ // each end plus a border.
+ //
+ Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ End = Start + RequestedWidth + 1;
+
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+ Bottom = Top + NumberOfLines + 2;
+
+ Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ Character = (CHAR16) BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintChar (Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = (CHAR16) BOXDRAW_VERTICAL;
+ for (Index = Top; Index + 2 < Bottom; Index++) {
+ String = ArrayOfStrings[Count];
+ Count++;
+
+ //
+ // This will clear the background of the line - we never know who might have been
+ // here before us. This differs from the next clear in that it used the non-reverse
+ // video for normal printing.
+ //
+ if (GetStringWidth (String) / 2 > 1) {
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+ }
+ //
+ // Passing in a space results in the assumption that this is where typing will occur
+ //
+ if (String[0] == L' ') {
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
+ }
+ //
+ // Passing in a NULL results in a blank space
+ //
+ if (String[0] == CHAR_NULL) {
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+ }
+
+ PrintStringAt (
+ ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
+ Index + 1,
+ String
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ PrintCharAt (Start, Index + 1, Character);
+ PrintCharAt (End - 1, Index + 1, Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom - 1, Character);
+ Character = (CHAR16) BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintChar (Character);
+ }
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+}
+
+VOID
+CreatePopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 *ArrayOfStrings,
+ ...
+ )
+{
+ CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
+}
+
+VOID
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN UINT8 Flags,
+ IN BOOLEAN State
+ )
+{
+ UINTN Index;
+ STATIC BOOLEAN InputError;
+ CHAR16 *NvUpdateMessage;
+ CHAR16 *InputErrorMessage;
+
+ NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
+ InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
+
+ switch (MessageType) {
+ case INPUT_ERROR:
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + gPromptBlockWidth,
+ gScreenDimensions.BottomRow - 1,
+ InputErrorMessage
+ );
+ InputError = TRUE;
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+ for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
+ PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, (CHAR16 *) L" ");
+ }
+
+ InputError = FALSE;
+ }
+ break;
+
+ case NV_UPDATE_REQUIRED:
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
+ gScreenDimensions.BottomRow - 1,
+ NvUpdateMessage
+ );
+ gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
+
+ gNvUpdateRequired = TRUE;
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+ for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
+ PrintAt (
+ (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
+ gScreenDimensions.BottomRow - 1,
+ (CHAR16 *) L" "
+ );
+ }
+
+ gNvUpdateRequired = FALSE;
+ }
+ }
+ break;
+
+ case REFRESH_STATUS_BAR:
+ if (InputError) {
+ UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
+ }
+
+ if (gNvUpdateRequired) {
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ FreePool (InputErrorMessage);
+ FreePool (NvUpdateMessage);
+ return ;
+}
+
+VOID
+FreeData (
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN CHAR16 *FormattedString,
+ IN CHAR16 *OptionString
+ )
+/*++
+
+Routine Description:
+
+ Used to remove the allocated data instances
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_FILE_FORM_TAGS *FileForm;
+ EFI_FILE_FORM_TAGS *PreviousFileForm;
+ EFI_FORM_TAGS *FormTags;
+ EFI_FORM_TAGS *PreviousFormTags;
+ EFI_IFR_BINARY *IfrBinary;
+ EFI_IFR_BINARY *PreviousIfrBinary;
+ EFI_INCONSISTENCY_DATA *Inconsistent;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_VARIABLE_DEFINITION *PreviousVariableDefinition;
+ VOID *Buffer;
+ UINTN Index;
+
+ FileForm = FileFormTagsHead;
+
+ if (FormattedString != NULL) {
+ FreePool (FormattedString);
+ }
+
+ if (OptionString != NULL) {
+ FreePool (OptionString);
+ }
+
+ for (; FileForm != NULL;) {
+ PreviousFileForm = NULL;
+
+ //
+ // Advance FileForm to the last entry
+ //
+ for (; FileForm->NextFile != NULL; FileForm = FileForm->NextFile) {
+ PreviousFileForm = FileForm;
+ }
+
+ FormTags = &FileForm->FormTags;
+
+ for (; FormTags != NULL;) {
+ FormTags = &FileForm->FormTags;
+ PreviousFormTags = NULL;
+
+ //
+ // Advance FormTags to the last entry
+ //
+ for (; FormTags->Next != NULL; FormTags = FormTags->Next) {
+ PreviousFormTags = FormTags;
+ }
+ //
+ // Walk through each of the tags and free the IntList allocation
+ //
+ for (Index = 0; FormTags->Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
+ //
+ // It is more than likely that the very last page will contain an end formset
+ //
+ if (FormTags->Tags[Index].Operand == EFI_IFR_END_FORM_SET_OP) {
+ break;
+ }
+
+ if (FormTags->Tags[Index].IntList != NULL) {
+ FreePool (FormTags->Tags[Index].IntList);
+ }
+ }
+
+ if (PreviousFormTags != NULL) {
+ FreePool (FormTags->Tags);
+ FormTags = PreviousFormTags;
+ FreePool (FormTags->Next);
+ FormTags->Next = NULL;
+ } else {
+ FreePool (FormTags->Tags);
+ FormTags = NULL;
+ }
+ }
+ //
+ // Last FileForm entry's Inconsistent database
+ //
+ Inconsistent = FileForm->InconsistentTags;
+
+ //
+ // Advance Inconsistent to the last entry
+ //
+ for (; Inconsistent->Next != NULL; Inconsistent = Inconsistent->Next)
+ ;
+
+ for (; Inconsistent != NULL;) {
+ //
+ // Preserve the Previous pointer
+ //
+ Buffer = (VOID *) Inconsistent->Previous;
+
+ //
+ // Free the current entry
+ //
+ FreePool (Inconsistent);
+
+ //
+ // Restore the Previous pointer
+ //
+ Inconsistent = (EFI_INCONSISTENCY_DATA *) Buffer;
+ }
+
+ VariableDefinition = FileForm->VariableDefinitions;
+
+ for (; VariableDefinition != NULL;) {
+ VariableDefinition = FileForm->VariableDefinitions;
+ PreviousVariableDefinition = NULL;
+
+ //
+ // Advance VariableDefinitions to the last entry
+ //
+ for (; VariableDefinition->Next != NULL; VariableDefinition = VariableDefinition->Next) {
+ PreviousVariableDefinition = VariableDefinition;
+ }
+
+ FreePool (VariableDefinition->VariableName);
+
+ if (VariableDefinition->NvRamMap != NULL) {
+ FreePool (VariableDefinition->NvRamMap);
+ }
+
+ if (VariableDefinition->FakeNvRamMap != NULL) {
+ FreePool (VariableDefinition->FakeNvRamMap);
+ }
+
+ if (PreviousVariableDefinition != NULL) {
+ VariableDefinition = PreviousVariableDefinition;
+ FreePool (VariableDefinition->Next);
+ VariableDefinition->Next = NULL;
+ } else {
+ FreePool (VariableDefinition);
+ VariableDefinition = NULL;
+ }
+ }
+
+ if (PreviousFileForm != NULL) {
+ FileForm = PreviousFileForm;
+ FreePool (FileForm->NextFile);
+ FileForm->NextFile = NULL;
+ } else {
+ FreePool (FileForm);
+ FileForm = NULL;
+ }
+ }
+
+ IfrBinary = gBinaryDataHead;
+
+ for (; IfrBinary != NULL;) {
+ IfrBinary = gBinaryDataHead;
+ PreviousIfrBinary = NULL;
+
+ //
+ // Advance IfrBinary to the last entry
+ //
+ for (; IfrBinary->Next != NULL; IfrBinary = IfrBinary->Next) {
+ PreviousIfrBinary = IfrBinary;
+ }
+
+ FreePool (IfrBinary->IfrPackage);
+
+ if (PreviousIfrBinary != NULL) {
+ IfrBinary = PreviousIfrBinary;
+ FreePool (IfrBinary->Next);
+ IfrBinary->Next = NULL;
+ } else {
+ FreePool (IfrBinary);
+ IfrBinary = NULL;
+ }
+ }
+
+ FreePool (gPreviousValue);
+ gPreviousValue = NULL;
+
+ //
+ // Free Browser Strings
+ //
+ FreePool (gPressEnter);
+ FreePool (gConfirmError);
+ FreePool (gConfirmPassword);
+ FreePool (gPromptForNewPassword);
+ FreePool (gPromptForPassword);
+ FreePool (gToggleCheckBox);
+ FreePool (gNumericInput);
+ FreePool (gMakeSelection);
+ FreePool (gMoveHighlight);
+ FreePool (gEscapeString);
+ FreePool (gEnterCommitString);
+ FreePool (gEnterString);
+ FreePool (gFunctionOneString);
+ FreePool (gFunctionTwoString);
+ FreePool (gFunctionNineString);
+ FreePool (gFunctionTenString);
+ return ;
+}
+
+STATIC
+BOOLEAN
+SelectionsAreValid (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead
+ )
+/*++
+
+Routine Description:
+ Initiate late consistency checks against the current page.
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ LIST_ENTRY *Link;
+ EFI_TAG *Tag;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ CHAR16 *StringPtr;
+ CHAR16 NullCharacter;
+ UINTN Index;
+ UINT16 *NvRamMap;
+ STRING_REF PopUp;
+ EFI_INPUT_KEY Key;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+
+ StringPtr = (CHAR16 *) L"\0";
+ NullCharacter = CHAR_NULL;
+
+ FileFormTags = FileFormTagsHead;
+
+ for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
+ MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ Tag = MenuOption->ThisTag;
+
+ ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
+ NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
+
+ //
+ // If the op-code has a late check, ensure consistency checks are now applied
+ //
+ if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
+ if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
+ if (PopUp != 0x0000) {
+ StringPtr = GetToken (PopUp, MenuOption->Handle);
+
+ CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);
+
+ do {
+ WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
+ //
+ CopyMem (NvRamMap, &Tag->OldValue, Tag->StorageWidth);
+ FreePool (StringPtr);
+ break;
+
+ default:
+ break;
+ }
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+UINT16
+GetWidth (
+ IN EFI_TAG *Tag,
+ IN EFI_HII_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+ Get the supported width for a particular op-code
+
+Arguments:
+ Tag - The Tag structure passed in.
+ Handle - The handle in the HII database being used
+
+Returns:
+ Returns the number of CHAR16 characters that is support.
+
+
+--*/
+{
+ CHAR16 *String;
+ UINTN Size;
+
+ Size = 0x00;
+
+ //
+ // See if the second text parameter is really NULL
+ //
+ if ((Tag->Operand == EFI_IFR_TEXT_OP) && (Tag->TextTwo != 0)) {
+ String = GetToken (Tag->TextTwo, Handle);
+ Size = StrLen (String);
+ FreePool (String);
+ }
+
+ if ((Tag->Operand == EFI_IFR_SUBTITLE_OP) ||
+ (Tag->Operand == EFI_IFR_REF_OP) ||
+ (Tag->Operand == EFI_IFR_PASSWORD_OP) ||
+ (Tag->Operand == EFI_IFR_STRING_OP) ||
+ (Tag->Operand == EFI_IFR_INVENTORY_OP) ||
+ //
+ // Allow a wide display if text op-code and no secondary text op-code
+ //
+ ((Tag->Operand == EFI_IFR_TEXT_OP) && (Size == 0x0000))
+ ) {
+ return (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
+ } else {
+ return (UINT16) gPromptBlockWidth;
+ }
+}
+
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ )
+/*++
+
+Routine Description:
+ Will copy LineWidth amount of a string in the OutputString buffer and return the
+ number of CHAR16 characters that were copied into the OutputString buffer.
+
+Arguments:
+ InputString - String description for this option.
+ LineWidth - Width of the desired string to extract in CHAR16 characters
+ Index - Where in InputString to start the copy process
+ OutputString - Buffer to copy the string into
+
+Returns:
+ Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+
+
+--*/
+{
+ static BOOLEAN Finished;
+ UINT16 Count;
+ UINT16 Count2;
+
+ if (Finished) {
+ Finished = FALSE;
+ return (UINT16) 0;
+ }
+
+ Count = LineWidth;
+ Count2 = 0;
+
+ *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
+
+ //
+ // Ensure we have got a valid buffer
+ //
+ if (*OutputString != NULL) {
+
+ //
+ //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.
+ //To avoid displaying this empty line in screen, just skip the two CHARs here.
+ //
+ if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
+ *Index = *Index + 2;
+ }
+
+ //
+ // Fast-forward the string and see if there is a carriage-return in the string
+ //
+ for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
+ ;
+
+ //
+ // Copy the desired LineWidth of data to the output buffer.
+ // Also make sure that we don't copy more than the string.
+ // Also make sure that if there are linefeeds, we account for them.
+ //
+ if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
+ (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
+ ) {
+ //
+ // Convert to CHAR16 value and show that we are done with this operation
+ //
+ LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
+ if (LineWidth != 0) {
+ Finished = TRUE;
+ }
+ } else {
+ if (Count2 == LineWidth) {
+ //
+ // Rewind the string from the maximum size until we see a space to break the line
+ //
+ for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
+ ;
+ if (LineWidth == 0) {
+ LineWidth = Count;
+ }
+ } else {
+ LineWidth = Count2;
+ }
+ }
+
+ CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
+
+ //
+ // If currently pointing to a space, increment the index to the first non-space character
+ //
+ for (;
+ (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
+ (*Index)++
+ )
+ ;
+ *Index = (UINT16) (*Index + LineWidth);
+ return LineWidth;
+ } else {
+ return (UINT16) 0;
+ }
+}
+
+STATIC
+VOID
+UpdateOptionSkipLines (
+ IN EFI_IFR_DATA_ARRAY *PageData,
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN CHAR16 **OptionalString,
+ IN UINTN SkipValue
+ )
+{
+ UINTN Index;
+ UINT16 Width;
+ UINTN Row;
+ UINTN OriginalRow;
+ CHAR16 *OutputString;
+ CHAR16 *OptionString;
+
+ Row = 0;
+ OptionString = *OptionalString;
+ OutputString = NULL;
+
+ ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
+
+ if (OptionString != NULL) {
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ if (SkipValue == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ FreePool (OutputString);
+ if (SkipValue != 0) {
+ SkipValue--;
+ }
+ }
+
+ Row = OriginalRow;
+ }
+
+ *OptionalString = OptionString;
+}
+//
+// Search table for UiDisplayMenu()
+//
+SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {
+ { SCAN_UP, UiUp },
+ { SCAN_DOWN, UiDown },
+ { SCAN_PAGE_UP, UiPageUp },
+ { SCAN_PAGE_DOWN, UiPageDown},
+ { SCAN_ESC, UiReset},
+ { SCAN_F2, UiPrevious},
+ { SCAN_LEFT, UiLeft },
+ { SCAN_RIGHT, UiRight },
+ { SCAN_F9, UiDefault},
+ { SCAN_F10, UiSave }
+};
+
+SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
+ { UiNoOperation, CfUiNoOperation },
+ { UiDefault, CfUiDefault },
+ { UiSelect, CfUiSelect },
+ { UiUp, CfUiUp},
+ { UiDown, CfUiDown },
+ { UiLeft, CfUiLeft },
+ { UiRight, CfUiRight },
+ { UiReset, CfUiReset },
+ { UiSave, CfUiSave },
+ { UiPrevious, CfUiPrevious },
+ { UiPageUp, CfUiPageUp },
+ { UiPageDown, CfUiPageDown }
+};
+
+UI_MENU_OPTION *
+UiDisplayMenu (
+ IN BOOLEAN SubMenu,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ OUT EFI_IFR_DATA_ARRAY *PageData
+ )
+/*++
+
+Routine Description:
+ Display menu and wait for user to select one menu option, then return it.
+ If AutoBoot is enabled, then if user doesn't select any option,
+ after period of time, it will automatically return the first menu option.
+
+Arguments:
+ SubMenu - Indicate is sub menu.
+ FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure.
+ PageData - A pointer to the EFI_IFR_DATA_ARRAY.
+
+Returns:
+ Return the pointer of the menu which selected,
+ otherwise return NULL.
+
+--*/
+{
+ INTN SkipValue;
+ INTN Difference;
+ INTN OldSkipValue;
+ UINTN Row;
+ UINTN Col;
+ UINTN Temp;
+ UINTN Temp2;
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN OriginalRow;
+ UINTN Index;
+ UINTN DataAndTimeLineNumberPad;
+ UINT32 Count;
+ INT16 OriginalTimeOut;
+ UINT8 *Location;
+ UINT16 Width;
+ CHAR16 *StringPtr;
+ CHAR16 *OptionString;
+ CHAR16 *OutputString;
+ CHAR16 *FormattedString;
+ CHAR16 YesResponse;
+ CHAR16 NoResponse;
+ BOOLEAN NewLine;
+ BOOLEAN Repaint;
+ BOOLEAN SavedValue;
+ EFI_STATUS Status;
+ UI_MENU_LIST *UiMenuList;
+ EFI_INPUT_KEY Key;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NewPos;
+ LIST_ENTRY *TopOfScreen;
+ LIST_ENTRY *SavedListEntry;
+ UI_MENU_OPTION *Selection;
+ UI_MENU_OPTION *MenuOption;
+ UI_MENU_OPTION *NextMenuOption;
+ UI_MENU_OPTION *SavedMenuOption;
+ UI_MENU_OPTION *PreviousMenuOption;
+ EFI_IFR_BINARY *IfrBinary;
+ UI_CONTROL_FLAG ControlFlag;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;
+ MENU_REFRESH_ENTRY *OldMenuRefreshEntry;
+ UI_SCREEN_OPERATION ScreenOperation;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_HII_VARIABLE_PACK_LIST *NvMapListHead;
+ EFI_HII_VARIABLE_PACK_LIST *NvMapListNode;
+ VOID *NvMap;
+ UINTN NvMapSize;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ VariableDefinition = NULL;
+ Status = EFI_SUCCESS;
+ FormattedString = NULL;
+ OptionString = NULL;
+ ScreenOperation = UiNoOperation;
+ NewLine = TRUE;
+ FormCallback = NULL;
+ FileFormTags = NULL;
+ OutputString = NULL;
+ gUpArrow = FALSE;
+ gDownArrow = FALSE;
+ SkipValue = 0;
+ OldSkipValue = 0;
+ MenuRefreshEntry = gMenuRefreshHead;
+ OldMenuRefreshEntry = gMenuRefreshHead;
+ NextMenuOption = NULL;
+ PreviousMenuOption = NULL;
+ SavedMenuOption = NULL;
+ IfrBinary = NULL;
+ NvMap = NULL;
+ NvMapSize = 0;
+
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ } else {
+ TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ }
+
+ if (SubMenu) {
+ Col = LocalScreen.LeftColumn;
+ } else {
+ Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;
+ }
+
+ BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
+
+ TopOfScreen = Menu.ForwardLink;
+ Repaint = TRUE;
+ MenuOption = NULL;
+
+ //
+ // Get user's selection
+ //
+ Selection = NULL;
+ NewPos = Menu.ForwardLink;
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
+
+ ControlFlag = CfInitialization;
+
+ while (TRUE) {
+ switch (ControlFlag) {
+ case CfInitialization:
+ ControlFlag = CfCheckSelection;
+ if (gExitRequired) {
+ ScreenOperation = UiReset;
+ ControlFlag = CfScreenOperation;
+ } else if (gSaveRequired) {
+ ScreenOperation = UiSave;
+ ControlFlag = CfScreenOperation;
+ } else if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ }
+ break;
+
+ case CfCheckSelection:
+ if (Selection != NULL) {
+ ControlFlag = CfExit;
+ } else {
+ ControlFlag = CfRepaint;
+ }
+
+ FileFormTags = FileFormTagsHead;
+ break;
+
+ case CfRepaint:
+ ControlFlag = CfRefreshHighLight;
+
+ if (Repaint) {
+ //
+ // Display menu
+ //
+ SavedMenuOption = MenuOption;
+ gDownArrow = FALSE;
+ gUpArrow = FALSE;
+ Row = TopRow;
+
+ Temp = SkipValue;
+ Temp2 = SkipValue;
+
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ FIELD_TEXT | FIELD_BACKGROUND
+ );
+
+ while (gMenuRefreshHead != NULL) {
+ OldMenuRefreshEntry = gMenuRefreshHead->Next;
+
+ FreePool (gMenuRefreshHead);
+
+ gMenuRefreshHead = OldMenuRefreshEntry;
+ }
+
+ for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
+ MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ MenuOption->Row = Row;
+ OriginalRow = Row;
+ MenuOption->Col = Col;
+ MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
+
+ if (SubMenu) {
+ if (MenuOption->ThisTag->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+ } else {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+ }
+ }
+
+ Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (Row <= BottomRow)) {
+ PrintStringAt (Col, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ if (Temp == 0) {
+ Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp != 0) {
+ Temp--;
+ }
+ }
+
+ Temp = 0;
+
+ Row = OriginalRow;
+
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
+
+ if (OptionString != NULL) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+ MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
+ ) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++) {
+ MenuOption->OptCol++;
+ }
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+
+ //
+ // If this is a date or time op-code and is used to reflect an RTC, register the op-code
+ //
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+ MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) &&
+ (MenuOption->ThisTag->StorageStart >= FileFormTags->FormTags.Tags[0].NvDataSize)) {
+
+ if (gMenuRefreshHead == NULL) {
+ MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+ ASSERT (MenuRefreshEntry != NULL);
+ MenuRefreshEntry->MenuOption = MenuOption;
+ MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead;
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ gMenuRefreshHead = MenuRefreshEntry;
+ } else {
+ //
+ // Advance to the last entry
+ //
+ for (MenuRefreshEntry = gMenuRefreshHead;
+ MenuRefreshEntry->Next != NULL;
+ MenuRefreshEntry = MenuRefreshEntry->Next
+ )
+ ;
+ MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+ ASSERT (MenuRefreshEntry->Next != NULL);
+ MenuRefreshEntry = MenuRefreshEntry->Next;
+ MenuRefreshEntry->MenuOption = MenuOption;
+ MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead;
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ }
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp2 == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ if (Temp2 == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ Temp2 = 0;
+ Row = OriginalRow;
+ }
+ //
+ // If this is a text op with secondary text information
+ //
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP) && (MenuOption->ThisTag->TextTwo != 0)) {
+ StringPtr = GetToken (MenuOption->ThisTag->TextTwo, MenuOption->Handle);
+
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&StringPtr[Index])) {
+ if (Temp2 == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ Row = OriginalRow;
+ FreePool (StringPtr);
+ }
+ } else {
+ //
+ // For now, assume left-justified 72 width max setup entries
+ //
+ PrintStringAt (Col, Row, MenuOption->Description);
+ }
+ //
+ // Tracker 6210 - need to handle the bottom of the display
+ //
+ if (MenuOption->Skip > 1) {
+ Row += MenuOption->Skip - SkipValue;
+ SkipValue = 0;
+ } else {
+ Row += MenuOption->Skip;
+ }
+
+ if (Row > BottomRow) {
+ if (!ValueIsScroll (FALSE, Link)) {
+ gDownArrow = TRUE;
+ }
+
+ Row = BottomRow + 1;
+ break;
+ }
+ }
+
+ if (!ValueIsScroll (TRUE, TopOfScreen)) {
+ gUpArrow = TRUE;
+ }
+
+ if (gUpArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+ PrintAt (
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ (CHAR16 *) L"%c",
+ ARROW_UP
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+
+ if (gDownArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+ PrintAt (
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ (CHAR16 *) L"%c",
+ ARROW_DOWN
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+
+ if (SavedMenuOption != NULL) {
+ MenuOption = SavedMenuOption;
+ }
+ }
+ break;
+
+ case CfRefreshHighLight:
+ ControlFlag = CfUpdateHelpString;
+ //
+ // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
+ // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
+ //
+ SavedValue = Repaint;
+ Repaint = FALSE;
+
+ if (NewPos != NULL) {
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+ if (SubMenu) {
+ if (gLastOpr && (gEntryNumber != -1)) {
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (gEntryNumber != MenuOption->EntryNumber) {
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ } else {
+ gLastOpr = FALSE;
+ }
+ }
+
+ ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ if (OptionString != NULL) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+ MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
+ ) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = MenuOption->Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ MenuOption->Row++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+ } else {
+ if (NewLine) {
+ if (MenuOption->ThisTag->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+ } else {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+ }
+ }
+
+ OriginalRow = MenuOption->Row;
+ Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (Col, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ MenuOption->Row++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+ }
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
+ }
+
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ if ((gPriorMenuEntry != 0) && (MenuOption->EntryNumber != gPriorMenuEntry) && (NewPos->ForwardLink != &Menu)) {
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ } else {
+ gPriorMenuEntry = 0;
+ }
+ //
+ // This is only possible if we entered this page and the first menu option is
+ // a "non-menu" item. In that case, force it UiDown
+ //
+ if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
+ //
+ // If we previously hit an UP command and we are still sitting on a text operation
+ // we must continue going up
+ //
+ if (ScreenOperation == UiUp) {
+ ControlFlag = CfScreenOperation;
+ break;
+ } else {
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+ }
+ //
+ // Set reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+
+ //
+ // Assuming that we have a refresh linked-list created, lets annotate the
+ // appropriate entry that we are highlighting with its new attribute. Just prior to this
+ // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
+ //
+ if (gMenuRefreshHead != NULL) {
+ for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ if (MenuRefreshEntry->MenuOption == MenuOption) {
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
+ }
+ }
+ }
+
+ if (SubMenu) {
+ ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
+ if (OptionString != NULL) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+ MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
+ ) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = MenuOption->Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ MenuOption->Row++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+ } else {
+ if (NewLine) {
+ OriginalRow = MenuOption->Row;
+
+ Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (Col, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ MenuOption->Row++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ }
+ }
+
+ if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
+ ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
+ (ScreenOperation == UiNoOperation)
+ ) {
+ UpdateKeyHelp (MenuOption, FALSE);
+ }
+ } else {
+ gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
+ }
+ //
+ // Clear reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+ //
+ // Repaint flag will be used when process CfUpdateHelpString, so restore its value
+ // if we didn't break halfway when process CfRefreshHighLight.
+ //
+ Repaint = SavedValue;
+ break;
+
+ case CfUpdateHelpString:
+ ControlFlag = CfPrepareToReadKey;
+
+ if (SubMenu &&
+ (Repaint || NewLine ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) &&
+ !(gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS)) {
+ //
+ // Don't print anything if it is a NULL help token
+ //
+ if (MenuOption->ThisTag->Help == 0x00000000) {
+ StringPtr = (CHAR16 *) L"\0";
+ } else {
+ StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
+ }
+
+ ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
+
+ gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
+
+ for (Index = 0; Index < BottomRow - TopRow; Index++) {
+ //
+ // Pad String with spaces to simulate a clearing of the previous line
+ //
+ for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
+ StrCat (&FormattedString[Index * gHelpBlockWidth * 2], (CHAR16 *) L" ");
+ }
+
+ PrintStringAt (
+ LocalScreen.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ &FormattedString[Index * gHelpBlockWidth * 2]
+ );
+ }
+ }
+ //
+ // Reset this flag every time we finish using it.
+ //
+ Repaint = FALSE;
+ NewLine = FALSE;
+ break;
+
+ case CfPrepareToReadKey:
+ ControlFlag = CfReadKey;
+
+ for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ ScreenOperation = UiNoOperation;
+
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ break;
+
+ case CfReadKey:
+ ControlFlag = CfScreenOperation;
+
+ OriginalTimeOut = FrontPageTimeOutValue;
+ do {
+ if (FrontPageTimeOutValue >= 0 && (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) && FrontPageTimeOutValue != (INT16) -1) {
+ //
+ // Remember that if set to 0, must immediately boot an option
+ //
+ if (FrontPageTimeOutValue == 0) {
+ FrontPageTimeOutValue = 0xFFFF;
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ }
+ break;
+ }
+
+ Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
+ if (Status == EFI_TIMEOUT) {
+ EFI_IFR_DATA_ENTRY *DataEntry;
+
+ DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1);
+
+ PageData->EntryCount = 1;
+ Count = (UINT32) ((OriginalTimeOut - FrontPageTimeOutValue) * 100 / OriginalTimeOut);
+ CopyMem (&DataEntry->Data, &Count, sizeof (UINT32));
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ FormCallback->Callback (
+ FormCallback,
+ 0xFFFF,
+ (EFI_IFR_DATA_ARRAY *) PageData,
+ NULL
+ );
+ }
+ //
+ // Count down 1 second
+ //
+ FrontPageTimeOutValue--;
+
+ } else {
+ ASSERT (!EFI_ERROR (Status));
+ PageData->EntryCount = 0;
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ FormCallback->Callback (
+ FormCallback,
+ 0xFFFE,
+ (EFI_IFR_DATA_ARRAY *) PageData,
+ NULL
+ );
+ }
+
+ FrontPageTimeOutValue = 0xFFFF;
+ }
+ } else {
+ //
+ // Wait for user's selection, no auto boot
+ //
+ Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
+ }
+ } while (Status == EFI_TIMEOUT);
+
+ if (gFirstIn) {
+ gFirstIn = FALSE;
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ DisableQuietBoot ();
+ }
+
+ if (Status == EFI_TIMEOUT) {
+ Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ } else {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ //
+ // if we encounter error, continue to read another key in.
+ //
+ if (EFI_ERROR (Status)) {
+ ControlFlag = CfReadKey;
+ continue;
+ }
+ }
+
+ switch (Key.UnicodeChar) {
+ case CHAR_CARRIAGE_RETURN:
+ Selection = MenuOption;
+ ScreenOperation = UiSelect;
+ gDirection = 0;
+ break;
+
+ //
+ // We will push the adjustment of these numeric values directly to the input handler
+ //
+ case '+':
+ case '-':
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+
+ if (Key.UnicodeChar == '+') {
+ gDirection = SCAN_RIGHT;
+ } else {
+ gDirection = SCAN_LEFT;
+ }
+
+ Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, NULL, &OptionString);
+ }
+ break;
+
+ case '^':
+ ScreenOperation = UiUp;
+ break;
+
+ case 'V':
+ case 'v':
+ ScreenOperation = UiDown;
+ break;
+
+ case ' ':
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ if (SubMenu) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !(MenuOption->ThisTag->GrayOut)) {
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+ gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
+ Selection = MenuOption;
+ ScreenOperation = UiSelect;
+ }
+ }
+ }
+ break;
+
+ case CHAR_NULL:
+ if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
+ ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
+ ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
+ ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
+ ) {
+ //
+ // If the function key has been disabled, just ignore the key.
+ //
+ } else {
+ for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
+ if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
+ if ((Key.ScanCode == SCAN_F9) || (Key.ScanCode == SCAN_F10)) {
+ if (SubMenu) {
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
+ }
+ } else {
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
+ }
+ }
+ }
+ }
+ break;
+ }
+ break;
+
+ case CfScreenOperation:
+ IfrBinary = gBinaryDataHead;
+
+ //
+ // Advance to the Ifr we are using
+ //
+ for (Index = 0; Index < gActiveIfr; Index++) {
+ IfrBinary = IfrBinary->Next;
+ }
+
+ if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
+ //
+ // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
+ // ignore the selection and go back to reading keys.
+ //
+ if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+ //
+ // if there is nothing logical to place a cursor on, just move on to wait for a key.
+ //
+ for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
+ NextMenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (!(NextMenuOption->ThisTag->GrayOut) && (NextMenuOption->ThisTag->Operand != EFI_IFR_SUBTITLE_OP)) {
+ break;
+ }
+ }
+
+ if (Link == &Menu) {
+ ControlFlag = CfPrepareToReadKey;
+ break;
+ }
+ }
+
+ for (Index = 0;
+ Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
+ Index++
+ ) {
+ if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
+ ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
+ }
+ }
+
+ break;
+
+ case CfUiPrevious:
+ ControlFlag = CfCheckSelection;
+ //
+ // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
+ //
+ if (MenuOption != NULL) {
+ if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
+ Selection = NULL;
+ Repaint = TRUE;
+ break;
+ }
+ }
+
+ if (IsListEmpty (&gMenuList)) {
+ Selection = NULL;
+ if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ }
+ break;
+ }
+
+ gLastOpr = TRUE;
+
+ while (gMenuRefreshHead != NULL) {
+ OldMenuRefreshEntry = gMenuRefreshHead->Next;
+
+ FreePool (gMenuRefreshHead);
+
+ gMenuRefreshHead = OldMenuRefreshEntry;
+ }
+ //
+ // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag
+ //
+ if (SubMenu) {
+ UiRemoveMenuListEntry (MenuOption, &Selection);
+ Selection->Previous = TRUE;
+ UiFreeMenu ();
+ UiInitMenu ();
+ }
+
+ gActiveIfr = Selection->IfrNumber;
+ return Selection;
+
+ case CfUiSelect:
+ ControlFlag = CfCheckSelection;
+
+ ExtractRequestedNvMap (FileFormTags, MenuOption->ThisTag->VariableNumber, &VariableDefinition);
+
+ if (SubMenu) {
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP &&
+ !(MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE)) ||
+ (MenuOption->ThisTag->GrayOut) ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ Selection = NULL;
+ break;
+ }
+
+ NewLine = TRUE;
+ UpdateKeyHelp (MenuOption, TRUE);
+ Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, PageData, &OptionString);
+
+ if (EFI_ERROR (Status)) {
+ Selection = NULL;
+ Repaint = TRUE;
+ break;
+ }
+
+ if (OptionString != NULL) {
+ PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
+ }
+
+ if (MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ Selection = MenuOption;
+ }
+
+ if (Selection == NULL) {
+ break;
+ }
+
+ Location = (UINT8 *) &PageData->EntryCount;
+
+ //
+ // If not a goto, dump single piece of data, otherwise dump everything
+ //
+ if (Selection->ThisTag->Operand == EFI_IFR_REF_OP) {
+ //
+ // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
+ //
+ if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
+ Selection = NULL;
+ Repaint = TRUE;
+ break;
+ }
+
+ UiAddMenuListEntry (Selection);
+ gPriorMenuEntry = 0;
+
+ //
+ // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious
+ //
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+ UiMenuList->FormerEntryNumber = MenuOption->EntryNumber;
+
+ gLastOpr = FALSE;
+
+ //
+ // Rewind to the beginning of the menu
+ //
+ for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink)
+ ;
+
+ //
+ // Get Total Count of Menu entries
+ //
+ for (Count = 1; NewPos->ForwardLink != &Menu; NewPos = NewPos->ForwardLink) {
+ Count++;
+ }
+ //
+ // Rewind to the beginning of the menu
+ //
+ for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink)
+ ;
+
+ //
+ // Copy the number of entries being described to the PageData location
+ //
+ CopyMem (&Location[0], &Count, sizeof (UINT32));
+
+ for (Index = 4; NewPos->ForwardLink != &Menu; Index = Index + MenuOption->ThisTag->StorageWidth + 2) {
+
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ Location[Index] = MenuOption->ThisTag->Operand;
+ Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4);
+ CopyMem (
+ &Location[Index + 4],
+ &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart],
+ MenuOption->ThisTag->StorageWidth
+ );
+ NewPos = NewPos->ForwardLink;
+ }
+ } else {
+
+ gPriorMenuEntry = MenuOption->EntryNumber;
+
+ Count = 1;
+
+ //
+ // Copy the number of entries being described to the PageData location
+ //
+ CopyMem (&Location[0], &Count, sizeof (UINT32));
+
+ //
+ // Start at PageData[4] since the EntryCount is a UINT32
+ //
+ Index = 4;
+
+ //
+ // Copy data to destination
+ //
+ Location[Index] = MenuOption->ThisTag->Operand;
+ Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4);
+ CopyMem (
+ &Location[Index + 4],
+ &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart],
+ MenuOption->ThisTag->StorageWidth
+ );
+ }
+ }
+ break;
+
+ case CfUiReset:
+ ControlFlag = CfCheckSelection;
+ gLastOpr = FALSE;
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ break;
+ }
+ //
+ // If NV flag is up, prompt user
+ //
+ if (gNvUpdateRequired) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+ YesResponse = gYesResponse[0];
+ NoResponse = gNoResponse[0];
+
+ do {
+ CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
+ } while
+ (
+ (Key.ScanCode != SCAN_ESC) &&
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
+ );
+
+ //
+ // If the user hits the YesResponse key
+ //
+ if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
+ } else {
+ Repaint = TRUE;
+ NewLine = TRUE;
+ break;
+ }
+ }
+ //
+ // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
+ //
+ if (MenuOption != NULL) {
+ if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
+ Selection = NULL;
+ Repaint = TRUE;
+ NewLine = TRUE;
+ break;
+ }
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ if (SubMenu) {
+ UiFreeMenuList ();
+ gST->ConOut->ClearScreen (gST->ConOut);
+ return NULL;
+ }
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE);
+
+ if (IfrBinary->UnRegisterOnExit) {
+ Hii->RemovePack (Hii, MenuOption->Handle);
+ }
+
+ UiFreeMenu ();
+
+ //
+ // Clean up the allocated data buffers
+ //
+ FreeData (FileFormTagsHead, FormattedString, OptionString);
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ return NULL;
+
+ case CfUiLeft:
+ ControlFlag = CfCheckSelection;
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ if (MenuOption->Skip == 1) {
+ //
+ // In the tail of the Date/Time op-code set, go left.
+ //
+ NewPos = NewPos->BackLink;
+ } else {
+ //
+ // In the middle of the Data/Time op-code set, go left.
+ //
+ NextMenuOption = CR (NewPos->ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (NextMenuOption->Skip == 1) {
+ NewPos = NewPos->BackLink;
+ }
+ }
+ }
+ break;
+
+ case CfUiRight:
+ ControlFlag = CfCheckSelection;
+ if ((MenuOption->Skip == 0) &&
+ ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP))
+ ) {
+ //
+ // We are in the head or middle of the Date/Time op-code set, advance right.
+ //
+ NewPos = NewPos->ForwardLink;
+ }
+ break;
+
+ case CfUiUp:
+ ControlFlag = CfCheckSelection;
+
+ if (NewPos->BackLink != &Menu) {
+ NewLine = TRUE;
+ //
+ // Adjust Date/Time position before we advance forward.
+ //
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+
+ //
+ // Caution that we have already rewind to the top, don't go backward in this situation.
+ //
+ if (NewPos->BackLink != &Menu) {
+ NewPos = NewPos->BackLink;
+ }
+
+ PreviousMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ //
+ // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
+ // to be one that back to the previous set of op-codes, we need to advance to the sencond
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+ // checking can be done.
+ //
+ DataAndTimeLineNumberPad = AdjustDateAndTimePosition (TRUE, &NewPos);
+
+ if (SubMenu) {
+ //
+ // If the previous MenuOption contains a display-only op-code, skip to the next one
+ //
+ if (PreviousMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || PreviousMenuOption->ThisTag->GrayOut) {
+ //
+ // This is ok as long as not at the end of the list
+ //
+ if (NewPos->BackLink == &Menu) {
+ //
+ // If we are at the start of the list, then this list must start with a display only
+ // piece of data, so do not allow the backward motion
+ //
+ ScreenOperation = UiDown;
+
+ if (PreviousMenuOption->Row <= TopRow) {
+ if (TopOfScreen->BackLink != &Menu) {
+ TopOfScreen = TopOfScreen->BackLink;
+ Repaint = TRUE;
+ }
+ }
+
+ UpdateStatusBar (INPUT_ERROR, PreviousMenuOption->ThisTag->Flags, FALSE);
+ break;
+ }
+ }
+ }
+ //
+ // Check the previous menu entry to see if it was a zero-length advance. If it was,
+ // don't worry about a redraw.
+ //
+ if ((MenuOption->Row - PreviousMenuOption->Skip - DataAndTimeLineNumberPad < TopRow) ||
+ (PreviousMenuOption->Skip > MenuOption->Row)
+ ) {
+ do {
+ if (TopOfScreen->BackLink == &Menu) {
+ break;
+ }
+
+ Repaint = TRUE;
+
+ //
+ // Is the current top of screen a zero-advance op-code?
+ // If so, keep moving forward till we hit a >0 advance op-code
+ //
+ SavedMenuOption = CR (TopOfScreen->BackLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ TopOfScreen = TopOfScreen->BackLink;
+ } while (SavedMenuOption->Skip == 0);
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ }
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
+ } else {
+ if (SubMenu) {
+ SavedMenuOption = MenuOption;
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
+ //
+ // If we are at the end of the list and sitting on a text op, we need to more forward
+ //
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+
+ MenuOption = SavedMenuOption;
+ }
+ }
+ break;
+
+ case CfUiPageUp:
+ ControlFlag = CfCheckSelection;
+
+ SavedListEntry = NewPos;
+ Link = TopOfScreen;
+ for (Index = BottomRow; Index >= TopRow + 1; Index -= MenuOption->Skip) {
+ if (Link->BackLink == &Menu) {
+ TopOfScreen = Link;
+ Link = SavedListEntry;
+ MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+ Link = Link->BackLink;
+ MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ TopOfScreen = Link;
+ SavedListEntry = Link;
+ }
+
+ NewPos = Link;
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ // Don't do this when we are already in the first page.
+ //
+ if (Repaint) {
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ }
+ break;
+
+ case CfUiPageDown:
+ ControlFlag = CfCheckSelection;
+
+ SavedListEntry = NewPos;
+ Link = TopOfScreen;
+ NewPos = TopOfScreen;
+ for (Index = TopRow; Index <= BottomRow - 1; Index += MenuOption->Skip) {
+ if (NewPos->ForwardLink == &Menu) {
+ NewPos = SavedListEntry;
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ Link = TopOfScreen;
+ NewLine = FALSE;
+ Repaint = FALSE;
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ NewPos = NewPos->ForwardLink;
+ Link = NewPos;
+ }
+
+ TopOfScreen = Link;
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ // Don't do this when we are already in the last page.
+ //
+ if (Repaint) {
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ }
+ break;
+
+ case CfUiDown:
+ ControlFlag = CfCheckSelection;
+ //
+ // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
+ // to be one that progresses to the next set of op-codes, we need to advance to the last
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+ // checking can be done. The only other logic we need to introduce is that if a Date/Time
+ // op-code is the last entry in the menu, we need to rewind back to the first op-code of
+ // the Date/Time op-code.
+ //
+ DataAndTimeLineNumberPad = AdjustDateAndTimePosition (FALSE, &NewPos);
+
+ if (NewPos->ForwardLink != &Menu) {
+ NewLine = TRUE;
+ NewPos = NewPos->ForwardLink;
+ NextMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ if (SubMenu) {
+ //
+ // If the next MenuOption contains a display-only op-code, skip to the next one
+ // Also if the next MenuOption is date or time,
+ //
+ if (NextMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || NextMenuOption->ThisTag->GrayOut) {
+ //
+ // This is ok as long as not at the end of the list
+ //
+ if (NewPos == &Menu) {
+ //
+ // If we are at the end of the list, then this list must end with a display only
+ // piece of data, so do not allow the forward motion
+ //
+ UpdateStatusBar (INPUT_ERROR, NextMenuOption->ThisTag->Flags, FALSE);
+ NewPos = NewPos->BackLink;
+ ScreenOperation = UiUp;
+ break;
+ }
+ }
+ }
+ //
+ // An option might be multi-line, so we need to reflect that data in the overall skip value
+ //
+ UpdateOptionSkipLines (PageData, NextMenuOption, FileFormTagsHead, &OptionString, SkipValue);
+
+ if (NextMenuOption->Skip > 1) {
+ Temp = MenuOption->Row + MenuOption->Skip + NextMenuOption->Skip - 1;
+ } else {
+ Temp = MenuOption->Row + MenuOption->Skip + DataAndTimeLineNumberPad;
+ }
+ //
+ // If we are going to scroll
+ //
+ if (Temp > BottomRow) {
+ do {
+ //
+ // Is the current top of screen a zero-advance op-code?
+ // If so, keep moving forward till we hit a >0 advance op-code
+ //
+ SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ //
+ // If bottom op-code is more than one line or top op-code is more than one line
+ //
+ if ((NextMenuOption->Skip > 1) || (MenuOption->Skip > 1)) {
+ //
+ // Is the bottom op-code greater than or equal in size to the top op-code?
+ //
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
+ //
+ // Skip the top op-code
+ //
+ TopOfScreen = TopOfScreen->ForwardLink;
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
+
+ OldSkipValue = Difference;
+
+ SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ //
+ // If we have a remainder, skip that many more op-codes until we drain the remainder
+ //
+ for (;
+ Difference >= (INTN) SavedMenuOption->Skip;
+ Difference = Difference - (INTN) SavedMenuOption->Skip
+ ) {
+ //
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it
+ //
+ TopOfScreen = TopOfScreen->ForwardLink;
+ SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (Difference < (INTN) SavedMenuOption->Skip) {
+ Difference = SavedMenuOption->Skip - Difference - 1;
+ break;
+ } else {
+ if (Difference == (INTN) SavedMenuOption->Skip) {
+ TopOfScreen = TopOfScreen->ForwardLink;
+ SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ Difference = SavedMenuOption->Skip - Difference;
+ break;
+ }
+ }
+ }
+ //
+ // Since we will act on this op-code in the next routine, and increment the
+ // SkipValue, set the skips to one less than what is required.
+ //
+ SkipValue = Difference - 1;
+
+ } else {
+ //
+ // Since we will act on this op-code in the next routine, and increment the
+ // SkipValue, set the skips to one less than what is required.
+ //
+ SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
+ }
+ } else {
+ if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
+ TopOfScreen = TopOfScreen->ForwardLink;
+ break;
+ } else {
+ SkipValue = OldSkipValue;
+ }
+ }
+ //
+ // If the op-code at the top of the screen is more than one line, let's not skip it yet
+ // Let's set a skip flag to smoothly scroll the top of the screen.
+ //
+ if (SavedMenuOption->Skip > 1) {
+ if (SavedMenuOption == NextMenuOption) {
+ SkipValue = 0;
+ } else {
+ SkipValue++;
+ }
+ } else {
+ SkipValue = 0;
+ TopOfScreen = TopOfScreen->ForwardLink;
+ }
+ } while (SavedMenuOption->Skip == 0);
+
+ Repaint = TRUE;
+ OldSkipValue = SkipValue;
+ }
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
+
+ } else {
+ if (SubMenu) {
+ SavedMenuOption = MenuOption;
+ MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
+ //
+ // If we are at the end of the list and sitting on a text op, we need to more forward
+ //
+ ScreenOperation = UiUp;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+
+ MenuOption = SavedMenuOption;
+ //
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
+ //
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ }
+ }
+ break;
+
+ case CfUiSave:
+ ControlFlag = CfCheckSelection;
+ //
+ // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data.
+ //
+ if (MenuOption != NULL) {
+ if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
+ Selection = NULL;
+ Repaint = TRUE;
+ break;
+ }
+ }
+ //
+ // If callbacks are active, and the callback has a Write method, try to use it
+ //
+ if (FileFormTags->VariableDefinitions->VariableName == NULL) {
+ if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
+ Status = FormCallback->NvWrite (
+ FormCallback,
+ (CHAR16 *) L"Setup",
+ &FileFormTags->FormTags.Tags[0].GuidValue,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) VariableDefinition->NvRamMap,
+ &gResetRequired
+ );
+
+ } else {
+ Status = gRT->SetVariable (
+ (CHAR16 *) L"Setup",
+ &FileFormTags->FormTags.Tags[0].GuidValue,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ }
+ } else {
+ VariableDefinition = FileFormTags->VariableDefinitions;
+
+ for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
+ if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
+ Status = FormCallback->NvWrite (
+ FormCallback,
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) VariableDefinition->NvRamMap,
+ &gResetRequired
+ );
+
+ } else {
+ Status = gRT->SetVariable (
+ VariableDefinition->VariableName,
+ &VariableDefinition->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ VariableDefinition->VariableSize,
+ (VOID *) VariableDefinition->NvRamMap
+ );
+ }
+ }
+ }
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE);
+ break;
+
+ case CfUiDefault:
+ ControlFlag = CfCheckSelection;
+
+ NvMapListHead = NULL;
+
+ Status = Hii->GetDefaultImage (Hii, MenuOption->Handle, EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
+
+ if (!EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (NULL != NvMapListHead);
+
+ NvMapListNode = NvMapListHead;
+
+ while (NULL != NvMapListNode) {
+ if (FileFormTags->VariableDefinitions->VariableId == NvMapListNode->VariablePack->VariableId) {
+ NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
+ NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
+ break;
+ }
+ NvMapListNode = NvMapListNode->NextVariablePack;
+ }
+
+ //
+ // Free the buffer that was allocated.
+ //
+ FreePool (FileFormTags->VariableDefinitions->NvRamMap);
+ FreePool (FileFormTags->VariableDefinitions->FakeNvRamMap);
+
+ //
+ // Allocate, copy the NvRamMap.
+ //
+ FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize - FileFormTags->VariableDefinitions->VariableSize);
+ FileFormTags->VariableDefinitions->VariableSize = (UINT16) NvMapSize;
+ FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize + FileFormTags->VariableDefinitions->VariableSize);
+
+ FileFormTags->VariableDefinitions->NvRamMap = AllocateZeroPool (FileFormTags->VariableDefinitions->VariableSize);
+ ASSERT (FileFormTags->VariableDefinitions->NvRamMap != NULL);
+
+ FileFormTags->VariableDefinitions->FakeNvRamMap = AllocateZeroPool (NvMapSize + FileFormTags->VariableDefinitions->VariableFakeSize);
+ ASSERT (FileFormTags->VariableDefinitions->FakeNvRamMap != NULL);
+
+ CopyMem (FileFormTags->VariableDefinitions->NvRamMap, NvMap, NvMapSize);
+ FreePool (NvMapListHead);
+ }
+
+ UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, TRUE);
+ Repaint = TRUE;
+ //
+ // After the repaint operation, we should refresh the highlight.
+ //
+ NewLine = TRUE;
+ break;
+
+ case CfUiNoOperation:
+ ControlFlag = CfCheckSelection;
+ break;
+
+ case CfExit:
+ while (gMenuRefreshHead != NULL) {
+ OldMenuRefreshEntry = gMenuRefreshHead->Next;
+
+ FreePool (gMenuRefreshHead);
+
+ gMenuRefreshHead = OldMenuRefreshEntry;
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ gST->ConOut->OutputString (gST->ConOut, (CHAR16 *) L"\n");
+
+ gActiveIfr = MenuOption->IfrNumber;
+ return Selection;
+
+ default:
+ break;
+ }
+ }
+}
+
+BOOLEAN
+ValueIsScroll (
+ IN BOOLEAN Direction,
+ IN LIST_ENTRY *CurrentPos
+ )
+/*++
+
+Routine Description:
+ Determine if the menu is the last menu that can be selected.
+
+Arguments:
+ Direction - the scroll direction. False is down. True is up.
+
+Returns:
+ FALSE -- the menu isn't the last menu that can be selected.
+ TRUE -- the menu is the last menu that can be selected.
+--*/
+{
+ LIST_ENTRY *Temp;
+ UI_MENU_OPTION *MenuOption;
+ MenuOption = NULL;
+
+ Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
+
+ if (Temp == &Menu) {
+ return TRUE;
+ }
+
+ for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
+ MenuOption = CR (Temp, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ if (!(MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+UINTN
+AdjustDateAndTimePosition (
+ IN BOOLEAN DirectionUp,
+ IN LIST_ENTRY **CurrentPosition
+ )
+/*++
+Routine Description:
+ Adjust Data and Time tag position accordingly.
+ Data format : [01/02/2004] [11:22:33]
+ Line number : 0 0 1 0 0 1
+
+Arguments:
+ Direction - the up or down direction. False is down. True is up.
+ CurrentPos - Current position.
+
+Returns:
+ Return line number to pad. It is possible that we stand on a zero-advance
+ data or time opcode, so pad one line when we judge if we are going to scroll outside.
+--*/
+{
+ UINTN Count;
+ LIST_ENTRY *NewPosition;
+ UI_MENU_OPTION *MenuOption;
+ UINTN PadLineNumber;
+
+ PadLineNumber = 0;
+ NewPosition = *CurrentPosition;
+ MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ //
+ // Calculate the distance from current position to the last Date/Time op-code.
+ //
+ Count = 0;
+ while (MenuOption->ThisTag->NumberOfLines == 0) {
+ Count++;
+ NewPosition = NewPosition->ForwardLink;
+ MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
+ PadLineNumber = 1;
+ }
+
+ NewPosition = *CurrentPosition;
+ if (DirectionUp) {
+ //
+ // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
+ // to be one that back to the previous set of op-codes, we need to advance to the first
+ // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate
+ // checking can be done.
+ //
+ while (Count++ < 2) {
+ NewPosition = NewPosition->BackLink;
+ }
+ } else {
+ //
+ // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
+ // to be one that progresses to the next set of op-codes, we need to advance to the last
+ // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate
+ // checking can be done.
+ //
+ while (Count-- > 0) {
+ NewPosition = NewPosition->ForwardLink;
+ }
+ }
+
+ *CurrentPosition = NewPosition;
+ }
+
+ return PadLineNumber;
+}
diff --git a/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.h b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.h
new file mode 100644
index 0000000000..78a51d08c8
--- /dev/null
+++ b/IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Ui.h
@@ -0,0 +1,440 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Ui.h
+
+Abstract:
+
+ Head file UI
+
+Revision History
+
+--*/
+
+#ifndef _UI_H
+#define _UI_H
+
+//
+// Include common header file for this module.
+//
+#include "CommonHeader.h"
+
+//
+// Globals
+//
+#define REGULAR_NUMERIC 0
+#define TIME_NUMERIC 1
+#define DATE_NUMERIC 2
+
+typedef enum {
+ UiNoOperation,
+ UiDefault,
+ UiSelect,
+ UiUp,
+ UiDown,
+ UiLeft,
+ UiRight,
+ UiReset,
+ UiSave,
+ UiPrevious,
+ UiPageUp,
+ UiPageDown,
+ UiMaxOperation
+} UI_SCREEN_OPERATION;
+
+typedef enum {
+ CfInitialization,
+ CfCheckSelection,
+ CfRepaint,
+ CfRefreshHighLight,
+ CfUpdateHelpString,
+ CfPrepareToReadKey,
+ CfReadKey,
+ CfScreenOperation,
+ CfUiPrevious,
+ CfUiSelect,
+ CfUiReset,
+ CfUiLeft,
+ CfUiRight,
+ CfUiUp,
+ CfUiPageUp,
+ CfUiPageDown,
+ CfUiDown,
+ CfUiSave,
+ CfUiDefault,
+ CfUiNoOperation,
+ CfExit,
+ CfMaxControlFlag
+} UI_CONTROL_FLAG;
+
+#define UI_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')
+#define UI_MENU_LIST_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINTN Row;
+ UINTN Col;
+ UINTN OptCol;
+ CHAR16 *Description;
+ UINTN Skip;
+
+ UINTN IfrNumber;
+ VOID *FormBinary;
+ EFI_HII_HANDLE Handle;
+ EFI_TAG *Tags;
+ UINTN TagIndex;
+ EFI_TAG *ThisTag;
+ UINT16 FormId;
+ BOOLEAN Previous;
+ UINT16 EntryNumber;
+ UINT16 Consistency;
+ BOOLEAN GrayOut;
+} UI_MENU_OPTION;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY MenuLink;
+
+ UI_MENU_OPTION Selection;
+ UINTN FormerEntryNumber;
+} UI_MENU_LIST;
+
+typedef struct _MENU_REFRESH_ENTRY {
+ struct _MENU_REFRESH_ENTRY *Next;
+ EFI_FILE_FORM_TAGS *FileFormTagsHead;
+ UINTN CurrentColumn;
+ UINTN CurrentRow;
+ UINTN CurrentAttribute;
+ UI_MENU_OPTION *MenuOption; // Describes the entry needing an update
+} MENU_REFRESH_ENTRY;
+
+typedef struct {
+ UINT16 ScanCode;
+ UI_SCREEN_OPERATION ScreenOperation;
+} SCAN_CODE_TO_SCREEN_OPERATION;
+
+typedef struct {
+ UI_SCREEN_OPERATION ScreenOperation;
+ UI_CONTROL_FLAG ControlFlag;
+} SCREEN_OPERATION_T0_CONTROL_FLAG;
+
+LIST_ENTRY Menu;
+LIST_ENTRY gMenuList;
+MENU_REFRESH_ENTRY *gMenuRefreshHead;
+
+INTN gEntryNumber;
+BOOLEAN gLastOpr;
+//
+// Global Functions
+//
+VOID
+UiInitMenu (
+ VOID
+ )
+;
+
+VOID
+UiInitMenuList (
+ VOID
+ )
+;
+
+VOID
+UiRemoveMenuListEntry (
+ IN UI_MENU_OPTION *Selection,
+ OUT UI_MENU_OPTION **PreviousSelection
+ )
+;
+
+VOID
+UiFreeMenuList (
+ VOID
+ )
+;
+
+VOID
+UiAddMenuListEntry (
+ IN UI_MENU_OPTION *Selection
+ )
+;
+
+VOID
+UiFreeMenu (
+ VOID
+ )
+;
+
+VOID
+UiAddMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_TAG *Tag,
+ IN VOID *FormBinary,
+ IN UINTN IfrNumber
+ )
+;
+
+VOID
+UiAddSubMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_TAG *Tag,
+ IN UINTN TagIndex,
+ IN UINT16 FormId,
+ IN UINT16 MenuItemCount
+ )
+;
+
+UI_MENU_OPTION *
+UiDisplayMenu (
+ IN BOOLEAN SubMenu,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ OUT EFI_IFR_DATA_ARRAY *PageData
+ )
+;
+
+VOID
+InitPage (
+ VOID
+ )
+;
+
+UI_MENU_OPTION *
+SetupBrowser (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Callback,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+;
+
+
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+;
+
+EFI_STATUS
+UiWaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+;
+
+VOID
+CreatePopUp (
+ IN UINTN ScreenWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 *ArrayOfStrings,
+ ...
+ )
+;
+
+EFI_STATUS
+ReadString (
+ IN UI_MENU_OPTION *MenuOption,
+ OUT CHAR16 *StringPtr
+ )
+;
+
+EFI_STATUS
+ReadPassword (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN PromptForPassword,
+ IN EFI_TAG *Tag,
+ IN EFI_IFR_DATA_ARRAY *PageData,
+ IN BOOLEAN SecondEntry,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ OUT CHAR16 *StringPtr
+ )
+;
+
+VOID
+EncodePassword (
+ IN CHAR16 *Password,
+ IN UINT8 MaxSize
+ )
+;
+
+EFI_STATUS
+GetSelectionInputPopUp (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_TAG *Tag,
+ IN UINTN ValueCount,
+ OUT UINT16 *Value,
+ OUT UINT16 *KeyValue
+ )
+;
+
+EFI_STATUS
+GetSelectionInputLeftRight (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_TAG *Tag,
+ IN UINTN ValueCount,
+ OUT UINT16 *Value
+ )
+;
+
+EFI_STATUS
+GetNumericInput (
+ IN UI_MENU_OPTION *MenuOption,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN BOOLEAN ManualInput,
+ IN EFI_TAG *Tag,
+ IN UINTN NumericType,
+ OUT UINT16 *Value
+ )
+;
+
+VOID
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN UINT8 Flags,
+ IN BOOLEAN State
+ )
+;
+
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN EFI_IFR_DATA_ARRAY *PageData,
+ OUT CHAR16 **OptionString
+ )
+;
+
+VOID
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ IN UINTN RowCount
+ )
+;
+
+VOID
+UpdateKeyHelp (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Selected
+ )
+;
+
+BOOLEAN
+ValueIsNotValid (
+ IN BOOLEAN Complex,
+ IN UINT16 Value,
+ IN EFI_TAG *Tag,
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN STRING_REF *PopUp
+ )
+;
+
+VOID
+FreeData (
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN CHAR16 *FormattedString,
+ IN CHAR16 *OptionString
+ )
+;
+
+VOID
+ClearLines (
+ UINTN LeftColumn,
+ UINTN RightColumn,
+ UINTN TopRow,
+ UINTN BottomRow,
+ UINTN TextAttribute
+ )
+;
+
+UINTN
+GetStringWidth (
+ CHAR16 *String
+ )
+;
+
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ )
+;
+
+UINT16
+GetWidth (
+ IN EFI_TAG *Tag,
+ IN EFI_HII_HANDLE Handle
+ )
+;
+
+VOID
+NewStrCat (
+ CHAR16 *Destination,
+ CHAR16 *Source
+ )
+;
+
+VOID
+IfrToFormTag (
+ IN UINT8 OpCode,
+ IN EFI_TAG *TargetTag,
+ IN VOID *FormData,
+ EFI_VARIABLE_DEFINITION *VariableDefinitionsHead
+ )
+;
+
+EFI_STATUS
+ExtractNvValue (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 VariableId,
+ IN UINT16 VariableSize,
+ IN UINT16 OffsetValue,
+ OUT VOID **Buffer
+ )
+;
+
+EFI_STATUS
+ExtractRequestedNvMap (
+ IN EFI_FILE_FORM_TAGS *FileFormTags,
+ IN UINT16 VariableId,
+ OUT EFI_VARIABLE_DEFINITION **VariableDefinition
+ )
+;
+
+BOOLEAN
+ValueIsScroll (
+ IN BOOLEAN Direction,
+ IN LIST_ENTRY *CurrentPos
+ )
+;
+
+UINTN
+AdjustDateAndTimePosition (
+ IN BOOLEAN DirectionUp,
+ IN LIST_ENTRY **CurrentPosition
+ )
+;
+
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ )
+;
+#endif // _UI_H